spec: instance sizes and egress allows, rev 6 (Astra R5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 files changed,
+51
−5
docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md+28 −5docs/superpowers/specs/CODEX-FINDINGS-instance-sizes-egress-R5.md+23 −0
diff --git a/docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md b/docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md| index 00c4fe4a9..897b35397 100644 |
| --- a/docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md |
| +++ b/docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md |
| @@ -1,9 +1,9 @@ |
| # Instance sizes and egress allows |
| Amadan #328 (an isolated instance reaching a private service its operator |
| -runs) and #329 (operator-set CPU and memory per instance). Revision 5, |
| -2026-10-21. Revisions 2 to 5 answer the builder check, Astra rounds |
| -1 to 4, and Paul's ruling on fleet addresses (`CODEX-FINDINGS-instance-sizes-egress-R<n>.md`); the |
| +runs) and #329 (operator-set CPU and memory per instance). Revision 6, |
| +2026-10-21. Revisions 2 to 6 answer the builder check, Astra rounds |
| +1 to 5, and Paul's ruling on fleet addresses (`CODEX-FINDINGS-instance-sizes-egress-R<n>.md`); the |
| dispositions are §9. |
| Both are the same mechanism: **an operator-set policy for an app and its |
| @@ -93,7 +93,9 @@ than from intent. |
| - An allow that reaches another app's instances, the probe, or any unit |
| outside the app's own per-host slices. |
| - An allow that can open loopback, link-local, the metadata service, or |
| - any address a fleet box holds. |
| + the box's own addresses; or a grant of an address a fleet box is known |
| + to hold. (An address another box acquires after the grant is reported, |
| + not closed: ruling 8, §4.2.) |
| - A revoke that leaves the address open on a running instance without |
| it being re-asserted and reported. |
| - A size change that OOM-kills a running process. |
| @@ -129,6 +131,19 @@ that way. |
| older console that never touches this object) does not inherit the old |
| instance's size (Astra R2-3). Deleting an instance through a new |
| console also removes the entry, for tidiness. |
| +- **The policy dies with its app** (Astra R5-1). An app's name is freed |
| + by a purge (`PurgeAppRow`, `internal/console/store.go:1731`: "a later |
| + app of the same name starts clean"), and the bucket purge already |
| + sweeps state kept outside the app's prefix for that reason (ledgers, |
| + promotion records, `internal/release/trash.go:276-295`). The policy |
| + object joins that sweep, before the tombstone marker, so a purge that |
| + dies is retried by the next pass; this covers manual and automatic |
| + purges alike. As a second guard, the console's app-create door deletes |
| + any policy object still at that key before the name is usable. A new |
| + app of an old name therefore never inherits an egress grant or a |
| + default size from its predecessor. Residual: only a console downgraded |
| + to a version without this sweep, after policies exist, could leave one |
| + behind; the release notes say so. |
| - **Precondition the builder must verify and record in the plan:** the |
| key is under the store's control boundary (`hostops/mutation_boundary.go` |
| and the bucket policy), so no app, build, instance or member |
| @@ -512,6 +527,13 @@ does exist, at `internal/activator/`. |
| | R1-5 / R3-2 / new 1 | The inventory can look complete with boxes missing | Superseded: Paul ruled for a grant-time check plus a report; root no longer depends on the inventory (§4.2) | |
| | new 2 | A cached completeness verdict never expires | Superseded the same way: no cached verdict exists (§4.2) | |
| +**Astra round 5** (REJECT; every earlier finding resolved): |
| + |
| +| # | Finding | Disposition | |
| +|---|---|---| |
| +| new 1 | A recreated app of the same name inherits the policy | Accepted: the purge sweeps the policy object, and app creation clears a lingering one (§3) | |
| +| new 2 | A test still required root to enforce other boxes' addresses | Accepted: test and anti-goal reworded to ruling 8 (§2, §11) | |
| + |
| ## 10. Left to the builder |
| - Column names, the call shapes, and the status snapshot fields. |
| @@ -532,7 +554,8 @@ does exist, at `internal/activator/`. |
| process afterwards. A revoke whose first write fails is re-asserted by |
| root's loop. |
| - A grant naming another box's address is refused; one naming an address |
| - a box acquires later is dropped by root and reported. |
| + another box publishes later raises the report's alert and stays in |
| + force; one this box acquires later is dropped by root and reported. |
| - Resize during a swap waits; growth reaches the serving generation's |
| own cap; a memory shrink leaves every running process's limits alone, |
| a swap's successor starts at the larger size, and the shrink lands at |
diff --git a/docs/superpowers/specs/CODEX-FINDINGS-instance-sizes-egress-R5.md b/docs/superpowers/specs/CODEX-FINDINGS-instance-sizes-egress-R5.md| new file mode 100644 |
| index 000000000..89117cdee |
| --- /dev/null |
| +++ b/docs/superpowers/specs/CODEX-FINDINGS-instance-sizes-egress-R5.md |
| @@ -0,0 +1,23 @@ |
| +R1-1: **RESOLVED** — Populated-slice skips and resize serialization remain. |
| +R1-2: **RESOLVED** — Growth updates generation limits and captured tier. |
| +R1-3: **RESOLVED** — Memory reductions require an empty slice. |
| +R1-4: **RESOLVED** — Failed writes are retried against read-back. |
| +R1-5: **RESOLVED** — Superseded by ruling 8. |
| +R1-6: **RESOLVED** — All claim validators use the shared size table. |
| +R1-7: **RESOLVED** — Separate storage protects policy from older manifest writers. |
| +R1-8: **RESOLVED** — The declined finding matches the retained size trust model. |
| +R1-9: **RESOLVED** — `HighOf` remains authoritative. |
| +R2-1: **RESOLVED** — Memory reductions wait for an empty slice. |
| +R2-2: **RESOLVED** — Publication changes explicitly cover region HA being off. |
| +R2-3: **RESOLVED** — Instance overrides are bound to `CreatedAt`. |
| +R3-1: **RESOLVED** — Pending reductions preserve the incumbent’s size through swaps. |
| +R3-2: **RESOLVED** — Superseded by ruling 8. |
| +R3-3: **RESOLVED** — Account-scoped policy reads through the fleet door are specified. |
| +R4-1: **RESOLVED** — Missing publishers are explicitly accepted and reported under ruling 8. |
| +R4-2: **RESOLVED** — Root no longer depends on cached fleet completeness. |
| + |
| +1. **P1 — A replacement app inherits its predecessor’s operator policy.** [§3:106](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/instance-egress-sizes-328-329/docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md:106) keys policy only by account and app name. Purge deletes the app prefix and explicitly listed auxiliary prefixes, leaving `control/app-policy/` untouched ([trash.go:272](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/instance-egress-sizes-328-329/internal/release/trash.go:272), [trash.go:284](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/instance-egress-sizes-328-329/internal/release/trash.go:284)). It then frees the name and revokes existing name-bound credentials so a replacement app starts clean ([store.go:1738](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/instance-egress-sizes-328-329/internal/console/store.go:1738)). A non-operator account owner can recreate that name and inherit its old egress grant and default size without another operator decision. The instance `CreatedAt` check does not protect these app-wide fields. **Smallest fix:** bind the policy to a verified app incarnation, or require policy retirement before name reuse across manual purges, automatic purges and mixed-version consoles. |
| + |
| +2. **P2 — A test still requires the enforcement ruling 8 removed.** [§11:534](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/instance-egress-sizes-328-329/docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md:534) requires root to drop an address subsequently acquired by “a box.” [§4.2:195](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/instance-egress-sizes-328-329/docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md:195) instead requires an alert while retaining the allow. **Smallest fix:** distinguish local acquisition, which root drops, from acquisition by another box, which produces an alert and preserves the allow. Qualify §2’s blanket fleet-address anti-goal accordingly. |
| + |
| +REJECT |
| \ No newline at end of file |