The handoff at the end of the run: every branch's tip, gate, review and CI state; the heartbeat has ended and was not renewed
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 files changed,
+13
−13
.claude/HANDOFF.md+9 −9implementation/carloku-paid-launch/OUTSTANDING.md+4 −4
CI passed — run details
diff --git a/.claude/HANDOFF.md b/.claude/HANDOFF.md| index 4c90893d1..1ac5d5e59 100644 |
| --- a/.claude/HANDOFF.md |
| +++ b/.claude/HANDOFF.md |
| @@ -7,13 +7,13 @@ |
| Get Carloku's paid plans live with Stripe Tax and the complete metered model; have the pricing page and signup flow reviewable in the morning. |
| **STATUS:** |
| -Written 12:03 Dublin on 2026-10-01. Three things, kept apart. |
| +Written 12:50 Dublin on 2026-10-01, at the end of the run. Nothing is running for it any more except the three review servers. Three things, kept apart. |
| 1. Draft copy to review, not approved: pricing http://100.119.180.57:38009 (name form http://docs-t1.tail5fd3ba.ts.net:38009), console billing page http://100.119.180.57:45033 (name form http://docs-t1.tail5fd3ba.ts.net:45033). |
| 2. A demo to click through: http://100.119.180.57:41881, real console handlers with Keymail and Stripe simulated. It is not Stripe proof. |
| 3. A tested branch that is not production-ready. `implementation/carloku-paid-launch/OUTSTANDING.md` says what is reviewable, tested and proven, lists every launch blocker, and lists each approval to ask for with its exact scope. |
| -All three review servers answered 200 on the IP form at 11:30 Dublin. |
| +All three review servers answered 200 on the IP form at 12:48 Dublin. |
| Preview readiness with billing off is not launch readiness, and a review that accepts a diff is not approval of the branch. Full metering is not ready: neither metered source is proven (replication writes, store transfer), Stripe has no catalog or runtime key and the quantity fence is unverified, and quantity reduction at renewal and the Free tier are not built. |
| @@ -23,7 +23,7 @@ Last gated tip when this was written: `bac513f6` (handoff-only commits sit on to |
| - `cd8821c6` is the last commit that changes product code (round seventeen's fixes). Local gate on it: build, vet, gofmt, `make test` with 61 packages ok on the second run (`logs/gate-cd8821c6.txt` in the run directory; the first run failed one `internal/activator` test, log kept as `logs/gate-cd8821c6-run1-failed.txt`); cross builds for darwin, linux arm64 and windows (`logs/cross-cd8821c6.txt`). Amadan CI passed on `cd8821c6`. |
| - `bac513f6` changes one test file only: it fixes that activator test. Its recording script wrote a file with a shell redirect, which creates the file empty before the content arrives, and the test could read it in that moment. The file is now renamed into place whole. Under the same load, 55 failures in 1,280 runs before and none after. Local gate on `bac513f6`: 61 packages ok, first run (`logs/gate-bac513f6.txt`). CI passed on `c1cf8822`, which is `bac513f6` plus this file. |
| -- Amadan CI sat queued all night, first ran at 07:34 Dublin, and has passed on `1395f7bf`, `d0a21aa1`, `d5705a63`, `973a9f15`, `abc9f781`, `86a1849d`, `cd8821c6` and `c1cf8822`. The local gate is not offered in CI's place. |
| +- Amadan CI sat queued all night, first ran at 07:34 Dublin, and has passed on `1395f7bf`, `d0a21aa1`, `d5705a63`, `973a9f15`, `abc9f781`, `86a1849d`, `cd8821c6`, `c1cf8822` and the handoff-only tips after it up to `a78d5982`. It has not run on any side branch. The local gate is not offered in CI's place. |
| Independent review. No review of the whole branch has passed. GPT-6 Astra rejected rounds 1 to 16; the AGENTS-required Opus production review accepted with fixes in rounds 2 to 16. Each round found the round before closed for its reported shapes and found neighbouring ones, in the object-store walks (`internal/objstore`) and their readers since round seven. Round seventeen read only the diff since round sixteen: Opus accepted, Astra accepted with fixes (one P2). That P2 and Opus's small items are fixed in `cd8821c6` and have not been read by a reviewer. Open items the reviews left are in `OUTSTANDING.md` 19a to 19i. Nothing lands until the whole branch has been read and accepted. Dispositions, round by round: `docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md`. |
| @@ -31,10 +31,10 @@ Two open defects, both with their paths disabled, neither offered as a risk to a |
| Side branches, all on the forge, none run through CI, nothing on the launch branch calls them. Each has now had one review by both reviewers, and none passed: |
| -- `feat/carloku-late-request-fencing-20261001` (`8ca8cd6b`, full local gate passes): a Stripe request cannot outlive its connection, and a void for a wrong-total invoice (remediation only). Both reviewers rejected it at `1772e840`. Five findings are fixed since and unread. One finding limits the design: the provider's idle-connection limit bounds when a request can begin to be written, not when a whole request is received. As designed the branch does not close the two defects. Open: the sandbox probe and three transport tests, in `DISPOSITIONS-late-request-fencing.md` on that branch. |
| +- `feat/carloku-late-request-fencing-20261001` (`1b61de82`, rebased onto this branch at `a78d5982`, full local gate passes): a Stripe request cannot outlive its connection, and a void for a wrong-total invoice (remediation only). Both reviewers rejected it at `1772e840`. Five findings are fixed since and unread. One finding limits the design: the provider's idle-connection limit bounds when a request can begin to be written, not when a whole request is received. As designed the branch does not close the two defects. Open: the sandbox probe and three transport tests, in `DISPOSITIONS-late-request-fencing.md` on that branch. |
| - `feat/carloku-metered-replicator-20261001` (`9c08ce31`, rebased onto this branch at `72b4f59a`, full local gate passes): path B, first pieces. Rejected by both reviewers twice, at `ebab1a37` and at `f4fe6f2b`. The second review found the ownership fence added after the first does not hold as built: a refused request is still sent, and the registry witness is moved by the replicator's own bookkeeping. Both need changes outside that branch's packages before a third review. What holds: ownership by file for the database itself, the refusals for unclaimed files and unreadable directories, the platform identities, the private store, and `Close` stopping the store. `DISPOSITIONS-metered-replicator.md` on that branch. |
| -- `feat/carloku-bucket-hour-evidence-20261001` (`b50f29bc`; code `58c1870c`, full local gate passes): the operator evidence door for a store's partial first hour. Astra rejected it, Opus accepted with fixes. Both confirmed it releases only that hour for the owner the ledger names. Both found the evidence is free text one operator records, which in practice is a waiver. That needs Paul's ruling (approval J in `OUTSTANDING.md`). Nothing fixed yet. `DISPOSITIONS-bucket-hour-evidence.md` on that branch. |
| -- `feat/carloku-storage-sole-holder-20261001` (`09520a62`, off this branch at `c68ecddd`, full local gate passes): the fix for `OUTSTANDING.md` 19i. The storage pass sizes a store only when it is the sole holder of its bucket. Read five times. The fifth reading, of the last diff, was accepted with fixes by both reviewers, P3 only; those fixes are in `09520a62` and unread. It is the nearest of the side branches to mergeable, and it is not merged: it needs your ruling on approval K, and a reading of its whole diff. |
| +- `feat/carloku-bucket-hour-evidence-20261001` (`0aa1fbec`, rebased onto this branch at `a78d5982`, full local gate passes): the operator evidence door for a store's partial first hour. Reviewed once: Astra rejected it, Opus accepted with fixes. Both confirmed it releases only that hour for the owner the ledger names. Both found the evidence is free text one operator records, which in practice is a waiver. That needs your ruling (approval J in `OUTSTANDING.md`). Nothing fixed yet. `DISPOSITIONS-bucket-hour-evidence.md` on that branch. |
| +- `feat/carloku-storage-sole-holder-20261001` (`4ed6b71e`, off this branch at `c68ecddd`, full local gate passes): the fix for `OUTSTANDING.md` 19i. The storage pass sizes a store only when it is the sole holder of its bucket. Read six times. The fifth reading, of a diff, was accepted with fixes by both reviewers. The sixth, of the whole change, was accepted with fixes by Opus and rejected by Astra on one P1, fixed in `4ed6b71e` and unread. It is the nearest of the side branches to mergeable. It is not accepted and not merged: it needs one more reading and your ruling on approval K. |
| - `feat/carloku-scoped-attestation-20261001` (`058ea506`): path A, parked. It cannot prove an exclusive writer. Replication-write completeness is a launch blocker, not waived. |
| **NEEDED:** |
| @@ -43,14 +43,14 @@ Side branches, all on the forge, none run through CI, nothing on the launch bran |
| **RECOMMENDED:** |
| - Rule on approvals J and K. K decides whether the storage branch can merge. |
| +- Storage branch: one more reading of `09520a62..4ed6b71e`, then of the whole change. |
| - Replicator: a request gate in `internal/lease` that stops a request (not only fails its recording), and a version of the routes table's owner-bearing columns in the registry. Then the sibling-file link checks. Then a third review. |
| - Decide what bounds a complete late request at Stripe, or redesign so nothing depends on it. |
| -- Rebase the fencing and evidence branches onto this branch: they predate the activator test fix (`bac513f6`), and their gates can fail on that test. |
| - Have the whole launch branch read again at its tip, not a diff, before anything is called accepted. |
| -- Then, each on its own branch: quantity reduction at renewal, the evidence door for a box's first minutes, the AWS principal inventory and the bucket ownership attestation door, Free-tier enforcement, dormancy and pool accounting. |
| +- Then, each on its own branch: quantity reduction at renewal, the evidence door for a box's first minutes, a short retry of the storage pass after 23:00 UTC, the AWS principal inventory and the bucket ownership attestation door, Free-tier enforcement, dormancy and pool accounting. |
| **SESSION:** |
| -A bounded heartbeat (`carloku-paid-launch-continuity`, id `a1f7c9af`, every 30 minutes, six runs at most, three hours) returns to this same agent from 10:00 Dublin. Not safe to close without a look: three review servers are serving on this box (pids and stop file under `/home/paulca/.local/share/carloku-paid-launch-20260930/logs`). |
| +The bounded heartbeat (`carloku-paid-launch-continuity`, id `a1f7c9af`) ran from 10:00 Dublin and its three hours ended at about 12:37. It was not renewed: what is left is either a decision of Paul's or new implementation large enough that he should choose to start it. No review, gate or build of this run is still running. Not safe to close without a look: three review servers are serving on this box (pids and stop file under `/home/paulca/.local/share/carloku-paid-launch-20260930/logs`). |
| The shared `/tmp` on this box was 99% full at 10:16 (about 478 MB free of 32 GB). Most of it is not this run's: `/tmp/titogo-admission-go-cache` (8.0 GB), `/tmp/admission-repair-cache` (6.5 GB, still growing), `/tmp/g` (3.2 GB) and two CI runner directories. This run did not touch them. It failed one gate run (tests that build a binary could not link). The gate wrapper (`~/.cache/carloku-gate/texec.sh`) now gives every package but the activator an on-disk scratch root, `/var/tmp/ck`; the activator keeps `/tmp/k` because its unix socket paths do not fit under a longer root. |
diff --git a/implementation/carloku-paid-launch/OUTSTANDING.md b/implementation/carloku-paid-launch/OUTSTANDING.md| index 3ba036252..23bf95d6b 100644 |
| --- a/implementation/carloku-paid-launch/OUTSTANDING.md |
| +++ b/implementation/carloku-paid-launch/OUTSTANDING.md |
| @@ -34,7 +34,7 @@ Each is concrete. None is waived. |
| 1. **Replication writes (`durability_writes_1k`) cannot be proven on any box.** The external replicator writes outside the ledger. Path A (scoped attestation) was built, reviewed in round six, and cannot prove an exclusive writer; it is off this branch and parked on `feat/carloku-scoped-attestation-20261001`. Path B (the platform's own replicator as the only writer) is **partial, unwired, and rejected at both of its reviews**, on `feat/carloku-metered-replicator-20261001` (`9c08ce31`, on the forge; the full local gate passes on it): a litestream store whose every replica client is metered with no unmetered fallback, an owner for each database the box replicates, and a fleet store that refuses anything it cannot meter, each with tests. Its second review found that the ownership fence added after the first does not hold as built: a refused request is still sent (the request meter sends on a failed start), and the registry witness it relies on is moved by the replicator's own bookkeeping, so the store goes stale within minutes of opening. Both need changes outside that branch's packages (a request gate in `internal/lease`, a routes-only version in the registry) before a third review is worth running. `DISPOSITIONS-metered-replicator.md` on that branch has every finding. **Absent**: the agent wiring that binds those meters to the box's ledger, a restore path that does not shell out to the external binary, the unit change, moving the replica credentials so nothing else on the box holds them (the unit runs as the same user as the agent today), and any attestation. Until all of that exists and is approved for a box, this meter is incomplete every month and nothing is invoiced. |
| 2. **Store transfer (`store_egress_gb`) has no source.** No Cost and Usage Report export exists on the account. It needs the scoped infrastructure approval, a first real delivery, an IAM principal inventory in the AWS provisioner (not built), and the bucket ownership attestation for stores that already exist (designed, not built). |
| -3. **A store's partial first hour** with a charged line holds the month, and nothing releases it. It holds by default and nobody is asked to waive it. What can release it is evidence: an operator door that records, for one bucket-hour, who is shown to have owned it and on what evidence, which the fold then honours. **Partial, unwired into this branch**, on `feat/carloku-bucket-hour-evidence-20261001` (`b50f29bc`; code at `58c1870c`): the record, the fold change and three operator API doors, with tests and mutation checks. It accepts only the hour a complete ledger began vouching in and only the owner that ledger names. The full local gate passes on it. First review: Astra rejected it, Opus accepted with fixes. Both confirmed that through the fold it releases nothing but that hour for that owner. Both also found that the evidence is free text that the same operator records and that stands at once, which in practice is a waiver: what counts as evidence, and whether a second person must approve it, needs Paul's ruling (approval J) before more is built. Nothing fixed yet (`DISPOSITIONS-bucket-hour-evidence.md` on that branch). No CI run, no CLI verb, and its operator-facing sentences are unreviewed. |
| +3. **A store's partial first hour** with a charged line holds the month, and nothing releases it. It holds by default and nobody is asked to waive it. What can release it is evidence: an operator door that records, for one bucket-hour, who is shown to have owned it and on what evidence, which the fold then honours. **Partial, unwired into this branch**, on `feat/carloku-bucket-hour-evidence-20261001` (`0aa1fbec`, rebased onto this branch): the record, the fold change and three operator API doors, with tests and mutation checks. It accepts only the hour a complete ledger began vouching in and only the owner that ledger names. The full local gate passes on it. First review: Astra rejected it, Opus accepted with fixes. Both confirmed that through the fold it releases nothing but that hour for that owner. Both also found that the evidence is free text that the same operator records and that stands at once, which in practice is a waiver: what counts as evidence, and whether a second person must approve it, needs Paul's ruling (approval J) before more is built. Nothing fixed yet (`DISPOSITIONS-bucket-hour-evidence.md` on that branch). No CI run, no CLI verb, and its operator-facing sentences are unreviewed. |
| 4. **A box's first minutes** before its ledger opened hold that day for everyone. Same as item 3: it holds by default, and the release is an operator evidence door, not a waiver. **Absent**. |
| ### Stripe |
| @@ -42,7 +42,7 @@ Each is concrete. None is waived. |
| 5. **No catalog, portal configuration, webhook endpoint or runtime key exists.** The plan and a print-only script are written. Needs scoped approval, then a test-mode rehearsal, then a real purchase. |
| 6. **The quantity worker's fence is unverified against Stripe.** It rests on documented idempotency rules, modelled by a fake. `TestSandboxQuantityFence` must pass in a Stripe sandbox, under both proration policies, before `CONSOLE_BILLING_QUANTITY_FENCE` is set. Test mode is not authorized, so it has not been run. A pass is not enough by itself: check 5b logs what the worker's own update does with a declining card, and that log has to be read and decided on, because the worker records an addition as charged on any success and sends no `payment_behavior`. Two things it cannot settle and that stay open after it: what Stripe does with a key across an API key rotation, and how Stripe later reconciles a request it answered with a 500. |
| 6a. **An ended subscription's operation may need a person every time.** If Stripe refuses the fence request on a canceled subscription's item (the sandbox run logs what it answers), every canceled team subscription with an unconfirmed operation waits on a resolved review, and until then the account's quantity work is held, under a later subscription too. That needs a code decision from the sandbox log before the worker is switched on. |
| -7. **Defect, open: an old quantity request can run after Stripe has forgotten its key.** Stripe forgets keys after 24 hours. A sender frozen longer than that can still land a request for an operation that was retired and replaced. On the launch branch that is only detected after the write (`billing_quantity_lowered`), which is not a fix. The fix is **partial, unwired into this branch**, on `feat/carloku-late-request-fencing-20261001` (`8ca8cd6b`, on the forge; the full local gate passes on it; design in `docs/superpowers/plans/2026-10-01-late-request-fencing.md`): a transport in which a request cannot outlive its connection, with tests. Its first review (both reviewers, at `1772e840`) rejected it. Five findings are fixed on the branch (a send deadline is one absolute instant fixed before the lease or authorization, on both paths; the lookup past the replay window no longer voids, and records and reviews what it finds; a void needs the invoice's whole identity and a real subtotal; the void's key changes with the hour, so a remembered failure cannot block it for a day). The rest is open there (`DISPOSITIONS-late-request-fencing.md` on that branch), and one finding limits the design itself: the provider's idle-connection limit bounds when a request can begin to be written, not when a complete request is received (a sender frozen after the headers and before the body, or bytes already in the kernel, are not covered). So this branch does not close this item as designed. The path that could cause the defect, the quantity worker, stays disabled until there is a supported provider-side bound on a complete request, or a design that does not need one. Nobody is asked to accept this risk. |
| +7. **Defect, open: an old quantity request can run after Stripe has forgotten its key.** Stripe forgets keys after 24 hours. A sender frozen longer than that can still land a request for an operation that was retired and replaced. On the launch branch that is only detected after the write (`billing_quantity_lowered`), which is not a fix. The fix is **partial, unwired into this branch**, on `feat/carloku-late-request-fencing-20261001` (`1b61de82`, on the forge; the full local gate passes on it; design in `docs/superpowers/plans/2026-10-01-late-request-fencing.md`): a transport in which a request cannot outlive its connection, with tests. Its first review (both reviewers, at `1772e840`) rejected it. Five findings are fixed on the branch (a send deadline is one absolute instant fixed before the lease or authorization, on both paths; the lookup past the replay window no longer voids, and records and reviews what it finds; a void needs the invoice's whole identity and a real subtotal; the void's key changes with the hour, so a remembered failure cannot block it for a day). The rest is open there (`DISPOSITIONS-late-request-fencing.md` on that branch), and one finding limits the design itself: the provider's idle-connection limit bounds when a request can begin to be written, not when a complete request is received (a sender frozen after the headers and before the body, or bytes already in the kernel, are not covered). So this branch does not close this item as designed. The path that could cause the defect, the quantity worker, stays disabled until there is a supported provider-side bound on a complete request, or a design that does not need one. Nobody is asked to accept this risk. |
| 8. **Stripe's treatment of a proration date outside the period** is assumed from documentation. Same sandbox run. |
| 9. **Defect, open: a late invoice-line request can leave a finalized invoice with a wrong total.** Past Stripe's key memory a stale line request runs as new. If it lands between the engine's line check and the finalize, the invoice is finalized with a duplicate line. The engine flags it and will not charge it, but a finalized invoice is open at Stripe, and an open invoice can be paid by the customer from Stripe's hosted page or the portal. That is customer-payable exposure and it is treated as such. Prevention is the same transport as item 7, at the same stage and with the same limit its first review found (**partial, on the fencing branch, rejected at first review**): as designed it bounds when a request can begin to be written, not when it is received whole. That branch also voids such an invoice when it finds one; that is remediation after the fact (the invoice is payable until the void lands, and a customer who pays first is owed a refund), the review found faults in the void itself that are open there, and it does not close this item. Billing stays OFF, so invoice writes are disabled until the prevention is proven. |
| @@ -65,7 +65,7 @@ Each is concrete. None is waived. |
| 19. **No review of the whole branch has passed.** Astra rejected rounds one to sixteen; Opus accepted each with fixes. Round seventeen read only the diff since round sixteen: Opus accepted, Astra accepted with fixes (one P2, fixed since and unconfirmed). That is not a pass of the branch: the last whole-branch reading was round sixteen's, and it was rejected. Every round has closed the shapes the round before reported and found neighbouring ones, in the store walks since round seven. Some concern records no walk of this build writes; others need only this build's ordinary walks (a failed rotation, a retained teardown, a scanning door racing a teardown), and two were faults in the previous round's own fixes. Round eleven found one P1 and two P2 in the store walks (a grant could move an older record to another bucket name; a waiting rotation ignored a grant that ran; the user and its policy were written before the grant was counted). Its fixes are on the launch branch (`1395f7bf`). Round twelve read them: every round-eleven finding is closed for its reported shape, Astra rejected again (one P1, two P2) and Opus accepted with fixes (one P2, three P3). The new findings were about records no walk of this build writes (a teardown note for another bucket, a record naming two buckets) being acted on by teardown, rotation and the scanning doors; a rotation started after a grant that failed at its last write; and a take-back that returned access to a bucket another account holds, through the member's own door. Round thirteen read those fixes: closed for their reported shapes, Astra rejected again (two P1, four P2) and Opus accepted with fixes (one P2, five P3). The new findings were paths that read such a record and acted without the check (the holder inventory, the storage pass, the declare door), a rotation's own failed last write, and a retained record blocking another account's take-back. The check now sits in the record's reader and writer. Round fourteen read those: closed for their reported shapes; Astra rejected (two P1, two P2), Opus accepted with fixes (two P2, two P3). Round fifteen read those: all closed; Astra rejected (one P1, one P2), Opus accepted with fixes (one P2, two P3), all about readers of a bucket that a retained teardown left to another account (a sweep in flight, the scan status, the storage pass). Round sixteen read those: all closed, and one of them had made a single store under teardown hold storage for every account. Astra rejected (one P1, two P2), Opus accepted with fixes (one P1, one P2, two P3). The storage hold is now per account; two findings are left open as 19f and 19i. Those fixes are on the launch branch and unconfirmed until the next round reads them. Each round's fixes are on the launch branch, gated locally, and unconfirmed until the next round reads them. |
| 19g. **Refusals whose doors say the wrong thing, and records only a person can repair.** A record that names two buckets (`ErrTwoBuckets`) or whose teardown note is about another bucket (`ErrUnfinishedTeardown`) is refused by the record's one reader and one writer, so nothing acts on it and nothing writes it; the settings page shows such a store as unreadable. No walk of this build writes either; whether an earlier build left such records in production has not been checked. There is no operator verb to repair one. The doors that meet these refusals answer with sentences written for other failures: the grant and provision doors say to run the grant again, the destroy door and the purge say to try again, the scanning doors say to try again or to re-run the grant. The same goes for a rotation refused because a grant must be run again first (`ErrGrantUnfinished`) and for a member's take-back refused because another account holds the bucket (`ErrBucketHeld`). Correct copy for each needs approval (A). |
| -19i. **A live bucket shared by two stores is sized in full for each of them.** The daily storage pass lists the whole bucket for every store record that names it, so two accounts on one operator-adopted bucket would each carry all of its bytes. It predates this branch. Open here. A fix is on `feat/carloku-storage-sole-holder-20261001` (`09520a62`, full local gate passes): the pass sizes a store only when it is the sole holder of its bucket and holds it, for its own account, otherwise. It has been read five times. Astra rejected the first four and Opus accepted each with fixes; the fifth reading, of the last diff, was accepted with fixes by both, P3 only, and those small fixes are in `09520a62`, unread. It is not merged into this branch. Its own open items are in 19i on that branch. With it, a store on a shared bucket is held every day until a person acts, and a departed store's leftover objects hold the remaining store until Paul rules whose bytes they are (approval K). |
| +19i. **A live bucket shared by two stores is sized in full for each of them.** The daily storage pass lists the whole bucket for every store record that names it, so two accounts on one operator-adopted bucket would each carry all of its bytes. It predates this branch. Open here. A fix is on `feat/carloku-storage-sole-holder-20261001` (`4ed6b71e`, full local gate passes): the pass sizes a store only when it is the sole holder of its bucket and holds it, for its own account, otherwise. It has been read six times. The fifth reading, of a diff, was accepted with fixes by both reviewers. The sixth, of the whole change, was accepted with fixes by Opus and rejected by Astra on one P1 (an older grant block that names no bucket was left out of the inventory), which is fixed in `4ed6b71e` and unread. It is not accepted and not merged into this branch. Its own open items are in 19i on that branch. With it, a store on a shared bucket is held every day until a person acts, and a departed store's leftover objects hold the remaining store until Paul rules whose bytes they are (approval K). |
| 19h. **A rotation whose delivery fails is repaired by a grant, which swaps the app's key with no overlap.** A failed delivery may still land, so the record stays marked, the next rotation is refused, and the grant run again replaces whichever key the app holds. Hosts hold a dead key until they adopt the new config. Before this branch such a rotation was resumed by running it again, which kept the overlap when the delivery had not landed and broke the app when it had. A repair that waits out the signing window and then reads which key was delivered would keep the overlap where the window is enforced (observed on AWS only, 19d); it is not built. |
| 19f. **A store that leaves a bucket with an unsupported name does not hand on its scanner debt.** There is no ledger for such a name. The last holder would delete the bucket and leave a scanning plan behind. Today's scanner (ClamAV) has no plan to leave, so this is latent. Also latent for the same reason: the scan grant door checks that no teardown has begun and then enables scanning as two steps, so a retained teardown landing between them would leave scanning enabled on the other account's bucket with nothing recording that it is owed. And the scan queue's drain checks permission once per batch, so a drain admitted before a retained teardown could return the other account's object metadata; nothing calls the drain or enqueues today, and it must be fixed before the queue is wired. |
| 19e. **A purge can end with a store that was granted during it.** A declare and a grant admitted while the app was live can land between the purge's last check and the removal of its marker. The purge now reports that as an error and never deletes the record, but it does not prevent it: the doors check liveness when they admit a request, not when they write. And after that error the estate is named only by its record and a log line. The app's console row is still trashed, so the settings page and the store-destroy door answer 404 and a second purge answers "not trashed", until the console restarts and restores the row from the record. The flash the member sees says "Nothing was deleted", which is false in this case; correct copy needs approval (A). |
| @@ -73,7 +73,7 @@ Each is concrete. None is waived. |
| 19c. **S3's conditional delete is unverified on a real backend.** The store walks and the app purge delete a record only as the generation they read. That has run against the directory store and an HTTP stub. No `If-Match` delete has been sent to AWS or to an S3-compatible store, and a backend that ignored the header would delete unconditionally. It needs one write to a scratch object, which is a production-adjacent write nobody has approved. |
| 19d. **The signing-time fence has been observed on AWS only.** An S3-compatible deployment or store endpoint has not been probed for its window. |
| 19a. **A retained teardown finishes only when someone runs it again.** Nothing runs it. A store that left a bucket to another account keeps its record until then. Until then its scanning shows no coverage and its storage is held each day, for its own account only, not measured: the bucket's bytes are the other account's. A day written as held stays held for that account; there is no rebuild door (item 18). |
| -20. **Amadan CI has passed on `1395f7bf`, `d0a21aa1`, `d5705a63`, `973a9f15`, `abc9f781`, `86a1849d`, `cd8821c6` and `c1cf8822`.** It sat queued on every tip all night and first ran at 07:34 Dublin on 2026-10-01. Any later code tip needs its own run; the local gate (build, vet, gofmt, `make test`, cross builds) is not CI and is not offered in its place. An agent account can neither see nor manage the runners. The hub's `carlos/platform` repository also answered 500 on and off through the night; bundles of every tip are in the run directory. |
| +20. **Amadan CI has passed on `1395f7bf`, `d0a21aa1`, `d5705a63`, `973a9f15`, `abc9f781`, `86a1849d`, `cd8821c6`, `c1cf8822` and the handoff-only tips after it up to `a78d5982`.** It has not run on any side branch. It sat queued on every tip all night and first ran at 07:34 Dublin on 2026-10-01. Any later code tip needs its own run; the local gate (build, vet, gofmt, `make test`, cross builds) is not CI and is not offered in its place. An agent account can neither see nor manage the runners. The hub's `carlos/platform` repository also answered 500 on and off through the night; bundles of every tip are in the run directory. |
| 21. **A scanner backend that calls a provider must be fenced like the walks.** Today's scanner (ClamAV) makes no provider call at teardown. A native one would, and its client would need the fenced signer. |
| ## Approvals to ask for, each with its exact scope |