You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit a654e33
Browse filesBrowse the repository at this point in the historyBrowse files
Three loose ends the Wave-3 agents flagged:
1. Android net/Api.kt referenced GET /v1/proof-pairing/sessions/:id/public
as an optional unauthenticated freshness read, but the endpoint did
not exist server-side. Land it. New getSessionPublicMinimal in the
service queries by id alone (no tenant filter — safe because the
returned shape carries no PII and no tenant identifier), uniformly
404s every rejection class for A-25 enumeration safety, pads to
LATENCY_FLOOR_MS for A-26, and is per-IP rate-limited at 30/min.
Three new request-level tests added (happy path, 404, no auth
required); 260/260 tests pass.
2. clientMeta short-key compression. The Android prover packs the proof
into CBOR with short keys (av/pl/md/ms/pi) to fit the 1500-byte QR
ceiling, the desktop forwards the raw scan as clientMeta.rawScan,
so server-side decoders need the short-key map. Documented in
docs/api_contract.md under POST /submit.
3. WebView process isolation. ADR-0010 originally said the WebView runs
in android:process=':prover'. The W3 prover (WebViewMobileProver)
lives inline in the main process because the IPC plumbing between
MainActivity and a separate ProverActivity is its own day of work.
Rewrote the manifest comment + the ADR paragraph to reflect what
actually ships (inline, in main process, with CSP + asset
hash-pinning + Android process sandboxing for defense-in-depth) and
what's deferred (the :prover process + Messenger/AIDL binder).
No code change — purely truthful docs.
Full test sweep: typecheck clean, 260/260 backend tests, Docusaurus
build green.
Copy file name to clipboardExpand all lines: docs/api_contract.md
+14-1Lines changed: 14 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -137,6 +137,7 @@ Cross-device verification flow: a desktop opens a session, a phone scans the QR
137
137
|`POST`|`/v1/proof-pairing/sessions/:id/submit`|`proof_pairing:claim`| Desktop submits the proof + public signals it scanned from the phone. Body: `{ did, proof, publicSignals, clientMeta? }`. Returns `{ session, tokens }`. |
138
138
|`GET`|`/v1/proof-pairing/sessions/:id/stream`|`proof_pairing:create` + `session_bind` cookie | Server-Sent Events. Events: `session_created`, `session_bound`, `session_expired`, `session_error`. Connection closes after a terminal event. |
139
139
|`GET`|`/v1/proof-pairing/sessions/:id`|`proof_pairing:create` + `session_bind` cookie | Polling fallback for clients without `EventSource`. |
140
+
|`GET`|`/v1/proof-pairing/sessions/:id/public`| none (per-IP rate-limited 30/min) | Unauthenticated freshness read. Returns only `{ id, state, expiresAt }` so the Android app can short-circuit a ceremony after a stale QR was scanned. Uniform `404 pairing_session_not_found` for every rejection class (A-25). Cache-Control: no-store. |
**`clientMeta.rawScan` short-key schema.** The Android app encodes the proof QR as `gzip(cbor({ s, p, ps, d, m }))` to fit under the 1500-byte QR-capacity ceiling (ADR-0009 §5). The desktop relays the raw scan string into `clientMeta.rawScan` unchanged; backend audit + analytics decoders need to know the field-shortening map:
Decoded forms are byte-equal to the long-keyed JSON above; the desktop's submit handler reconstructs the long-keyed body before posting if it needs to call `/submit` itself, so server-side handlers can rely on the documented long-keyed shape and treat `clientMeta.rawScan` as an opaque audit token.
0 commit comments