- _mockTokenServer now reads and captures the request body instead of
draining it — Completer type updated to ({HttpRequest, String rawBody})
- Two new tests: assert that url, method, nonce are present in the
/auth/get-token request body; verify POST requests carry method=POST
48/48 tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each request to a gated endpoint now triggers a fresh FIDO2 assertion.
Challenge = SHA256(url|method|nonce) — bound to the specific resource.
The self-contained assertion bundle lets the server verify independently
without calling back to the phone.
- fido2_ops.dart: GetAssertionResult gains clientDataJson; getAssertion
accepts optional challenge override
- proxy_service.dart: _handleAuthGetToken accepts {url,method,nonce},
derives challenge, runs card assertion, returns b64url bundle
- filter_proxy.dart: _getAuthToken(uri, method) generates nonce and
passes binding fields to Component 2
- component3/phone.go: stateless GetTokenForRequest(url, method) —
no session caching, no expiry, one card touch per request
- component3/proxy.go: use GetTokenForRequest
- component3/main.go: remove --user flag (Component 2 picks enrolled user)
- k_server_app.py: _verify_assertion_token() — verifies path+method
match, challenge claim, and ECDSA-P256 signature; accepts both
legacy X-Proxy-Token and new Bearer assertion tokens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
proxy_service.dart: _handleConnect gates on hasAnyActiveSession() (407 if
no active session), then connects directly to the upstream external target
(host:port from Host header), detaches the socket, and pipes bytes
bidirectionally. k_server is not involved in CONNECT tunnels.
filter_proxy_test.dart: replace _mockTcp() with _mockComp2Tcp() in the
CONNECT routing group so the mock speaks the full CONNECT handshake
(reads request headers, sends 200 Connection Established, pauses sub).
All 21 tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- k_phone/lib/filter_proxy.dart: Component 1 — raw-socket HTTP proxy with
gating filter; gated hosts relay to Component 2, others go direct
- k_phone/lib/session_manager.dart: add hasAnyActiveSession() for the
personal-device gated-proxy authorization model
- k_phone/test/filter_proxy_test.dart: full test suite for Component 1
- k_phone/test/enrollment_test.dart: full test suite for EnrollmentDb
- k_phone/integration_test/registration_login_test.dart: emulator integration test
- Misc k_phone lib fixes (ctaphid_channel, fido2_ops, proxy_service, main,
enrollment_db, k_server_client) and pubspec/Gradle updates
- CLAUDE.md + Workplan.md: document Component 1, k_phone module map,
gated terminology (replacing "allowlist"), pending CONNECT handler in
Component 2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>