Commit 8e39425
Pulkit Pareek
dashboard: three-QR signup ceremony demo at /demo/registration
End-user-visible counterpart to the ADR 0023 backend. The operator
opens the route, types a name + email, clicks "Open session & mint
QR1", and the page walks through three QR steps:
1. QR1 ("Pair your phone") — encodes the pair-step deeplink. A
phone scanning the QR (or, in this demo, the simulator panel)
POSTs to /v1/registrations/pair-device with the code + a
hardware fingerprint. Server flips state to awaiting_commitment
and mints the enroll_code.
2. QR2 ("Submit your biometric commitment") — the phone captures
the biometric locally (mobile/biometric/ pipeline), computes
the Poseidon commitment + DID, scans QR2 to POST them to
/v1/registrations/submit-commitment. State flips to
awaiting_verification; server mints verify_code + a 128-bit
challenge_nonce baked into QR3's deeplink.
3. QR3 ("Verify and create account") — phone re-captures the
biometric, produces a Groth16 proof, scans QR3 to POST to
/v1/registrations/complete. Server checks the challenge_nonce
matches, asserts publicSignals[0] equals the stored commitment,
verifies the proof off-chain, creates the tenant_user.
The biometric never crosses a wire. Only the commitment (step 2)
and the proof (step 3) do. The deeplink format is
zeroauth://reg?step=<pair|enroll|verify>&session=<uuid>&code=<code>
[&challenge=<hex>] — same format the android/ companion app
handles.
Right column is a "Simulate phone" panel that exercises the
phone-side endpoints directly so an operator can drive the
ceremony from one browser window without an actual companion app.
Pair + commit steps run end-to-end against the live backend. The
verify step intentionally lands a `verify_failed` because the demo
posts a stub Groth16 proof — that's the verifier doing its job. The
real green path goes through the android/ mobile prover (Phase 1
Sprint 4 integration).
Server side: three new console proxies at /api/console/registrations
(POST / GET :id / DELETE :id) mirror /v1/registrations but auth via
console JWT. Both surfaces strip pair_code_hash, enroll_code_hash,
verify_code_hash, verify_challenge_nonce out of the response shape
before it touches the browser — the plaintext codes are returned
only at issuance, the challenge nonce travels only in the QR3
deeplink.
Nav: "QR sign-in" + "QR signup" now sit side by side under the
shared /demo/ namespace; the old singular "Demos" label split to
make the two flows distinguishable.
Verify:
- npx tsc --noEmit (dashboard + backend) clean
- npm test (dashboard, vitest) 56/56
- npm test (backend, jest) 524/524 across 44 suites
- npm run build (dashboard) 121 modules, QrRegistration
lazy chunk = 28.4 kB / 9.95 kB
gzip; main bundle unchanged1 parent d64833c commit 8e39425
5 files changed
Lines changed: 757 additions & 1 deletion
File tree
- dashboard/src
- components/layout
- lib
- routes/demo
- src/routes
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
25 | 29 | | |
26 | 30 | | |
27 | 31 | | |
| |||
125 | 129 | | |
126 | 130 | | |
127 | 131 | | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
128 | 140 | | |
129 | 141 | | |
130 | 142 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
58 | | - | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
59 | 62 | | |
60 | 63 | | |
61 | 64 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
286 | 286 | | |
287 | 287 | | |
288 | 288 | | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
289 | 329 | | |
290 | 330 | | |
291 | 331 | | |
| |||
722 | 762 | | |
723 | 763 | | |
724 | 764 | | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
725 | 811 | | |
726 | 812 | | |
727 | 813 | | |
| |||
0 commit comments