Skip to content

Complete real browser-side wiring of the master plane (parent-control web app) #163

@hanwencheng

Description

@hanwencheng

Problem

The parent-control web app (apps/parent-control) renders the master-side flows but does not perform the real backend calls. Audited in PR #162 (docs/plan/web-flow/wire-real-paths.md §2):

  • Onboarding ceremony — only the K11 WebAuthn step is real (and only in daemon backend mode); email-verify, wallet/SIWE→J1, and register_master_device are progress-bar narration with a mock tx hash. "Logged in" is a localStorage flag, not a session JWT.
  • Memory plant/list — hits the daemon ui-bridge but stores in an in-memory map; no cap-mint → STS → memory worker → S3.
  • Pairing / scope / revoke mutations — in-memory stubs; no broker pairing calls, no on-chain registerAgentDevice / setScopeWithWebauthn.
  • Under the default empty backend (what a fresh user runs), nothing is real.

Root issue: the orchestration logic lives behind a localhost daemon (desktop-only). For the phone-first product (most operators have only a phone, no desktop), the browser/client itself must carry the master-plane logic and talk to the always-on broker.

Target

Complete the real browser-side wiring of the master plane so the web app drives the master onboarding, memory, pairing, and mutations through the real broker + chain + memory worker — the same calls harness/phase1-wire-demo.sh already makes — with no fabricated/in-memory data.

Per the plan (#162, docs/plan/web-flow/wire-real-paths.md §0.5 + §11 + §12): factor the master-plane orchestration into a portable agentkeys-core, compile it to WASM, and expose it as a CoreBackend behind the existing lib/client AgentKeysClient interface — so the browser calls the broker directly (the same core later binds to the mobile native app via UniFFI).

Scope (master plane, browser/client side only)

  • X0 — carve the master-plane logic into agentkeys-core with a host-agnostic API (no axum/daemon deps); extend the existing init_flow with pairing + cap + onboarding-state.
  • X1wasm-bindgen exports for: email auth (start/verify/status), wallet SIWE (start/verify), pairing (claim/pending/ack), cap-mint, onboarding-state aggregation. wasm-pack build.
  • X2CoreBackend implementing AgentKeysClient (alongside empty/daemon); NEXT_PUBLIC_AGENTKEYS_BACKEND=core. UI unchanged (same interface).
  • X3 — WebAuthn interop: the core asks the JS host to run navigator.credentials.{create,get}; the K11 enroll + assert flow back into the core.
  • Onboarding §9 — real email magic-link → broker binding_nonce; real wallet/SIWE → J1 (replaces the localStorage.ak_onboarded flag with a real session); real register_master_device.
  • Memory — plant/list through real cap-mint → OIDC-mint → STS → memory worker → S3 (replace the in-memory map).
  • Pairing §10.2 — proxy the broker pairing endpoints (/v1/agent/pairing/*, /v1/agent/pending-bindings) + bind/grant chain writes.
  • X4 — chain-write delegation per the §11 gating decision (see below).

Gating constraint (verified — wire-real-paths.md §11)

Every master chain write is msg.sender-bound to the operator's secp256k1 key (SidecarRegistry / AgentKeysScope); K11 is an additional gate, not a substitute. A browser/WASM host cannot safely custody the secp256k1 key, so it must delegate the on-chain broadcast to a key-holding host (phone Keychain / desktop daemon) — unless the contracts move to assertion-only auth. The exact secure delegation/relayer mechanism is the open design question (under adversarial security review; see #162 §11 fork A vs B).

Acceptance criteria

  • With NEXT_PUBLIC_AGENTKEYS_BACKEND=core, a fresh operator completes onboarding (email → Touch ID → wallet/SIWE → master registered on chain) entirely from the browser, producing the same on-disk + on-chain artifacts the harness produces.
  • Memory planted from the UI is readable via the real memory worker / S3 (cross-checked by the agent-side hook memory-inject).
  • A pairing claim + scope grant from the UI lands real registerAgentDevice + setScopeWithWebauthn txs; isServiceInScope(...) == true.
  • No narrated/in-memory data paths remain on the master plane; disconnected/empty states are honest.

References

  • Plan: PR #162docs/plan/web-flow/wire-real-paths.md (§0.5 host model, §11 gating, §12 WASM scope), data-model.md (phone-first amendment), arch.md §22c.3.
  • Reference implementation of the real calls: harness/phase1-wire-demo.sh.
  • Canonical ceremonies: docs/arch.md §9 (master bootstrap), §10.1, §10.2.

Out of scope

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions