spec: host lifecycle claim rev 5.1, CC20 sweep moves/<host>/ and CC21 purge fence
S3 cannot condition the claim write on the registration's version, so purge fences a drained registration's host claim before removing it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+25
−2
docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md+25 −2
CI passed — run details
diff --git a/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md b/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md| index cb2597a7c..df41dd1b4 100644 |
| --- a/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md |
| +++ b/docs/superpowers/specs/2026-10-02-host-lifecycle-claim-design.md |
| @@ -1,6 +1,6 @@ |
| # The host lifecycle claim |
| -Design, 2026-10-03, **rev 5**. A small primitive cited by: |
| +Design, 2026-10-03, **rev 5.1** (rev 5 plus CC20, CC21). A small primitive cited by: |
| - **#199**, deleting an instance and parking its data: |
| `2026-10-02-replica-ownership-design.md`, which this spec supersedes |
| @@ -401,7 +401,26 @@ site now uses: |
| like any other. Expiry alone is not enough: dropping such a |
| registration would let purge tear down a store the create already |
| uses. A crashed console's registration therefore expires and drains, |
| - and does not block every purge. This is tested with |
| + and does not block every purge. |
| + |
| + **Fencing a paused creator (CC21).** A console can renew its |
| + registration, pause, and then resume after purge has drained that |
| + registration. S3 cannot make the creator's claim write conditional on |
| + the registration object's version, because they are two objects. So |
| + purge fences from the claim side: |
| + - before removing a registration whose host claim doesn't name the |
| + create, purge CASes that host's claim from free or absent to a |
| + **purge fence**, `{op: {kind: "purging", id: <purge id>}}`, with no |
| + holder; |
| + - only then does it remove the registration. |
| + |
| + The paused creator's claim CAS (§5.1 step 2) is from free or absent, |
| + so it now fails, and the create is refused before any record exists. |
| + The fence is released to free at the purge's completion (`done`). |
| + The creator also re-reads its registration as its last step before |
| + the claim CAS, and stops if it is gone or admission is closed. That is |
| + cheap, but not sufficient on its own; the fence is what guarantees |
| + it. This is tested with |
| at least two hosts. |
| 1a. **Adopt first (CC6).** Run the one adoption routine (§9) for every |
| record of the app that has no claim, before deciding which hosts the |
| @@ -517,6 +536,8 @@ host it can see in its bucket that has no operation running. It lists: |
| - the location of every incarnation in that host's |
| `retired_incarnations`; |
| +- **`moves/<host>/`** (CC20): a staging write that completes after its |
| + move's cleanup would otherwise stay there for good; |
| - every generation within the live `holder.location` other than |
| `holder.generation` (the moves spec's dead generations). |
| @@ -817,6 +838,8 @@ the model catches it. |
| | CC17 | §5.1 step 5 | |
| | CC18 | §2 `holder.generation` | |
| | CC19 | C3, the staging-work lease exception | |
| +| CC20 | §6.2a at-rest sweep | |
| +| CC21 | §5.3 step 1b, the purge fence | |
| ## 13. S3 behaviour this relies on, verified |