Removed #[non_exhaustive] from TlsMode and the wildcard _ arm in the
match tls_mode block in main.rs. Since setup_tls already rejects unknown
modes with bail!, the wildcard was unreachable dead code. Removing it
ensures the compiler catches future TlsMode variant additions. Added
defense-in-depth count mismatch check after the acceptor loop to catch
any silent listener/acceptor mismatch from zip truncation.
Remove unused log_rate_limit! and log_config_reload! macros,
format_event_fields() function, ProxyError::NotFound/BadRequest/
PayloadTooLarge/UpstreamTls variants, build_multi_domain_server_config(),
SniCertResolver struct, and dead test helper methods. Gate
AcmeTlsConfig::directory_url() and KvVisitor with #[cfg(test)].
Change build_upstream_uri to return Result<Uri, ()> so that URI parse
failures are properly handled instead of silently dropping the query
string and unwrapping a fallback. On parse failure, log a warning with
the malformed URI and return 502 Bad Gateway to the client.
The rate limiter previously extracted client IP from the X-Forwarded-For
header first, falling back to ConnectInfo. This allowed attackers to bypass
rate limits by sending spoofed X-Forwarded-For headers. Per ADR-025, the
rate limiter now uses ConnectInfo<SocketAddr> exclusively and rejects
requests with 429 when ConnectInfo is absent.
Delete the duplicate RawConfig struct and collect_sites helper from cli.rs.
Rewrite load_config to use FullConfig::parse + into_static_and_dynamic,
eliminating the redundant manual construction path.
Dual MIT/Apache-2.0 license, public-facing README with quick start
and config reference, step-by-step deploy/README.md for Docker and
systemd setups, and AGENTS.md for LLM-assisted development.
Architecture updates based on gaps discovered during live deployment testing:
- ADR-023: HTTP/2 client-facing support via ALPN-based protocol detection.
The spec previously said HTTP/2 was out of scope, but the deployment
revealed that modern browsers negotiate HTTP/2 via ALPN. The proxy now
correctly detects the negotiated ALPN protocol and uses the appropriate
HTTP server builder (http2::Builder for h2, auto::Builder for http/1.1).
Upstream connections remain HTTP/1.1. Host resolution now falls back to
URI host for HTTP/2 :authority pseudo-headers.
- ADR-024: ANSI-disabled logging. All tracing-subscriber layers now use
with_ansi(false) to prevent ANSI escape codes in log output, which broke
fail2ban regex matching in Docker deployments. Also documents the fail2ban
regex anchor fix (^RATE_LIMIT → RATE_LIMIT).
Bug fixes found by architecture review:
- Fix missing ALPN protocols in manual TLS mode. build_manual_server_config
and build_multi_domain_server_config did not set alpn_protocols, meaning
manual TLS mode could not support HTTP/2. Added h2 and http/1.1 ALPN
entries to both functions (acme-tls/1 only in ACME mode).
- Fix missing with_ansi(false) in JSON log format. The init_json function
with file output did not disable ANSI on stdout or file layers, which would
break fail2ban in production JSON logging mode.
Other spec updates:
- All document statuses updated from draft to reviewed
- proxy.md: documented Server header removal, upstream HTTPS client,
two-phase timeout enforcement, HTTP/2 host resolution, connect timeout
- tls.md: documented ALPN configuration differing by mode (ACME vs manual)
- overview.md: added HTTP/2 client-facing support to scope, updated crate
deps (hyper-rustls, rustls-native-certs, hyper-util), clarified out-of-scope
- config.md: fixed http_port type (u16→u32) to match implementation, added
ANSI-disabled note for LoggingConfig
- operations.md: documented ANSI-disabled logging, fail2ban regex anchor
- open-questions.md: updated OQ-09 resolution (connect timeout fully
implemented), OQ-10 (C2 bug is fixed)
- Add with_ansi(false) to all tracing_subscriber fmt layers so log
output (both stdout and file) is plain text without escape codes.
This is critical for Docker deployments and fail2ban log parsing.
- Remove ^ anchor from fail2ban failregex since log lines have a
timestamp/level prefix before RATE_LIMIT.
Two changes to properly support HTTP/2 clients:
1. server.rs: Detect ALPN protocol after TLS handshake and use
hyper::server::conn::http2::Builder for H2 connections instead
of the auto::Builder which failed to detect HTTP/2 over TLS.
The auto::Builder's ReadVersion mechanism doesn't work reliably
with tokio-rustls TlsStreams. For H1 connections, continue using
auto::Builder with upgrade support.
2. handler.rs: Fallback to URI host when Host header is missing.
In HTTP/2, the host is conveyed via :authority pseudo-header which
hyper represents as the URI host, not a Host header.
All #[allow(dead_code)] annotations on now-used items have been removed
(acceptor.rs, acme.rs, config.rs, static_config.rs). #[non_exhaustive]
added to TlsMode, ProxyError, AdminSocketError, and ValidationError
with wildcard match arms in main.rs for the non-exhaustive enums.