diff --git a/docs/superpowers/specs/2026-08-21-byod-wifi-portal-hardening-design.md b/docs/superpowers/specs/2026-08-21-byod-wifi-portal-hardening-design.md index 759bd18..f29ab6b 100644 --- a/docs/superpowers/specs/2026-08-21-byod-wifi-portal-hardening-design.md +++ b/docs/superpowers/specs/2026-08-21-byod-wifi-portal-hardening-design.md @@ -137,6 +137,20 @@ is the proxy", and the second is surfaced as a health line on the Wi-Fi Devices page. The failure becomes one glance to diagnose instead of a mystery. This is also the single most important thing to verify against the live controller. +**Known blind spot in that detection** (found during implementation, 2026-08-21). +`proxy_untrusted` is inferred from `X-Forwarded-For` being present while +`$request->ip()` still equals the raw `REMOTE_ADDR` — that is, the header arrived +but `TrustProxies` did not apply it. It therefore does NOT catch a Traefik +misconfiguration that sends no forwarded header at all: that degrades to +`no_client`, which reads as "your device is not on the network" rather than "this +is broken, tell IT". + +So `proxy_untrusted` is a useful signal but **not a sufficient outage alarm**. The +hardware validation step must confirm the true client IP actually arrives, rather +than confirming that the misconfiguration alarm is quiet — a quiet alarm is +exactly what the blind spot produces. Plan 2's health line should read the +resolved IP itself and say what it is, not merely report a reason code. + ### MAC randomization Normally stable per SSID, so it does not break the design. When it does rotate,