# WAX-SEAL — milestone #21 intake JIT (doyle, 2026-08-23)

Milestone: `BigscreenVR/spt-bs-releases#21` (kind: MILESTONE, GREENLIT → WIP this intake).
Requests: #7 (sealed messages, IDEA) · #8 (`spt-wax-seal`, IDEA) · #19 (Esc cancel, ADDITION).
Design source of truth: **CONTEXT.md:1074** (wax seal, ratified 2026-07-29 access-control grill),
CONTEXT.md:785 (anchor subnet), CONTEXT.md:1098 (IO parser / `;;…;;` siting), ADR-0054 (sealed-code
crypto house rules), releases#19 (Esc-cancel ruling), ACCESS-CONTROL-JIT.md FF-T2 (the landed
Esc-cancel TOTP overlay pattern on `spt rc engine-room`).

## Operator grill rulings (2026-08-23, this session — the greenlit form)

1. **#8 is discharged by the core primitive.** The anonymous-minter shell from #8's sketch stays
   a downstream shell, unbuilt (CONTEXT.md:1075 already demoted it). Re-scope comment-recorded on #8.
2. **TOTP ceremony only this milestone.** FIDO2 (enrollment verb, per-OS backends, `E` overlay
   shortcut, signature verify) = **fast-follow**: request + milestone minted at this intake,
   sequenced to pick up the moment WAX-SEAL ships. Overlay ships WITHOUT the `E` shortcut until then.
3. **Mint entry points**: `spt seal mint` (text on stdin) and `spt send <id> --seal`. The
   `;;text to seal;;` shortform is **ratified-but-deferred** to the IO-parser milestone (its funnel
   is that milestone's machinery; CONTEXT.md:1098) — deferral comment-recorded on #7 and #21.
4. **No ceremony surface ⇒ fast refusal** `SEAL_NO_CEREMONY_SURFACE` — no pending-mint state, no
   timeout queue. The agent is told to have the operator attach and retry.
5. **Binding subnet default**: the minter endpoint's **anchor subnet**; on `spt send --seal` where
   the destination does not share the sender's anchor subnet, the **lexicographically-first subnet
   shared by both endpoints** (ADR-0054 §9 house rule for "several subnets qualify"). `--subnet`
   overrides. The overlay ALWAYS names the subnet whose code it expects. Rationale: the seal record
   replicates subnet-scoped, so the binding subnet must be one the receiver can `verify` in.
6. **No expiry, no revoke in v1.** Timestamp is in the record; a reversed decision is a newer seal.
7. **`verify` is content-bound**: token + content on stdin → BOUND / NOT-BOUND (+ record fields).
   Bare `verify` with no content refuses, pointing at `describe`. `describe <token>` → record fields.

8. **Ceremony content overflow (Q10, operator-ruled 2026-08-23 evening)**: ruled **(c)** —
   content is CAPPED AT 500 CHARS at the ceremony seam (longer refuses with a named reason,
   distinct notice to the requester; never truncated), the overlay SUPPORTS SCROLLING (a
   ≤500-char content can still overflow a small PTY grid — the surface adapts, the content
   never shrinks), and submit is NEVER gated on scrolled-to-end (no EULA-pattern consent
   theater). doyle's pins under this ruling: the cap counts Unicode scalar values at the
   ceremony seam only (a record property it is not — but all v1 mints pass the ceremony, so
   it caps in effect); ceremony content must be valid UTF-8 (bytes you cannot display verbatim
   are bytes nobody can consent to — non-UTF-8 refuses with its own named reason).

## Design-of-record (doyle, pinned at intake — not operator questions)

- **Ceremony shows the sealed content verbatim** in the overlay (a blind mint is a consent hole;
  #7's own sketch shows it). Sealed dispatch also shows the destination id.
- **Overlay keys**: Enter = submit, Esc = cancel per releases#19 — clean abort, NO partial seal
  record, pending sealed-send dropped with a clear notice to the initiating agent.
- **TOTP verify**: member-or-admin code of the selected subnet, `totp::code_at` + `accepts_step`
  window, verified locally against `SubnetStore::seed_bytes`/`admin_seed_bytes` (ER W3-T2 pattern).
  Attempt bound per the ER finding-4 / REQ-ER-BRINGUP-ATTEMPT-BOUND shape (bounds presented guesses;
  Esc/absent input is not a guess and spends nothing).
- **Seal record**: `{token, content_hash, minter: subnet:endpoint@node (fully qualified),
  minted_at, ceremony_kind}`. Token 8–10 chars, unambiguous lowercase charset, narrow per the
  REQ-HAZARD-ID-CHARSET discipline. Content hash over exact bytes presented at the ceremony.
- **Store/replication**: subnet security material beside grant store/whitelist, same plumbing,
  subnet-scoped replication so `spt api seal verify|describe` answers on any member node.
- **Envelope attribute**: sealed message carries its token as a **sender-authored** envelope
  attribute (riding like `json=`, collision-proof). ⚠ It must ride END-TO-END: it is NOT in the
  receiver-composed attribute strip class (`trust-warning`, `mnemonics-json` — CONTEXT.md:960);
  builder must verify the strip seam strips the CLASS and not this attr. Forged/wrong tokens are
  harmless by construction: `verify` recomputes the content hash (KH 7.5 discipline — the attr is
  never an authorization subject by itself; only a BOUND verify verdict is evidence).
- **rc arm**: a remote attached controller runs the ceremony client-side and ships proof up the
  rc channel (rc-paste client-originated precedent) — CONTEXT.md:1075 ratified.
- **No shared subnet on sealed dispatch** (destination shares none of the sender's memberships):
  refuse with the reason named — do not fall back to an anchor-subnet seal the receiver cannot verify.

## Waves (todlando; test rework → hertz per dispatch split)

- **W1 — record + store + api verbs.** ✅ BUILT (todlando, PR spt-bs-core#156 @ 0244c5d2) +
  GATED PASS (doyle 2026-08-23, verdict comment on #21; all legs green, design review clean,
  premise correction verified — grants/whitelist never replicate, seals ride the notif pattern).
  PR parks for the milestone golden chain. Gate-rig residue: `.worktrees/gate-wax-w1` 68K
  source-only dir handle-pinned at teardown — retry removal at wave end (target reaped, pool
  released). Seal record, token mint, security-material store +
  subnet-scoped replication, `spt api seal describe`, `spt api seal verify` (content-bound,
  refuse-toward-describe). REQs: REQ-SEAL-RECORD, REQ-SEAL-TOKEN-FORMAT,
  REQ-SEAL-STORE-REPLICATES-SUBNET-SCOPED, REQ-SEAL-VERIFY-CONTENT-BOUND, REQ-SEAL-DESCRIBE.
- **W2 — TOTP ceremony.** ✅ BUILT (todlando, 8079987a on build/wax-seal-w2, lane-local) —
  DESIGN-REVIEW PASS (doyle 2026-08-24: surface ladder, conn hygiene, throttle-before-verify,
  Esc grammar, ledger fail-closed all verified at sites; provenance concern DISSOLVED on
  measurement — ceremony surface is structurally the asserted endpoint's own screen). ONE
  finding, ruled + folded as W3 first commit: minter node half = daemon node-key short hex,
  never os_hostname (mutable, non-unique; pubkey is the identity). MECHANICAL GATE LEGS VOIDED
  by the IR-59 disk incident (LNK1318 + os error 112 at 3MB free; register face committed
  d1f98fff) — they re-run ONCE at the W3 head via sequential takeover of the lane pool at
  todlando's pool-release, evidencing W2+W3 together. Builder's own env-scrubbed 3161/3161 at
  8079987a stands as builder evidence meanwhile. Gate-rig residues .worktrees/gate-wax-w1 +
  gate-wax-w2 (source-only, pruned) handle-pinned — retry removal at milestone close. Overlay (FF-T2 pattern + releases#19 Esc), content shown verbatim,
  subnet named, member-or-admin verify + attempt bound, SEAL_NO_CEREMONY_SURFACE refusal,
  rc client-side arm. REQs: REQ-SEAL-CEREMONY-TOTP, REQ-SEAL-CEREMONY-CONTENT-SHOWN,
  REQ-SEAL-CEREMONY-ESC-CANCEL (satisfies #19), REQ-SEAL-NO-CEREMONY-SURFACE,
  REQ-SEAL-CEREMONY-RC-CLIENT.
- **W3 — entry points + envelope.** ✅ BUILT (todlando, 5 commits → 035c3fe6 on build/wax-seal-w3,
  pushed) + GATED: local legs GREEN at head (doyle warm-takeover run: clippy 0, treqs 0, workspace
  3170/3170+1skip), design review CLEAN (attr class pins at codec + ingress, pure lexicographic
  resolver, trim parity, exit-0-iff-admitted; four builder decisions approved). TWOHOST CLIMB RAN
  2026-08-24 (kitsubito role B via manual procedure 2): role A green incl. both seal rungs; role B
  RED on a RIG defect — S1 mints ~0.3s before A exits vs 500ms pusher cadence, zero pushes
  structurally (IR-29 second face @ a6592772). NOT a product defect. Rig fix → hertz (dispatched,
  two shapes); re-climb on his fix. Combined W2+W3 verdict: PASS-PENDING-CLIMB. `spt seal mint`, `spt send --seal [--subnet]`, subnet-default
  rule (anchor → shared-lexicographic → refuse), envelope attr end-to-end + receiver rendering.
  REQs: REQ-SEAL-MINT-VERB, REQ-SEAL-SEND-SEALED, REQ-SEAL-SUBNET-BINDING-DEFAULT,
  REQ-SEAL-ENVELOPE-ATTR.
- **W4 — docs + gate.** Public envelope docs (the attr is adapter-visible surface), CLI reference
  (⚠ IR-52 conditional rider: if the docs-site CLI generator is touched, land the depth fix with
  it), CONTEXT.md mints for rulings 3–7 above, docs-drift gate, milestone gate + field acceptance.

REQ minting rides the W1 build PR (registry-first within the lane; mints-ride-build-PRs rule).
Stages activate per wave (doc/impl/unit in the delivering lane; int at gate) — never pre-fail.

## Gate findings carried forward (doyle, W1 design review 2026-08-23)

- **W3 caution — exact-bytes sealing**: verify hashes EXACT bytes (trailing newline ⇒ NOT-BOUND,
  unit-pinned). `spt send --seal` must hash the same byte buffer it delivers — one buffer, never
  re-read/re-encoded between ceremony and delivery, or shell-added newlines mint seals that never
  verify. Needs a unit pinning ceremony-buffer == delivered-buffer identity.
- **W2 caution — cross-process store write**: the daemon's apply arm serializes same-process
  writers under SEAL_APPLY, but the W2 ceremony mint writes trust/seals.json from the CLI process —
  two atomic writers, last-writer-wins, and a lost LOCAL MINT is the one record re-presentation
  cannot heal (only the minting node held it). W2 must make the mint write cross-process-safe
  (file lock, or write through the daemon).

## Deferred, relocated (nothing dangling)

- FIDO2 ceremony → fast-follow request + milestone (minted this intake, blocked-by #21).
- `;;text to seal;;` shortform → IO-parser milestone (comment on #7/#21).
- Anonymous-minter shell → downstream project, no request (CONTEXT.md:1075 demotion stands).

## Register sweep (intake mandate)

IR-52 composed as CONDITIONAL W4 rider (above). IR-2 trigger unmet (todlando's PR set parked
unlanded). IR-55 armed with hertz. Remainder: triggers unfired or discipline entries. Recorded
in docs/INFRA-REGISTER.md sweep block this intake.
