HTTP fallback leg (docs/19): e2e scenario 13 + docs
- e2e.py: scenario 13 (http fallback) — drives a full turn over the HTTP leg (health + POST /v1/frame + SSE /v1/events, no WS) and asserts the user echo lands on the SSE stream in < 1.5 s. - ws_probe.py --http: prints '== user echo in X.XXs' (the docs/19 sendable-in-fallback timing assertion) alongside the existing health/POST/SSE output; same assertion flags as the WS leg. - docs: 19 status flipped to implemented; 09-pairing-security §9.4 cross-reference (second door, same lock: token + device allowlist, 64 KiB cap, rate limit, optional TLS, unauthenticated /v1/health); 13-testing manual scenario 15 + automated pointers.
This commit is contained in:
1 parent
7f936fa596
commit
2349a95dd4
5 files changed
+61
-2
No files matched your search
@@ -60,6 +60,14 @@ security principal (the token is).
|
||||
- **Reverse proxy / tunnel** (Caddy, Cloudflare Tunnel, ngrok): terminate TLS
|
||||
at the edge, forward WS to `127.0.0.1:8790`.
|
||||
- **Public bind** (`0.0.0.0`) + WSS + strong token — last resort.
|
||||
- **HTTP fallback leg (docs/19):** the gateway also serves the same frames
|
||||
over plain HTTP (`ANDROID_HTTP_PORT`, default 8791) for the app's
|
||||
fallback transport. It is a *second door with the same lock*: the same
|
||||
Bearer token (constant-time `verify_token`) + the same device allowlist
|
||||
(`X-Iris-Device`), the same 64 KiB body cap and per-device rate limit as
|
||||
the WS. Optional TLS via `ANDROID_HTTP_CERT` / `ANDROID_HTTP_KEY`.
|
||||
`GET /v1/health` is unauthenticated by design (liveness only — it must
|
||||
not reflect tokens, device ids, or versions).
|
||||
- The app stores the server URL + (for self-signed) the pinned cert fingerprint
|
||||
in secure storage.
|
||||
|
||||
|
||||
@@ -131,6 +131,15 @@ adb logcat -d > /tmp/logcat.txt
|
||||
entries drop out); tap a row → the command is sent and the drawer closes;
|
||||
type an unknown command → the drawer closes (the raw text can still be
|
||||
sent; hermes answers with its unknown-command reply).
|
||||
15. **HTTP fallback (docs/19):** with the WS port unreachable (e.g. the
|
||||
gateway bound WS to a dead port, or a firewall dropping 8790 but not
|
||||
8791), the app stays sendable: the status pill shows "connected · http"
|
||||
(green), a sent message echoes back within ~1 s and the agent reply
|
||||
streams in over SSE; the attach button is disabled (media needs the
|
||||
live WS). When the WS comes back the pill returns to "connected" and
|
||||
media works again. Automated: `e2e.py` scenario 13 (health +
|
||||
`POST /v1/frame` + SSE turn, user-echo < 1.5 s) and
|
||||
`ws_probe.py --http` (same assertion flags as the WS leg).
|
||||
|
||||
## 13.5 Debugging tips
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@ by the gateway. When the WS is down (flaky network, NAT timeout, app just
|
||||
relaunched), the app **sends over `POST` and receives over SSE** instead of
|
||||
waiting 2–20 s for a WS redial.
|
||||
|
||||
Status: **design (proposed, not built)**. Complements — does not replace —
|
||||
Status: **implemented** (gateway leg: `gateway-plugin/http_server.py`; app
|
||||
leg: `app/shared/src/commonMain/kotlin/iris/net/HttpGateway.kt` +
|
||||
`GatewayClient.State.HttpFallback`). Complements — does not replace —
|
||||
`04-wire-protocol.md` (frames), `08-push.md` (outbox/sync/push), and
|
||||
`09-pairing-security.md` (auth model).
|
||||
|
||||
|
||||
Reference in new issue
Block a user