| index 2649be21f..927748fad 100644 |
| --- a/docs/superpowers/specs/2026-10-15-region-ha-two-box-regions-design.md |
| +++ b/docs/superpowers/specs/2026-10-15-region-ha-two-box-regions-design.md |
| @@ -1,6 +1,8 @@ |
| # Region HA, spec 2: two-box regions |
| |
| -Design, 2026-10-15, **rev 11**. DRAFT. Nothing here is built. |
| +Design, 2026-10-15, **rev 12**. DRAFT. Nothing here is built. |
| + |
| +**Rev 12** answers Astra's round 11 (`CODEX-FINDINGS-REGION-HA-SPEC2-11.md`, **A11-1**, P2, accepted). Rollback's exclusion is set on the region's group, and every box the group launches inherits it at enrolment, so a replacement can't reopen placement. §24. |
| |
| **Rev 11** answers Astra's round 10, a full pass (`CODEX-FINDINGS-REGION-HA-SPEC2-10.md`, cited **A10-n**): three P2s and one P3, all accepted. Rollback now restores only the ingress and never destroys a group that has hosted an instance, so retiring a group is spec 4's drain too. Moves take their source from the claim, not from placement eligibility. §23 maps them. |
| |
| @@ -300,7 +302,12 @@ The choice is made once and recorded in the create intent, as now (H12). Recover |
| - the box's existing instances stay where they are; |
| - operations already heading to it before the role was set simply finish there, and the instance joins the box's existing ones. Nothing needs to be empty, so nothing needs to be waited for. |
| |
| -The roles are set by an operator, through `carlos system box role <ref> legacy|platform|default`, a console API only an operator may call, and they persist in the roster. Spec 4's drain later moves a `legacy` box's instances to the group, and then the box is retired. |
| +The roles are set by an operator, through `carlos system box role <ref> legacy|platform|default`, a console API only an operator may call, and they persist in the roster. |
| + |
| +**A group-level role** (A11-1). Each region's group has its own entry in the roster: the `Region` struct already carries `GroupName` and `GroupARN`. That entry gains a **default role for its boxes**, normally `default`, set with `carlos system group role <region> legacy|default`. |
| +- The console's enrolment pass (§5) gives every box it enrols from that group the group's role, in the same roster write that enrols it. |
| +- So a replacement launched after the group was excluded enrols already excluded, and is never placeable even for a moment. |
| +- Changing the group's role also changes the role of every box currently enrolled from it, in one roster write. Spec 4's drain later moves a `legacy` box's instances to the group, and then the box is retired. |
| |
| **Rebalancing:** none automatic. An operator moves an instance between boxes in a region with spec 1's relocation. Automatic rebalancing is spec 4's. |
| |
| @@ -354,13 +361,13 @@ Each is closed by a code change, or by showing it's safe under claim mode, befor |
| - **Before any group box reaches hosting mode** (step 1 failing): destroy the group and NLB freely. Nothing has been placed on them. |
| - **After that, before step 3:** |
| - set the old box's role back to `default`, so new instances can land on it again; |
| - - set both group boxes to `legacy`, so nothing new lands on them. |
| + - set **the group's** role to `legacy` (`carlos system group role <region> legacy`). That excludes both current group boxes and every replacement the group launches later (A11-1). |
| - The group boxes keep whatever they host. They stay in service, behind the old box's forwarding, until spec 4's drain retires them. |
| - **From step 3 until acceptance:** |
| 1. Remove zone A's mapping from the NLB. An address on a requester-managed interface can't be disassociated directly. The NLB itself is kept, because the group boxes are its targets. |
| 2. Wait until the EIP shows as unassociated. |
| 3. Swap the old box's addresses back: disassociate its new EIP, associate the region's EIP, and force a republication. In IE, switch the relay and MX records back and restart the relay advertising the region's address (A2-9). |
| - 4. Set the roles as for "before step 3". Group instances stay where they are, reached through the old box privately. |
| + 4. Set the roles as for "before step 3", the group's role included. Group instances stay where they are, reached through the old box privately. |
| - **After acceptance:** recovery is forward, within the group. |
| |
| **Cost.** |
| @@ -403,6 +410,7 @@ Each is closed by a code change, or by showing it's safe under claim mode, befor |
| - **Rehearsal on dev:** |
| - the full §9 sequence, with the cut-over window measured, the zone-B rehearsal, and both rollback sequences run once. Rollback leaves the group in service with its instances, including one that was never woken; |
| - outbound moves from a `legacy` box and from the `platform` box; |
| + - a group box replaced after rollback, and one already joining during rollback: each enrols with the group's `legacy` role and is never placeable; |
| - the old box's address swap at the cut-over: forced republication, and cross-region forwards to its instances recovering within a minute; |
| - the `legacy` and `platform` roles excluding a box from creates, relocation targets and move targets, persisting across console and box restarts, and an operation already heading to the box finishing there; |
| - one group box terminated by hand, with replacement and re-enrolment observed; |
| @@ -526,3 +534,9 @@ All three were answered in Astra's round 1 and folded in: |
| | A10-2 P2: rollback can't relocate a never-woken group instance | Accepted by the same change: rollback moves nothing (§9) | |
| | A10-3 P2: moves need source validation separate from destination eligibility | Accepted: the source comes from the claim and is checked only as enrolled, active and unfenced. Only the destination uses §7 (§8) | |
| | A10-4 P3: §6 still requires emptying the old box | Accepted: §6 describes the address swap (§6) | |
| + |
| +## 24. Astra round 11 dispositions (rev 12) |
| + |
| +| Finding | Disposition | |
| +|---|---| |
| +| A11-1 P2: rollback's exclusion doesn't survive box replacement | Accepted: a role on the region's group entry in the roster, inherited at enrolment in the same write, and applied to current members when changed (§7, §9) | |