Skip to content

Dashboard live polling + audit findings update#63

Merged
pulkitpareek18 merged 3 commits into
mainfrom
dev
May 29, 2026
Merged

Dashboard live polling + audit findings update#63
pulkitpareek18 merged 3 commits into
mainfrom
dev

Conversation

@pulkitpareek18
Copy link
Copy Markdown
Collaborator

Summary

Two surgical improvements that close the gap between "ceremony built" and "ceremony usable in a demo with a real phone":

  1. Live polling in QrRegistration.tsx — polls `GET /api/console/registrations/:id` every 2 s while the page is in any awaiting_* state. When the server reports a forward transition, the dashboard auto-advances without operator intervention. The simulator panel keeps dispatching state directly so it doesn't wait on the poll. Polling stops at terminal states.

  2. audit-findings.md updates — a new "Phase 1 follow-ons landed since the last snapshot" section records ADR 0022 / 0023 / 0024; a new "Pilot-ready vs production-ready gap" section lists the six known blockers that still gate a real BFSI tenant onboarding (real biometric capture, real Groth16 proof for verify step, camera QR scanning, circuit v1.3 with challenge_nonce, branch protection on main, PII strip).

Test plan

  • `npx tsc --noEmit` clean (dashboard)
  • `npm test` (vitest) — 56/56
  • CI on the push will rerun validate + Playwright

Pulkit Pareek added 3 commits May 29, 2026 12:12
The dashboard demo at /demo/registration was driving the phone-side
endpoints through a simulator. This commit adds the actual Kotlin
client so the same flow runs against the live backend from a real
phone (sideloaded APK).

What lands:

  net/RegistrationApi.kt      — Retrofit binding for the three
                                phone-side endpoints (POST
                                /v1/registrations/{pair-device,
                                submit-commitment, complete}) plus
                                request/response DTOs. Same OkHttp +
                                Json stack as ZeroAuthApi; pulled out
                                into ApiFactory.createRegistrationApi
                                so callers that only need the new
                                surface skip the W3 init cost.

  util/RegQrPayload.kt        — Parser for the QR deeplinks:
                                zeroauth://reg?step=<pair|enroll|verify>
                                &session=<uuid>&code=ZA-XXXX-XXXX
                                [&challenge=<32-hex>]. Returns
                                Result.failure with stable string
                                codes (reg_qr_parse_failed,
                                reg_qr_missing_field,
                                reg_qr_bad_code_shape,
                                reg_qr_bad_challenge_shape) so the UI
                                routes errors without a try/catch.

  util/DeviceFingerprint.kt   — Builds the >= 16-char opaque
                                fingerprint string the server hashes.
                                Composition: android:<appId>:
                                <ANDROID_ID>:<install_uuid>; result
                                SHA-256-hex'd. Per-install UUID lives
                                in SharedPreferences so the same
                                install always produces the same
                                fingerprint (lets the same row in the
                                devices table re-enroll on
                                code-regenerate).

  ui/reg/RegistrationViewModel.kt — State machine:
                                Idle → Pairing → AwaitingEnrollScan
                                → Committing → AwaitingVerifyScan →
                                Verifying → Completed | Failed.
                                onQrText(text) parses, branches by
                                step, and POSTs. BiometricSecretSource
                                and ProofGenerator are injection seams
                                so Phase 1 Sprint 4 can swap the
                                StubProofGenerator for the real
                                WebViewMobileProver.

  ui/reg/RegistrationHelpers.kt — Default injections:
                                PerInstallStableSecret persists a
                                32-byte secret in SharedPreferences so
                                step 2 and step 3 derive the same
                                commitment (without that, the verify
                                step's publicSignals[0] check fails).
                                DeriveDidAndCommitment computes
                                Poseidon.hash2(secret, zeroSalt) and
                                derives the DID suffix. StubProofGenerator
                                returns a structurally valid Groth16
                                envelope — the server's verifier will
                                reject it (intentionally) until the
                                real prover lands.

  ui/reg/RegistrationScreen.kt — Compose UI. Paste-deeplink only for
                                V1 (the camera scan path mirrors
                                ui/scan/ScanScreen.kt's ML Kit +
                                CameraX pipeline and gets wired in
                                Phase 1 Sprint 4). Step badge,
                                progress indicators, terminal
                                Completed / Failed cards.

  ui/SplashScreen.kt          — Second CTA "Create a new account
                                (3-QR signup)" routes to the new flow.
                                Original "Sign in" CTA unchanged.

  nav/Nav.kt                  — New Screen.Registration entry +
                                composable route.

Tests:

  test/util/RegQrPayloadTest.kt — 11 Robolectric tests covering the
                                happy path for each step + every
                                stable error code (wrong scheme, wrong
                                host, unknown step, missing
                                session/code, malformed code/challenge,
                                verify-without-challenge).

Verify (CI):
  .github/workflows/android.yml runs ./gradlew assembleDebug + test
  on every push that touches android/**. The local toolchain in this
  environment doesn't have gradle/android SDK installed (the wrapper
  jar is gitignored per README), so the validation falls to CI.

How to install on a phone:
  cd android
  gradle wrapper --gradle-version 8.7
  ./gradlew :app:installDebug   # adb-attached device
The Compose viewModel(factory = ...) builder needs the explicit
imports for viewModelFactory and initializer. Without them the
qualified path resolves the builder but the lambda-inside-builder
fails 'Unresolved reference initializer'. Android CI #62 caught
this; local env has no SDK to validate at commit time.
Two small improvements that close the gap between "ceremony built"
and "ceremony usable in a demo with a real phone":

1) QrRegistration.tsx polls GET /api/console/registrations/:id
   every 2 s while the page is in any awaiting_* state. When the
   server reports a forward transition the dashboard auto-advances
   without operator intervention — this is what a real phone
   scanning the QRs would trigger. The simulator panel keeps
   dispatching state directly so it doesn't wait on the poll.
   Polling stops at terminal states (completed / abandoned / error)
   and when the page is idle/creating, so there's no background
   load when nothing's happening.

2) docs/security/audit-findings.md gains a new "Phase 1 follow-ons
   landed since the last snapshot" section recording ADR 0022
   (device enrollment), ADR 0023 (three-QR signup), and ADR 0024
   (qrcode.react dep). The original 21 findings carry forward
   unchanged. A second new section "Pilot-ready vs production-ready
   gap" lays out the six known gaps that still block a real BFSI
   tenant onboarding, so the tracker doesn't claim more than is true.

Verify:
  - npx tsc --noEmit (dashboard)   clean
  - npm test         (vitest)      56/56
Copilot AI review requested due to automatic review settings May 29, 2026 08:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@pulkitpareek18 pulkitpareek18 merged commit eb1d29a into main May 29, 2026
7 of 8 checks passed
@pulkitpareek18 pulkitpareek18 deleted the dev branch May 29, 2026 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants