---
name: ff-wave-built
description: FF fast-follow wave (pre-A-2) MERGED to main 2026-07-30 in golden v0.47.0 @00f3f92 (counter 82); 9 REQ mints + rotation; wave CLOSED; key rulings + shapes inside.
metadata: 
  node_type: memory
  type: project
  originSessionId: d780a4d4-c7b1-44a2-818b-9d5f41a0eb4e
  modified: 2026-07-31T05:03:30.418Z
---

**FF wave (ACCESS-CONTROL-JIT §FF, grilled 2026-07-30) built and pushed: `build/ff-fastfollow` @`dfc0352`, 12 commits off d26a2b2**, incl. doyle's docs cherry-picks (a2e9c7f, d4f5acf, 8fffa2e — docs/ff-grill-rulings branch). Battery at tip: clippy -D warnings clean · 22/22 unit suites · nextest --workspace --tests 2365/2365 (1 skipped, 702s; reseed grace pair + twohost + daemon_e2e lifecycle all PASS) · traceable-reqs exit 0 · xtask OK (reference regenerated). Gate report SENT to doyle 2026-07-30 ~18:41; doyle gates; golden assembles; kitsubito rides golden.

**REQ mints (all doc/impl/unit active, int at gate):** REQ-ER-CEREMONY-VERB, REQ-ER-BRINGUP-PROMPT, REQ-ACL-VIEW-ROSTER, REQ-ACL-VIEW-DRILLDOWN, REQ-ACL-NODE-VIEW, REQ-SUBNET-STATUS-MODES, REQ-SUBNET-CREATE-CAPTURE-PROOF, REQ-SUBNET-REVOKE-ADMIN-GATE, REQ-SUBNET-ADMIN-RESURFACE; REQ-SUBNET-ADMIN-SEED-ROTATION activated.

**Shapes that will matter later:**
- Admin seed rides the re-seed grace frame as a second item under single-source `ADMIN_PUSH_PREFIX` ("admin:<subnet>") — the frame decoder is TOTAL, so tuple extension would have cost N-1 peers member grace with the frame; old peers NotFound-ignore the sibling. ':' now unmintable in subnet names (BadName at create AND add_joined).
- `rotate_seed(name, Option<pending_admin>)` NEVER mints admin material — the pending key is minted at the revoke ceremony (where the human is), capture-proven (code-free display + typed-back current code, ±1 window), PARKED on RotationPending BEFORE tombstones; close adopts; parked absent = ruled degrade (member rotates, old admin kept, stderr + node-scope notif naming `revoke --force-rotate-seed`).
- Revoke requires CURRENT admin TOTP per touched subnet before any write; create shows admin QR first code-free with capture proof, mint persists only after proof. Both interactive-only where an admin key exists (scripted eviction gone by ruling).
- Ceremony agent-deny = env markers OR `roster::detect_self_by_ancestry()` — refusal-only reuse of label-only self-detect (F-024 ancestry-for-GRANT stays parked).
- Views: `crates/spt/src/accessview.rs` pure builders/renderers; drill-down filters TYPED subjects via `briefing::ruleset_rows_where` (never rendered-string matching); `spt daemon access` = node tier; subnet mode facts on `spt subnet status <name>` (doyle ruled: no near-synonym `show` verb).

**Why:** the wave's rulings (parked-pending-key, capture proof) exist because rotate-both would otherwise brick governance at first eviction — an authenticator cannot follow a seed rotation.

**How to apply:** when touching seedxfer, subnet names, rotation, or the ceremonies, re-read ADR-0051 §2a/§2b and ACCESS-CONTROL-JIT §FF first; the window/parked mechanics have three pinned rulings (park-before-tombstone; degrade-never-brick; one-pending-key-per-window). See [[v0460-published]].

**OPEN FOLLOW-UP, MINE (filed on the board 2026-07-30, builds after the operator's next batch call — NOT before).** hertz's #47 RCA found a product defect in this wave's `admin_rotation_incomplete_loudness`: it opens an ambient `NotifStore` + `EpochSource` *inside an explicitly-plumbed enclosing flow*, so it cross-minted epochs into concurrent tests and wrote 3 real rows into the LIVE home. Fix = thread the handles through instead of re-opening ambiently, plus a KH 4.8 ambient-caller census across the wave's sibling sites (don't fix the one site and call it done — that is the [[sweep-dispatch-site-counts]] class). The lesson generalizes: inside a flow that already plumbs its stores, opening an ambient store is not a shortcut, it is a second writer aimed at the live home.

**CLOSED 2026-07-30.** doyle gated dfc0352 green, assembled golden/ff-fastfollow @`00f3f92` (main d26a2b2 + PR #128 + #127 runbook docs + v0.47.0 bump), main ff'd to that same sha (PR #128 merged via 56e92e5); deployah GO'd for counter 82 — publish had NOT yet reached the releases board when I checked. My worktree cleanup done: registration pruned, branch deleted, tree deleted EXCEPT one empty `.worktrees/ff-fastfollow/crates/spt-daemon` still handle-pinned by an unidentified holder (no process runs from that path; retry the delete later).

**Golden's one red was NOT the wave** — Windows `test` leg failed `spt::endpoint_teardown_authority_e2e::stop_reaps_the_hosted_subtree_and_run_recovers_the_endpoint` (line 608, "re-run mints exactly one FRESH session — got []"), green on same-sha rerun; hertz owns the fix lane (`.worktrees/lane-teardown-oracle`, fix/teardown-oracle-soundness) for the next batch. RCA worth remembering: the second bringup SUCCEEDED (exit 0, session announced, pids spawned) but neither oracle saw it inside its 20s budget, and `sessions_after_resume=[3]` proves session id 2 WAS allocated to it — the row just landed late on a hot phase-B box. The instrument defect underneath: `broker_session_ids_for()` maps both `Brain::cold_start` and `sessions()` errors to an empty vec, so "broker unreachable" is indistinguishable from "row gone" — the exact postcondition the stop assertion checks, meaning one transient IPC failure makes stop falsely PASS and run2 falsely FAIL. See [[instrument-soundness-guards]].
