docs: spec §24 names Verifier.Enroll and the stamped aliases; plan 1b's flag-on prerequisites and after-the-build fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 files changed,
+20
−4
docs/superpowers/plans/2026-10-06-region-ha-1b-claim-readers.md+17 −2docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md+3 −2
CI passed — run details
diff --git a/docs/superpowers/plans/2026-10-06-region-ha-1b-claim-readers.md b/docs/superpowers/plans/2026-10-06-region-ha-1b-claim-readers.md| index e8a5e668b..0ef299a5b 100644 |
| --- a/docs/superpowers/plans/2026-10-06-region-ha-1b-claim-readers.md |
| +++ b/docs/superpowers/plans/2026-10-06-region-ha-1b-claim-readers.md |
| @@ -4149,11 +4149,12 @@ and settles five details: |
| 1. **Enrollment refuses one instance under two references (§5.1).** The |
| record's `box` field is not covered by AWS's signature, so box A's |
| record copied to B's key with that field rewritten still verifies. |
| - `boxid.Enroll` refuses an instance the roster holds under another |
| + `boxid.Verifier.Enroll` refuses an instance the roster holds under another |
| reference, as well as a reference the roster holds for another |
| instance, counting entries in every state. |
| 2. **A positive stamp is the relocatable mark (§18's open question).** |
| - Only relocatable hosts with a claim carry a stamp, so the edge's report |
| + Only relocatable hosts with a claim, and their aliases and served |
| + catch-alls, carry a stamp, so the edge's report |
| of two boxes at one positive stamp already concerns them alone. No |
| separate marker. |
| 3. **The edges file's claim reads (§5.4).** A relocatable host with no |
| @@ -4241,6 +4242,8 @@ Everything spec 1 rev 5.4 asks for that this plan does not build, with the reque |
| **Not waiting for the claim, and not in this plan.** Plan 1a's "After the build" items 9 (a streaming put, lifting the 64 MiB limit, and the data bucket's conditional-write policy for `files/`), 11 (one inotify instance per agent) and 12 (a size cap in `StagePlatform`, a rate limit on `Commit`) need no claim change. They matter only once the files publisher is switched on, which waits for L13, so they belong with that plan. |
| +**Turning the flag on.** `CARLOS_REGION_HA` must be set in `/etc/carlos/host.env`, where both the agent and root's `carlos-system-update.service` read it. A drop-in for `carlos-edge.service` alone would turn on the edges file's claim reads and the box record but not root's §5.10 refusal. It is on only for a value `strconv.ParseBool` reads as true (`1`, `t`, `true`). Two things must be in place before any box sets it: the per-pass deadline on the edges file's claim reads (built: see "After the build", item 4), and a roster-wide check that no instance holds more than one reference (enrollment's per-record check cannot see two entries the roster already holds; it belongs with L7's roster). |
| + |
| ## What the dry run could not check |
| - `readIdentityRecord` against a real box's IMDS. Plan 1a verified the regional certificates and the signature on the dev box; this plan's reader was tested only against an in-process fake. Before the branch lands, on the dev box with `CARLOS_REGION_HA=1` set for the agent, confirm `control/boxes/<label>.json` appears once and that `boxid.Enroll` accepts its bytes with the dev account and region. |
| @@ -4295,3 +4298,15 @@ Findings are in `CODEX-PLAN-REGION-HA-1B-R2.md` (reviewed at 161728ab). Round 2 |
| |---|---|---| |
| | R2-1 | P2 Task 6: claim passes bypass the publication retry backoff | fixed: a claim pass is gated on the schedule's `retryAt`, and its outcome goes through `edgesFileSchedule.done` (a failure advances the backoff, a success clears it; the timer does not move). `TestEdgesLoopClaimPassesObeyTheRetryBackoff` runs the loop's schedule against a bucket that fails for 20 minutes then recovers: 12 attempts while failing (40 unthrottled), and the 30-second passes back after recovery. It fails with the `retryAt` gate removed, with claim outcomes not recorded, and with claim passes off | |
| | R2-2 | P2 Task 5: three validation checks survive removal | fixed: three more stored cases, each failing exactly one check: `running` with no volume (empty mapping), `terminated` with its root mapping (state), a volume with an id but no device (device). Removing each of the five checks (state, empty mapping, volume id, device, version) fails its own case | |
| + |
| +## After the build |
| + |
| +The final whole-branch review (2026-10-06) raised seven findings, all ruled by the controller and fixed on the branch: |
| + |
| +1. `boxvolumes`: a `shutting-down` record whose DeleteOnTermination volumes show `detaching` (EC2 detaching them on the way to deletion) is evidence, not a refusal. In any other state, and for a volume whose flag is false, only `attached` and `attaching` count. |
| +2. `boxid.Verifier.Enroll`: a roster entry for the same reference with no proven cloud yet does not refuse it; only an entry naming another instance does. |
| +3. `Enroll`'s doc says the record's `box` is not signed, so for a reference the roster does not yet hold the caller must bind instance to reference independently (operator approval, the tofu id, or H16's group confirmation). The agent's `publishBoxRecord` checks a record already under its label against its own identity and logs loudly, once per run, when it is signed for another instance or cannot be read. |
| +4. The edges file's claim reads share a 20-second deadline per pass; a read it cuts short keeps the last decision, and reads not reached wait for a later pass. Failed reads are logged on the first failing pass, every 60th after, and on recovery. A host `hostclaim.Key` rejects is never read and publishes as before. |
| +5. `regionHAEnabled` accepts only what `strconv.ParseBool` reads as true; `""`, `0`, `false`, `off`, `no` and anything unparseable are off. |
| +6. `boxid`'s "unknown field" test uses a fully signed record plus one extra field, so only `DisallowUnknownFields` can refuse it. |
| +7. Spec §24 names `Verifier.Enroll` and includes aliases and served catch-alls among the stamped entries; this plan says where the flag is set and what must exist before it is turned on. |
diff --git a/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md b/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md| index 0dce3ecb4..dd48f6b80 100644 |
| --- a/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md |
| +++ b/docs/superpowers/specs/2026-10-04-region-ha-box-placement-design.md |
| @@ -1808,11 +1808,12 @@ and settles five details: |
| 1. **Enrollment refuses one instance under two references (§5.1).** The |
| record's `box` field is not covered by AWS's signature, so box A's |
| record copied to B's key with that field rewritten still verifies. |
| - `boxid.Enroll` refuses an instance the roster holds under another |
| + `boxid.Verifier.Enroll` refuses an instance the roster holds under another |
| reference, as well as a reference the roster holds for another |
| instance, counting entries in every state. |
| 2. **A positive stamp is the relocatable mark (§18's open question).** |
| - Only relocatable hosts with a claim carry a stamp, so the edge's report |
| + Only relocatable hosts with a claim, and their aliases and served |
| + catch-alls, carry a stamp, so the edge's report |
| of two boxes at one positive stamp already concerns them alone. No |
| separate marker. |
| 3. **The edges file's claim reads (§5.4).** A relocatable host with no |