carlos / platform Public

The handoff and the outstanding list record the first reviews of all three side branches; none passed

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 8897e9530c3a8652ca089395534b91f6912ea0e8 parent 551e32c
2 files changed, +15 −13
  • .claude/HANDOFF.md +11 −10
  • implementation/carloku-paid-launch/OUTSTANDING.md +4 −3

CI passed — run details

diff --git a/.claude/HANDOFF.md b/.claude/HANDOFF.md
index 8e28737a6..067636710 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 09:52 Dublin on 2026-10-01. Three things, kept apart.
+Written 10:15 Dublin on 2026-10-01. 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 09:31 Dublin.
+All three review servers answered 200 on the IP form at 10:00 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.
@@ -29,22 +29,23 @@ Independent review. No review of the whole branch has passed. GPT-6 Astra reject
Two open defects, both with their paths disabled, neither offered as a risk to accept: a quantity request that runs after Stripe has forgotten its key, and a late invoice-line request that can leave a finalized invoice with a wrong total a customer could pay. The design meant to remove both is `docs/superpowers/plans/2026-10-01-late-request-fencing.md`; its first review found that, as designed, it does not (below).
-Side branches, all on the forge, each with the full local gate passing on the named tip (base `d5705a63`), none run through CI, nothing on the launch branch calls them:
+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` (`a64517ba`): a Stripe request cannot outlive its connection, and a void for a wrong-total invoice (remediation only). Reviewed once by both reviewers at `1772e840`: both rejected it. Two shared findings are fixed in `a64517ba` (a send deadline is one absolute instant fixed before the lease or authorization, on both paths). The rest is open in `DISPOSITIONS-late-request-fencing.md` on that branch. 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.
-- `feat/carloku-metered-replicator-20261001` (`ebab1a37`, not reviewed): path B, first build. A metered replication store with no unmetered fallback, an owner for every database the box replicates, a fleet store that refuses anything it cannot meter. Nothing attests. Code map: run directory `notes/path-b-replicator-code-map.md`.
-- `feat/carloku-bucket-hour-evidence-20261001` (`58c1870c`, not reviewed): the operator evidence door for a store's partial first hour. The hour still holds by default; the door releases only that hour, only for the owner the ledger names, on a named person's recorded evidence.
+- `feat/carloku-late-request-fencing-20261001` (`157f0de8`, 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`. Four findings are fixed since. 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 items: `DISPOSITIONS-late-request-fencing.md` on that branch.
+- `feat/carloku-metered-replicator-20261001` (`40558c1d`; code `ebab1a37`, full local gate passes): path B, first pieces. Both reviewers rejected it: the owner of a database is resolved once and never re-checked, and paths are compared as text, so a symlink can bill one tenant for another's database. Nothing fixed yet. `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-scoped-attestation-20261001` (`058ea506`): path A, parked. It cannot prove an exclusive writer. Replication-write completeness is a launch blocker, not waived.
**NEEDED:**
-- Paul: approve or edit both copy reviews; confirm the HALF code word; decide the proration policy; approve or change the whole-paid-day rule for partial months; review copy for the store refusals (`OUTSTANDING.md` 19g). No ruling is asked for on a store's first clock hour or a box's first minutes: they hold by default, and what releases one is an operator evidence door, not a waiver.
+- Paul: approve or edit both copy reviews; confirm the HALF code word; decide the proration policy; approve or change the whole-paid-day rule for partial months; review copy for the store refusals (`OUTSTANDING.md` 19g); rule on what counts as evidence for a held bucket-hour (approval J). No ruling is asked for on a store's first clock hour or a box's first minutes: they hold by default, and what releases one is an operator evidence door, not a waiver.
- Scoped approvals, prepared as plans only: Stripe test mode, to run `TestSandboxQuantityFence`; the `rk_live` restricted key and Stripe catalog; the Cost and Usage Report export; one scratch-object write to check S3's conditional delete. Exact scopes are in the approvals table of `OUTSTANDING.md`.
**RECOMMENDED:**
-- Decide what bounds a complete late request at Stripe (a documented server-side request timeout, or a design that does not depend on one). Until then the fencing branch's remaining findings are worth fixing only for the void and the tests.
+- Replicator branch: fix the two P1s (bind ownership to the registry generation and re-check it; compare files by identity, not path text), then the rest of its dispositions.
+- Decide what bounds a complete late request at Stripe, or redesign so nothing depends on it. The fencing branch's remaining items are the void's fixed key, the sandbox probe and three transport tests.
+- Evidence door: after the ruling, withdrawal by entry, audit correctness, a canonical pin, and the refusal of a withdrawal that would invalidate a closed month.
- Have the whole launch branch read again at its tip, not a diff, before anything is called accepted.
-- Review the other two gated side branches (metered replicator, bucket-hour evidence).
-- Then, each on its own branch: the agent wiring and restore path for path B, the evidence door for a box's first minutes, quantity reduction at renewal, the storage pass using the holder inventory (19i), the AWS principal inventory and the bucket ownership attestation door, Free-tier enforcement, dormancy and pool accounting.
+- Then, each on its own branch: the storage pass using the holder inventory (19i), 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.
**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`), and two review processes may still be running. Scratch left on the box: `~/.cache/tmp/claude-1001/{mutcopy,fencing-wt,replicator-wt,evidence-wt}` (the last three are git worktrees), `/tmp/k`, `~/.cache/carloku-gate`.
diff --git a/implementation/carloku-paid-launch/OUTSTANDING.md b/implementation/carloku-paid-launch/OUTSTANDING.md
index 7dc5663b2..708127eca 100644
--- a/implementation/carloku-paid-launch/OUTSTANDING.md
+++ b/implementation/carloku-paid-launch/OUTSTANDING.md
@@ -32,9 +32,9 @@ Each is concrete. None is waived.
### Meters (the complete metered model cannot invoice until both are proven)
-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**, on `feat/carloku-metered-replicator-20261001` (`ebab1a37`, 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. **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.
+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**, on `feat/carloku-metered-replicator-20261001` (`40558c1d`, on the forge; the full local gate passes on its code, `ebab1a37`; first review: both reviewers rejected it, on an owner resolved once and never re-checked and on paths compared as text, among others; nothing fixed yet, see `DISPOSITIONS-metered-replicator.md` on that branch): 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. **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` (`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. Not reviewed, 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` (`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.
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` (`a64517ba`, 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. Two shared findings are fixed on the branch (a send deadline is now one absolute instant fixed before the lease or authorization, on both the quantity and the invoice path). 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` (`157f0de8`, 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. Four 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 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.
@@ -90,6 +90,7 @@ Nothing below was assumed overnight. None of it has been done. No row asks anyon
| F | Stripe live provisioning | Products, prices, portal configuration, webhook endpoint and an `rk_live_` runtime key, exactly as `stripe-provisioning.md` lists them | A test purchase, then a real one. After A |
| G | AWS, read-write, scoped | Create the Cost and Usage Report data export in the collector plan. Separately: write, conditionally delete and remove one scratch object in the deployment bucket, to check that S3 honours `If-Match` on a delete (item 19c) | The store transfer meter's source; the conditional delete the store walks rely on |
| H | Box change | Path B on a dev box: replace the external replicator with the platform's own, including which user holds the replica credentials. Not ready to ask for: the code is partial and unwired (item 1) | The replication meter |
+| J | What counts as evidence for a held bucket-hour | Whether an operator's entry must carry a retained artifact (which trail, which query, which interval) and whether a second person must approve it before it stands. The door as built takes free text from one operator | Whether the evidence door can ever release a store's first hour. Until ruled, it releases nothing |
| I | Merge | None requested. No review round has passed | |
## Tested on this branch, not proven