db-region-forward: Astra round 3 findings, unedited
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+69
−0
docs/superpowers/specs/CODEX-FINDINGS-DB-REGION-FORWARD-R3.md+69 −0
diff --git a/docs/superpowers/specs/CODEX-FINDINGS-DB-REGION-FORWARD-R3.md b/docs/superpowers/specs/CODEX-FINDINGS-DB-REGION-FORWARD-R3.md| new file mode 100644 |
| index 000000000..0679789f0 |
| --- /dev/null |
| +++ b/docs/superpowers/specs/CODEX-FINDINGS-DB-REGION-FORWARD-R3.md |
| @@ -0,0 +1,69 @@ |
| +| Earlier finding | Disposition | Evidence and remaining work | |
| +|---|---|---| |
| +| **1. Incarnation check** | **FIXED; DECLINED-AGREE** on version pinning | [§8.2:595](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:595) brackets each download and retry, withholding output until check B. This uses the identity validated by [provision.go:2777](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/provision/provision.go:2777) and [claim.go:192](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/hostclaim/claim.go:192). The stronger version-pinning mechanism remains unnecessary for the reported race. | |
| +| **2. Socket on stdin** | **FIXED** | [§8.3:638](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:638) specifies socket stdin/stdout and journal stderr, explicitly replacing [claimunit_template.go:19](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/host/claimunit_template.go:19). This matches systemd’s socket activation contract. [https://www.freedesktop.org/software/systemd/man/257/systemd.socket.html](https://www.freedesktop.org/software/systemd/man/257/systemd.socket.html) | |
| +| **3. Progress versus completion ack** | **FIXED** | [§9.1:728](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:728) removes both acknowledgement routes. The ambiguity cannot occur. | |
| +| **4. Late writes after `lost`** | **FIXED** for terminal arbitration | [§5.8:416](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:416) makes `lost` logical closure: late chunks are ignored, and competing results use the same create-only key. [store.go:794](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/release/store.go:794) supplies the required condition. The separate expiry-boundary problem remains under finding 13. | |
| +| **5. Cleanup reopens election** | **FIXED** | [§5.9:456](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:456) retains `picked` beyond the acceptance window. Later requests are rejected by age. Conditional creation is implemented at [store.go:794](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/release/store.go:794). | |
| +| **6. “Showed none” after rejection** | **FIXED** | [§5.5:289](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:289) buffers and verifies before stdout, avoiding the irreversible writes in [db.go:427](/home/paulca/amadan.net/carlos/platform-db-region-forward/db.go:427). | |
| +| **7. Stored-ciphertext bound** | **PARTLY — P2** | [§5.7:375](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:375) now accounts for retained output and noncurrent versions, but “gone two days after creation at most” is still false. The bucket is versioned at [deployment-buckets/main.tf:23](/home/paulca/amadan.net/carlos/platform-db-region-forward/infra/modules/deployment-buckets/main.tf:23). S3 rounds eligibility to midnight UTC; noncurrent age starts when the successor is created; deletion can occur later. **Fix:** describe lifecycle eligibility and eventual reclamation, without a hard two-day deletion guarantee. A hard deadline requires a different reclamation mechanism. This is a failure of the revised mechanism, separate from the already-flagged provisional ruling. [https://docs.aws.amazon.com/AmazonS3/latest/userguide/intro-lifecycle-rules.html](https://docs.aws.amazon.com/AmazonS3/latest/userguide/intro-lifecycle-rules.html), [https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-expire-general-considerations.html) | |
| +| **8. Disk reservations** | **FIXED** for the reported admission/restart defects | [§5.7:385](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:385) removes the timeout escape and retains reservations until unit termination. [§8.3:675](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:675) adds disconnect cancellation. The existing cancellable operations are [db.go:418](/home/paulca/amadan.net/carlos/platform-db-region-forward/db.go:418) and **`CheckDBContext`**, at [check.go:44](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/lease/check.go:44); the implementation must use that variant, not `CheckDB`, which supplies a background context. | |
| +| **9. Worker readiness** | **FIXED** | [§7.1:493](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:493) requires a real-unit probe, reserves its third connection, and skips probes during orphan blocking. This extends the armed-worker precedent at [movesoffline.go:254](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/host/movesoffline.go:254). | |
| +| **10. Incomplete snapshot evidence** | **FIXED** | [§7.1:519](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:519) checks incomplete evidence first and requires both flags for either refusal. This matches [snapshot.go:137](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/edgesfile/snapshot.go:137), [snapshot.go:182](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/edgesfile/snapshot.go:182), and `EvidenceComplete` at [snapshot.go:219](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/edgesfile/snapshot.go:219). | |
| +| **11. Separate store endpoints** | **DECLINED-AGREE** | [§12:908](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:908) explicitly limits support to the existing endpoint model. Both clients use the process-wide endpoint: [store.go:712](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/release/store.go:712), [endpoint.go:146](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/lease/endpoint.go:146), [s3compat.go:40](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/s3compat/s3compat.go:40). | |
| +| **12. Census classifications** | **FIXED** | [§13:937](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:937) uses supported classes, includes both runner callers, and requires removal rows and rulings. These match [plan14_root_reads_test.go:478](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/provision/plan14_root_reads_test.go:478), the existing J4 entry at [plan14-root-reads.tsv:202](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/provision/testdata/plan14-root-reads.tsv:202), and the nonrecord precedent at [moves_offline_census_test.go:12](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/provision/moves_offline_census_test.go:12). | |
| +| **13. Completion deletes terminal evidence** | **PARTLY — P2** | Completion no longer deletes anything, but [§5.8:427](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:427) permits independent lifecycle deletion, while follow has no maximum age. If `result.json` disappears before the retained request and `picked`, a follow call can create `lost` for a completed read. The condition in [store.go:794](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/release/store.go:794) permits creation over a current delete marker. **Fix:** establish a common logical follow/write cutoff before any lifecycle eligibility; after it, never synthesize another result. Test result-first expiry and concurrent housekeeping. [https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes.html](https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes.html) | |
| +| **14. Cleanup removes follow identity** | **PARTLY — P2** | [I6:173](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:173) promises equal lifetimes, but per-object lifecycle expiry cannot provide them. A request created before midnight and output created after midnight can have expiry dates a day apart. Once the request disappears, [§9.1:740](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:740) returns 404 for retained output. **Fix:** guarantee identity through an explicit retrieval interval shorter than lifecycle eligibility, and stop promising availability for every retained object. For fallback housekeeping, specify request-last, retryable deletion—the existing implementation does so at [runs/store.go:128](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/runs/store.go:128). | |
| +| **15. Full db gate hides `record-changed`** | **FIXED** | [§9.1:732](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:732) separates admission from follow/cancel authorization. It avoids the current-record refusals at [apidb.go:132](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/console/apidb.go:132), following the retained-request precedent at [apirunsfollow.go:126](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/console/apirunsfollow.go:126). | |
| + |
| +For the seven invariants in [§5.2:166](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:166): |
| + |
| +| Invariant | Disposition | Check | |
| +|---|---|---| |
| +| **I1 Immutable** | **PARTLY** | All listed protocol PUTs are conditional creates, and acknowledgements are gone. However, §5.8’s housekeeping deletes lack an enforced boundary separating them from still-permitted follow/cancel calls. Calling the pass “housekeeping” does not establish that boundary. Findings 13–14 remain relevant. | |
| +| **I2 Expiry is the store’s** | **NOT FIXED** | The stated timing is inaccurate; the fallback explicitly deletes objects itself; and a lazily ended read need not have a terminal result after 22 minutes. No route cutoff establishes the claim that cleanup touches objects “which nothing reads.” | |
| +| **I3 One owner** | **FIXED** for cooperating participants | Conditional creation of `picked` elects one owner, including a console expiry claim. A lost response does not elect two owners, but recovery from it is incomplete: new finding 16. This is protocol ownership, not authenticated writer identity. | |
| +| **I4 One end** | **PARTLY** | Competing result creates correctly arbitrate owner versus `lost` while the key remains present. Finding 13 shows how lifecycle expiry can reopen that decision. | |
| +| **I5 Acceptance** | **PARTLY** | Buffering, authenticated decryption, sequence checks and the sealed hash protect against incomplete or inconsistent output. They do not prove that the named owner wrote it: new finding 18. | |
| +| **I6 Identity** | **PARTLY** | The signed-request follow gate fixes current-record dependence. Equal physical lifetimes are not established: finding 14. | |
| +| **I7 Time is decided lazily** | **PARTLY** | `lost` can be retried through conditional creation. The two-write `expired` transition lacks recovery, and abandoned reads have no specified admission-counter expiry: new findings 16–17. | |
| + |
| +The “closed by” table therefore holds for **3, 4, 5 and 15**, subject to the retained-key boundary above. It does **not fully close 7, 13 or 14**. |
| + |
| +The chunk read-back rule at [§5.3:217](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:217) correctly preserves sealed bytes across ambiguous retries. Conditional-create support itself is available on S3 and MinIO; the missing recovery concerns `picked`, not that primitive. [https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes.html](https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes.html), [https://github.com/minio/minio/blob/master/cmd/erasure-object-conditional_test.go](https://github.com/minio/minio/blob/master/cmd/erasure-object-conditional_test.go) |
| + |
| +For the queue, current-plus-previous-hour listing covers requests behind the box’s clock across an hour boundary. A request in the next hour, within the permitted future skew, becomes discoverable when the box crosses that boundary; the 30-second poll still leaves it within the box’s acceptance window. I found no additional permanent omission caused solely by hour partitioning under the stated skew bound. |
| + |
| +16. **P2 — Lazy expiry can strand a read between its two writes.** |
| + |
| + **Spec:** [§5.8:413](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:413), [§5.3:199](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:199). |
| + |
| + The console creates `picked=expired`, then crashes or fails to create `result.json`. Subsequent follow calls find `picked`, so the “no picked” expiry branch no longer applies. There is no owning box whose deadline supplies the normal `lost` transition. A lost successful PUT response causes the same problem: “create failed” does not establish that a box owns the read. |
| + |
| + Existing code explicitly handles uncertain write outcomes: [apirunsfollow.go:94](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/console/apirunsfollow.go:94) documents them, and [host/runs.go:270](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/host/runs.go:270) reads ownership back after an unsuccessful pickup response. The new design specifies equivalent recovery only for chunks. |
| + |
| + **Fix:** make every follow call reconcile an existing console-expiry marker with a missing result. After ambiguous or conflicting `picked` writes, read the marker and distinguish console expiry, this exact box attempt, and another owner. Test a crash between the writes and a committed `picked` whose response is lost. |
| + |
| +17. **P2 — Abandoned reads have no specified way to release console admission slots.** |
| + |
| + **Spec:** [§5.7:366](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:366), [§5.8:423](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:423). |
| + |
| + Admit reads while boxes are busy, then let their CLIs disappear before pickup. No follow calls remain to create `expired`; no box owns them; lifecycle deletion cannot update the console’s in-memory counters. The design gives no counter-release rule. Two abandoned reads can exhaust a person’s allowance; sixteen can exhaust the console’s until restart. |
| + |
| + The existing token budget is not a sufficient precedent: it explicitly expires entries while admitting subsequent requests at [authcli.go:229](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/console/authcli.go:229). Existing runs also have independent expiry processing at [runsweep.go:98](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/console/runsweep.go:98). |
| + |
| + **Fix:** give admission reservations a bounded lifetime independent of CLI polling. Reconcile or expire them during subsequent admissions or a local timer, using pickup and owner deadlines. This need not introduce protocol deletes. Test abandoned queued reads, abandoned picked reads, and recovery without restarting the console. |
| + |
| +18. **P2 — The new non-owner forgery claim contradicts the sealing mechanism.** |
| + |
| + **Spec:** [§5.9:457](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:457), [I5:172](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:172), versus [§5.6:322](/home/paulca/amadan.net/carlos/platform-db-region-forward/docs/superpowers/specs/2026-10-22-db-region-forward-design.md:322). |
| + |
| + A non-owner can read the public reply key, create forged chunks, then win the `result.json` create with a matching sealed hash and the legitimate owner’s box name. The owner’s later `failed` result loses. The CLI’s specified checks accept the forged, internally consistent answer. |
| + |
| + Every box has deployment-bucket write authority at [region-host/main.tf:166](/home/paulca/amadan.net/carlos/platform-db-region-forward/infra/modules/region-host/main.tf:166). Sealing at [crypto.go:206](/home/paulca/amadan.net/carlos/platform-db-region-forward/internal/appconfig/crypto.go:206) uses the recipient’s public key and a freshly generated sender key; it supplies no owner credential. A key path and a `box` string cannot establish authorship. |
| + |
| + **Fix:** align I3/I5, §5.9 and T4 with §5.6’s explicitly accepted trust boundary: consistency is checked, but a compromised deployment writer can forge an answer. If non-owner forgery resistance is required instead, add authenticated owner publication. Test forged chunks **together with a forged matching result**, rather than chunk substitution alone. |
| + |
| +Reviewed at `20524df4c65542a2f5c196903981e0fc62d22ee4`. Static review; no runtime acceptance tests or file changes. Platform module code at both cited release tags was inspected. Current flagship refs and deployment-state assertions remain unverified: GitHub retrieval failed, and the available infrastructure checkout is dated October 6. |
| + |
| +**REVISE** |
| \ No newline at end of file |