DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path change-requests/cr-create-commit-ceremony-v0_1.md

Change Request — Browser commit ceremony (the passkey step-up, all three doors) — v0.1

Document: cr-create-commit-ceremony-v0_1 Version: v0.1 Date: 2026-06-29 Type: Phase change request — Operator Layer frontend (a shared component + wiring at three commit points). No engine change/instantiate, /instantiate/challenge, and the WebAuthn primitives already exist. This is the cross-cutting commit-ceremony gap surfaced by live use of door 3. Consumer: Claude Code (executor). Branch base: OL main @ b107290; engine main @ 0b2c232 (engine read-only — reused, not changed). Origin: Running door 3 live (a real PRD → extract → review → amend) landed on a "Foundation saved. Commit it with your passkey to make it official." screen with no commit affordance — a dead end. Grounding found this is not door-3-specific: the browser commit-with-passkey ceremony (/instantiate/challenge → WebAuthn assertion → /instantiate) is unbuilt for all three doors. Doors 1/2 commit via the conversation, which returns step_up_required, but ChatView handles no step_up_required action — so they dead-end too, less visibly. The engine half is built and verified to the gate; the browser ceremony half was never built. Grounding: the door-3 "Foundation saved" end-state inspection (DocumentCreateFlow ends at amend, no /instantiate call anywhere in OL; door3.ts has no commit client; ChatView handles only exhaustion_choice_dialog, not step_up_required; getWebAuthnAssertion exists from Phase 48 sign-in) — OL b107290, engine 0b2c232.


Plain-language summary

When you finish creating an engagement — by any of the three doors — the last step is to commit it with your passkey. The engine is ready for that (it asks for the passkey tap). But the screen never actually offers the tap: door 3 ends on a sentence telling you to commit with your passkey, with no button; doors 1 and 2 end on a message the conversation can't act on. So today, no engagement can actually be finished in the browser — every door stops one step short. This builds the missing step: a shared "make it official" commit that runs the passkey ceremony (ask the engine for a challenge → tap your passkey → commit), wired into all three doors' finish points. Built once, used everywhere. No engine change — it wires up endpoints that already exist.

What was wrong with what we said

Through the create-stage builds, the passkey-commit was described as "the one pending real-world step — the Operator's to perform in the browser." That was true of the engine (/instantiate exists, the step-up gate fires, headless checks reached it) but it implied there was a surface to perform the commit on. There is not. No door has a commit button, a challenge call, or a WebAuthn ceremony wired. "The Operator's to perform" should have read "not yet built." This CR builds it; a manifest correction (below) fixes the record.

Why it hid: every door's build verified the commit "to the WebAuthn gate" — true, but that gate is exactly where the headless check stops and the browser ceremony begins. "To the gate" was the literal ceiling of headless verification; the unbuilt ceremony lives in the gap above it, reachable only by a real person in a browser. Live use surfaced it (the fifth exists-vs-works instance of the arc, and the one that hid inside the un-automatable human-presence step).

What's true today (grounded)

Decisions

  1. One shared commit-ceremony component, not three. The ceremony (challenge → getWebAuthnAssertion → instantiate) is identical across doors; build it once, wire it at each door's commit point.
  2. No engine change. Reuse /instantiate(/challenge) and getWebAuthnAssertion. Engine read-only.
  3. The component is the affordance. Per "only show what's available" — the commit is presented as an actionable control (a "Make it official" / "Set it up" commit button that launches the ceremony), not described in prose. The door-3 "Foundation saved" dead-end text is replaced by the control.
  4. Handle the findings branch — if commit returns findings (divergent), the component offers the existing /instantiate-divergent path (commit despite findings) per Operator authority, or routes gaps to the conversation. Confirm the real signal shape at Step 0.

Scope boundary


The build — steps

Per-step commits, suite green at each, halt-before-push. OL only.

Step 0 — inspect before building (no code)

Confirm against OL b107290 / engine 0b2c232:

  1. Branch base.
  2. The step_up_required signal shape from each commit path — door 1/2's converse → create_engagement_commit (how step_up_required arrives in ConverseResponse / the action payload) and door 3's /instantiate direct call (the challenge → assertion → instantiate sequence). The shared component must hook the same ceremony from both entry points; confirm the exact signal each surfaces.
  3. /instantiate/challenge request/response — what the challenge endpoint returns (the WebAuthn options getWebAuthnAssertion needs), and what /instantiate expects (the serialized assertion + any engagement id / findings-override flag).
  4. getWebAuthnAssertion's shape — the options it takes and the SerializedAssertion it returns, confirming it maps cleanly onto the challenge response + the instantiate request (it was built for /auth/login/begin — confirm the challenge response is shaped compatibly, or what adaptation is needed).
  5. The findings/divergent branch — how a commit-with-open-findings surfaces, and whether /instantiate-divergent is the Operator-authority "commit anyway" path.

Report findings — especially 2 (the two entry-point signals) and 4 (the helper's fit) — then build.

Step 1 — The shared commit-ceremony component

A component that runs: request /instantiate/challengegetWebAuthnAssertion(options)POST /instantiate with the assertion → on success, the engagement is active (navigate to it / confirm). Loading + error states (a failed/cancelled passkey tap returns cleanly, re-offers). The findings branch (Step-0.5) offers /instantiate-divergent per Operator authority. Presented as an actionable commit control.

Suite expectation: the component runs challenge → assertion → instantiate; success activates; a cancelled assertion re-offers; findings route correctly.

Step 2 — Wire door 3

Replace DocumentCreateFlow phase === "done"'s text-only dead-end with the commit-ceremony component (after amend). "Foundation saved" becomes "Foundation saved — make it official" with the actual commit control.

Suite expectation: door 3's post-amend state presents the commit control; committing activates the engagement carrying the reviewed commitments.

Step 3 — Wire doors 1/2

Handle step_up_required in ChatView (the conversation commit path) by presenting the same commit-ceremony component (as a request_action handler alongside the existing exhaustion_choice_dialog). The conversation commit now completes instead of rendering an inert message.

Suite expectation: a door-1/2 conversation commit that returns step_up_required presents the ceremony; committing activates the engagement.


Acceptance

Manifest correction owed (named)

The v0.72 §5 item — "browser passkey-commit pending across all three doors… the Operator's to perform" — is half-wrong: it implied an affordance that was never built. A manifest note (v0.73 or a §5 amendment) should correct it: the commit ceremony was unbuilt across all three doors; this CR builds it. Recorded here so the correction isn't lost; the record should state the true claim ("not yet built") not the softer one ("pending your tap").

What this completes


DUNIN7 — Done In Seven LLC — Miami, Florida Change Request — Browser commit ceremony (the passkey step-up, all three doors) — v0.1 — 2026-06-29 Live use of door 3 surfaced a dead end: "Foundation saved. Commit with your passkey." with no commit affordance. Grounding found the browser commit ceremony (/instantiate/challenge → WebAuthn assertion → /instantiate) is unbuilt for ALL THREE doors — doors 1/2 dead-end too (ChatView ignores step_up_required). The engine half is built and verified to the gate; the browser half never was — it hid in the gap the headless checks structurally couldn't reach (the human-presence tap). Fix: one shared commit-ceremony component reusing the existing getWebAuthnAssertion helper + the existing /instantiate(/challenge) endpoints, wired at all three doors' commit points. No engine change. Acceptance is a real passkey tap completing a real engagement in the browser, per door. Corrects the v0.72 §5 "pending your tap" claim to "was unbuilt." Base OL b107290, engine 0b2c232.