carlos / platform Public

spec: instance sizes and egress allows, rev 6 (Astra R5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 1f53efdf8f7f03950656e104f3089f6ee6ed94ec parent 2d82ecc
2 files changed, +51 −5
  • docs/superpowers/specs/2026-10-21-instance-sizes-and-egress-design.md +28 −5
  • docs/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