Record review round four, its dispositions, the AWS billing read and two decisions
The Astra and Opus round 4 reviews are committed unedited, with the dispositions for each finding. The collector plan records a read-only look at the flagship account's billing: no export exists, S3 carried only Usage lines from July to September (no credits or discounts), no free transfer allowance reaches the account, Ireland's usage types are written EU-, and inter-region transfer out of Ireland grew forty-fold in September. The attestation plan records the choice of the scoped path, what is built and tested, and the four steps left before any box may attest. The partial-month plan says plainly that the whole-paid-day rule is not in the approved spec, which speaks only of prorating the allowance, and needs Paul's approval; it lists what the rule rounds away and the tests that pin its boundary. Handoffs and the requirements audit are refreshed.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
9 files changed,
+398
−31
.claude/HANDOFF.md+7 −7docs/superpowers/plans/2026-10-01-durability-attestation-path.md+20 −1docs/superpowers/plans/2026-10-01-partial-month-billing.md+25 −4docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md+8 −1docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md+46 −1docs/superpowers/specs/CODEX-FINDINGS-carloku-paid-launch-overnight-round4.md+118 −0docs/superpowers/specs/OPUS-REVIEW-carloku-paid-launch-overnight-round4.md+158 −0implementation/carloku-paid-launch/AGENT_HANDOFF.md+12 −13implementation/carloku-paid-launch/requirements-audit.json+4 −4
diff --git a/.claude/HANDOFF.md b/.claude/HANDOFF.md| index cac9fbc46..5c672548f 100644 |
| --- a/.claude/HANDOFF.md |
| +++ b/.claude/HANDOFF.md |
| @@ -7,17 +7,17 @@ |
| 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:** |
| -Code tip c3913dd9 (later commits are documents only). On that commit: `go build`, `go vet`, gofmt and `make test` passed outside the sandbox (60 packages ok, log `logs/gate-round3-fixes.txt` in the run directory). Cross builds and Amadan CI for the tip: see the Amadan branch handoff, which is updated when they are read. Independent review: GPT-6 Astra rejected rounds 1, 2 and 3 (ten, eight, five findings); the AGENTS-required Opus production review accepted with fixes in rounds 2 and 3 (eight findings each). Every finding was accepted and fixed with a reproduction (`docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md`). Round four of both runs against the tip; nothing lands until it passes. Landed in this run: console GET billing page, signup and billing demo harness, durability epoch race fix, unmetered-fallback escapes, AWS Cost and Usage Report transfer collector with bucket ownership ledger, statement folds for both new meters, partial-month billing on whole paid days, operator doors for review holds and the house marker, team quantity worker behind an unset policy switch, Stripe provisioning plan and print-only script. Review servers running on docs-t1, each answering 200 on its IP form at 02:00 on 2026-10-01: pricing http://docs-t1.tail5fd3ba.ts.net:38009 (fallback http://100.119.180.57:38009), console billing page http://docs-t1.tail5fd3ba.ts.net:45033 (fallback http://100.119.180.57:45033), signup and billing demo http://100.119.180.57:41881. The tailnet hostname was not verified from this box. Billing is OFF. No AWS, Stripe or production change was made. |
| +The exact tip, its gate result and its CI result are in the Amadan branch handoff, which is rewritten at each checkpoint; this file names what the work is. Independent review: GPT-6 Astra rejected rounds 1 to 4 (ten, eight, five, five findings); the AGENTS-required Opus production review accepted with fixes in rounds 2 to 4 (eight findings each, all P3 in round 4). Every finding was accepted and fixed with a reproduction (`docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md`). Round five runs against the tip; nothing lands until it passes. Landed in this run: console GET billing page, signup and billing demo harness, durability epoch race fix, unmetered-fallback escapes, AWS Cost and Usage Report transfer collector with bucket ownership ledger, statement folds for both new meters, partial-month billing on whole paid days, operator doors for review holds and the house marker, team quantity worker behind an unset policy switch, a teardown guard for shared buckets, the console half and scope computation of a scoped replication attestation (unwired), Stripe provisioning plan and print-only script. Review servers on docs-t1, each answering 200 on its IP form at 01:50 Dublin time on 2026-10-01: pricing http://docs-t1.tail5fd3ba.ts.net:38009 (fallback http://100.119.180.57:38009), console billing page http://docs-t1.tail5fd3ba.ts.net:45033 (fallback http://100.119.180.57:45033), signup and billing demo http://100.119.180.57:41881. The tailnet hostname was not verified from this box. Billing is OFF. No AWS, Stripe or production change was made; AWS was read once (one Cost Explorer query and two list calls on the flagship account). |
| **NEEDED:** |
| -- Paul: approve or edit both copy reviews; confirm the HALF code word; decide the proration policy (`CONSOLE_BILLING_PRORATION` stays unset until then). |
| -- Scoped approvals, prepared as plans only: the rk_live restricted key and Stripe catalog (`implementation/carloku-paid-launch/stripe-provisioning.md`); the Cost and Usage Report export (`docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md`); Stripe test mode, to confirm the provider refuses a proration date outside the current period. |
| -- A read of the AWS billing console: does account 271376211898 carry credits or discounts on S3 transfer? If so the transfer meter never completes as built. |
| -- A choice of attestation path for replication writes (`docs/superpowers/plans/2026-10-01-durability-attestation-path.md`). |
| +- Paul: approve or edit both copy reviews; confirm the HALF code word; decide the proration policy (`CONSOLE_BILLING_PRORATION` stays unset until then); approve or change the whole-paid-day rule for partial months (`docs/superpowers/plans/2026-10-01-partial-month-billing.md`, "What the approved spec says"). |
| +- Scoped approvals, prepared as plans only: the rk_live restricted key and Stripe catalog (`implementation/carloku-paid-launch/stripe-provisioning.md`); the Cost and Usage Report export (`docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md`); Stripe test mode, to confirm how the provider treats a proration date outside the current period. |
| +- A decision on a store's first clock hour: an operator release for a held bucket-hour, or the platform absorbs it (collector plan). |
| **RECOMMENDED:** |
| -- Read the round-four reviews, fix what they find, re-review the exact tip. |
| -- Then: the AWS principal inventory and the bucket ownership attestation door, quantity reduction at renewal, a `carlos` verb and docs for the operator doors, Free-tier enforcement, dormancy and pool accounting (none started). |
| +- Read the round-five reviews, fix what they find, re-review the exact tip. |
| +- Then: the reader and agent call for the scoped attestation, the AWS principal inventory and the bucket ownership attestation door, quantity reduction at renewal, a `carlos` verb and docs for the operator doors, Free-tier enforcement, dormancy and pool accounting (none started). |
| +- Find what moved 1,395 GB out of Ireland to three other regions in September (collector plan); it is the largest S3 transfer line on the account and grew forty-fold in a month. |
| **SESSION:** |
| Not safe to close: three 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. |
diff --git a/docs/superpowers/plans/2026-10-01-durability-attestation-path.md b/docs/superpowers/plans/2026-10-01-durability-attestation-path.md| index 0bdab3adb..4e84e93b4 100644 |
| --- a/docs/superpowers/plans/2026-10-01-durability-attestation-path.md |
| +++ b/docs/superpowers/plans/2026-10-01-durability-attestation-path.md |
| @@ -1,6 +1,6 @@ |
| # Replication writes: how a box could honestly attest |
| -Date: 2026-10-01. Status: the meter folds and holds; no production box attests; nothing here flips that. |
| +Date: 2026-10-01. Status: the meter folds and holds; no production box attests; nothing here flips that. Path A is chosen and its console half and scope computation are built and tested locally (see "Decision and progress"). The agent does not call any of it. |
| ## Where the meter stands |
| @@ -31,6 +31,25 @@ The external Litestream binary is the one writer that makes the attestation fals |
| The flag may be set only by code that checks its own premise at startup: no `carlos-litestream.service` running the external binary (B), or the exclusion set computed from the registry under a witness (A). A host test must show that a box with a unit-backed route and the external replicator present publishes a day that is not complete for that route's owner. No test may set the flag to make a billing test pass. |
| +## Decision and progress (2026-10-01) |
| + |
| +**Path A is the one to build first.** It is native to the platform, it needs no change to a root unit, and the evidence it rests on is all on the box: the registry and the external replicator's own config. Carloku's paid plans meter awake hours, so the tenants they bill run hibernating exec routes, and those are exactly the routes the activator replicates through the ledger. Path B is still needed before an always-on or unit-backed tenant can be billed for writes; until then such an account's month holds. |
| + |
| +Built and tested on the branch, with no effect in production: |
| + |
| +- **The fold counts durability days per account.** A box-day attested with an exclusion set is complete for every account the box did not exclude. `usageSweep.DurabilityExcluded` carries the excluded days and each statement's `SourceDays` is reduced for its own account only (`durabilityfold.go`, `accountSourceDays`). `TestDurabilityFoldScopedAttestationHoldsOnlyTheExcludedAccount` pins it, including two boxes of which one excludes and an unattested box. |
| +- **The scope computation** (`internal/host/durabilityscope.go`, `durabilityScope`). It excludes the owner of every unit-backed route, of every exec route that records a database and does not hibernate, and of every route whose database the live config names. It attests nothing when the replicator's state cannot be read, when the config names a database no route owns, or when the unit has been running since before its config was last written. `TestDurabilityScope` pins each rule. |
| +- **The test this plan required first.** `TestScopedAttestationPublishesADayIncompleteForTheUnitOwner`: a box with a unit-backed route and the external replicator present publishes a day that is not complete for that route's owner, and is complete for the owner of a hibernating exec route. |
| + |
| +Not built, in the order it should be: |
| + |
| +1. The reader of the replicator's state: the config's paths, its modification time, and the unit's start time from systemd. It must refuse a config it did not fully account for (`ops.ParseLitestreamDBs` reads only the generated shape), and resolve the console database path the way the generator does. |
| +2. The agent's call, on open and before every seal: compute the scope, and exclude any account that has newly appeared from the earliest instant the external replicator could have known its database (the config's modification time), through `DurabilityLedger.Escaped`. The call must be behind an explicit switch that is off by default. |
| +3. An independent review of 1 and 2. This is the code that makes attestation read true. |
| +4. A scoped approval to set the switch on the flagship, after a dev box has run with it for a week and its published days have been read by hand. |
| + |
| +What an excluded account sees: its replication-write meter never completes, so the monthly freeze refuses its month and it is billed nothing. Whether such an account should instead be billed its other four meters with writes left out is a product decision this plan does not make. |
| + |
| ## Open decisions |
| - Whether LIST requests, which S3 prices at the write tier, should count. They do not today. |
diff --git a/docs/superpowers/plans/2026-10-01-partial-month-billing.md b/docs/superpowers/plans/2026-10-01-partial-month-billing.md| index 2b4ce2c7c..d516629a5 100644 |
| --- a/docs/superpowers/plans/2026-10-01-partial-month-billing.md |
| +++ b/docs/superpowers/plans/2026-10-01-partial-month-billing.md |
| @@ -1,6 +1,6 @@ |
| # Billing a month the paid plan covers only partly |
| -Date: 2026-10-01. Status: built on `feat/carloku-paid-launch-20260916`, awaiting independent review. Required work, not a waiver: the complete metered model must bill a first month that starts mid-month, a month a subscription ends in, and a free-to-paid change, correctly. |
| +Date: 2026-10-01. Status: built on `feat/carloku-paid-launch-20260916` and reviewed in round four. **The rule for which usage counts is not in the approved spec and needs Paul's approval before it bills anyone** (see "What the approved spec says"). Required work, not a waiver: the complete metered model must bill a first month that starts mid-month, a month a subscription ends in, and a free-to-paid change, correctly. |
| ## What happened before this was built |
| @@ -8,6 +8,20 @@ Date: 2026-10-01. Status: built on `feat/carloku-paid-launch-20260916`, awaiting |
| It refuses for a real reason. A statement holds one total per meter for the month. With usage as a single monthly number, there is no way to say how much of it fell inside the paid part, and charging overage against usage from the free part would bill people for what Free allowed. |
| +## What the approved spec says, and what it does not |
| + |
| +The pricing spec (`2026-09-07-carloku-pricing-plans-design.md`, "Entitlement assignments are effective-dated") says: "A within-month change prorates the allowance by the days each assignment was in force, matching how Stripe prorates the subscription itself." That covers the allowance, and the code does it, weighting each paid span by its exact share of the month. |
| + |
| +The spec says nothing about which usage is billed when the plan covered only part of the month. The whole-paid-day rule below is this branch's answer, chosen because it can never bill usage from an unpaid hour. It is a proposal until Paul approves it. What it costs and what it gives away: |
| + |
| +- Usage on the day a plan starts and on the day it ends is never billed, while the allowance still includes the paid hours of those days. Both round toward the customer, by at most two days' usage a month. |
| +- A plan paid for less than one whole UTC day in a month bills no usage for that month. |
| +- A lapse of any length inside a day (a failed payment recovered an hour later) takes that whole day's usage out. |
| + |
| +The boundary is pinned case by case in `TestBillingCalculationPaidDayBoundaries` (a start exactly at midnight, one nanosecond after, the last minute of a day, an end exactly at midnight, one nanosecond before, a paid-through at noon, a quantity change at noon, the last day of the month, a span inside one day) and `TestBillingCalculationALapseInsideADayTakesTheDayOut`. Each case also checks that the counted days never cover more time than was paid for. |
| + |
| +The alternative, if Paul prefers it, is to bill the boundary days in proportion to their paid hours. That needs hourly meters on the statement and bills an estimate for storage, which accrues by the day. |
| + |
| ## The design |
| Bill only usage that provably fell inside the paid interval, against the allowance prorated to that interval. |
| @@ -28,12 +42,19 @@ What this does not do: bill Free usage. Free is bounded by enforcement, which is |
| ## As built |
| - `plans.AllowanceForMonth` returns `Partial` and the `Covered` paid spans. It refuses only a history it cannot read, a month with no paid span, and paid spans that disagree on the terms version or the house marker. |
| -- `usage.Statement.Days` holds each meter by UTC day. `TestStatementDaysSumToTheMonthlyMeters` pins that the days sum to the monthly totals for every source. |
| +- `usage.Statement.Days` holds each billed meter by UTC day. `TestStatementDaysSumToTheMonthlyMeters` pins that the days sum to the monthly totals for all five billed meters, fed from metrics, edge, storage, a replication ledger and an AWS report. |
| - `billingUsageOnPaidDays` counts a day only when its 24 hours lie inside one paid span. The frozen calculation records the counted days and names its arithmetic `base_units_floor_whole_paid_days_v1`. A statement with no daily meters for a partial month is refused with `billing_statement_days_unusable` and held, never billed on the monthly total. |
| - `TestInvoiceEngineBillsAPartialFirstMonthOnItsPaidDays` bills a subscription that starts mid-month end to end; the renewal tests cover a partial month frozen behind a review. |
| -Not built: point 6. A month with no paid day is still refused by `AllowanceForMonth` (no paid span) and retried quietly; it is never billed, but it is not yet recorded as waived. |
| +- A statement whose daily meters contradict it (a day outside the month, days that do not sum to a billed meter's total) is refused with `billing_statement_days_mismatch`, which the invoice pass logs on every attempt. The days are summed in date order, so the answer is the same on every run. |
| +- Only the five billed meters are recorded by day. The others (CPU, memory, requests, backhaul, fleet) are not. |
| + |
| +Point 6, as built, is two cases. A month with a paid span and no whole paid day prices, counts no usage, and bills nothing through the ordinary invoice floor. A month with no paid span at all is still refused by `AllowanceForMonth` and retried quietly; it is never billed, but it is not recorded as waived. |
| + |
| +Known hold: two subscriptions in one month (a customer cancels on the tenth and subscribes again on the twentieth) now price, then file `billing_invoice_identity_mixed`, which holds the account for an operator. Before this change the month was refused quietly. Invoicing each subscription's part of the month separately is not built. |
| + |
| +The quantity worker dates a seat's assignment at the instant the provider prorates it from, so a seat's charge and its allowance start together even when the request is retried hours later. |
| ## Order |
| -Built after the round-two findings were closed. It changes the frozen calculation that the invoice engine and its recovery tests rest on, so it is in the scope of review round four. |
| +Built after the round-two findings were closed and reviewed in round four. The end-to-end invoice test replaces the production preparation step, as every invoice engine test does; the production gate (verified evidence, every billed meter complete for the whole month) is shown to apply to a partial month by `TestPrepareBillingCalculationRefusesUnprovenMeters`. No test drives a partial month through real evidence end to end, because no fixture can complete all five meters for a month. |
diff --git a/docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md b/docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md| index a9c2e0318..86084da53 100644 |
| --- a/docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md |
| +++ b/docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md |
| @@ -37,7 +37,14 @@ Verification after apply: within 24 hours `billing/cur/carloku-transfer/metadata |
| - Scoped approval for the four changes above, then a first real delivery read end to end. |
| - Existing stores: the four stores already provisioned on the flagship have no ownership ledger, and a re-grant writes one that does not claim completeness, because credentials existed before the ledger did. Their charged transfer holds the month until an operator attests each bucket's history (who has ever been granted it). That door does not exist yet and must be designed: it grants billing authority. |
| - Confirm against the first real report that usage types, resource ids and the invoice id behave as the fixtures assume, in particular how the 100 GB free allowance is written across buckets. Anything unexpected arrives as `store_egress_unclassified_charge`, never as a bill. |
| -- **Credits and discounts hold the month.** AWS writes `Credit`, `Refund`, `Fee`, `EdpDiscount`, `PrivateRateDiscount` and `BundledDiscount` lines on the same transfer usage types as the usage they adjust. Any such line with a non-zero cost holds store transfer for the month for every account (`transfer_adjustment`), because AWS then charged something other than what the usage lines say, and nothing lets an operator release that hold. Before the export is approved, check whether account 271376211898 carries promotional credits, an enterprise discount or a private rate that touches S3 transfer. If it does, the meter will never complete as built, and the classifier needs a ruling on how a discounted byte is charged on before the export is worth creating. This is a read of the account's billing console, not a change. |
| +- **What the account's billing shows (read-only, 2026-10-01).** Account 271376211898 is an organization member account (reached through `OrganizationAccountAccessRole`). It has no Data Export and no legacy Cost and Usage Report. One Cost Explorer query for July to September 2026, S3 only, grouped by record type and usage type, shows: |
| + - **Only `Usage` lines.** No credit, refund, fee or discount line touched S3 in those three months, so the hold below would not have fired. September is still marked estimated. |
| + - **Ireland is written `EU-`, not `EUW1-`**, and us-east-1 has no prefix: `EU-DataTransfer-Out-Bytes`, `EU-APS2-AWS-Out-Bytes`, `DataTransfer-Out-Bytes`. The classifier accepts all of them; `TestRealFlagshipUsageTypesClassify` pins every transfer usage type the query returned. |
| + - **No free allowance reaches this account.** Internet transfer out was charged from the first gigabyte in every month (0.03 GB cost 0.0028 in July). Every tenant byte of transfer out is a charged byte. |
| + - **Inter-region transfer out of Ireland is the large line, and it grew forty-fold**: 34 GB in August, 1,395 GB in September (about 464 GB each to Sydney, London and us-east-1, 27.91 in the month). Three equal streams to the three other regions look like the platform's own bucket being read by boxes there, not tenant traffic. Whatever bucket it is must be in `CONSOLE_STORE_EGRESS_PLATFORM_BUCKETS`, or its charged lines hold every month as unowned. The cause is worth finding for its own sake. |
| + - The raw result is `logs/aws-ce-s3-2026-07..09.json` in the run directory. It was one Cost Explorer request, which AWS bills at one cent. |
| +- **Credits and discounts hold the month.** AWS writes `Credit`, `Refund`, `Fee`, `EdpDiscount`, `PrivateRateDiscount` and `BundledDiscount` lines on the same transfer usage types as the usage they adjust. Any such line with a non-zero cost holds store transfer for the month for every account (`transfer_adjustment`), because AWS then charged something other than what the usage lines say, and nothing lets an operator release that hold. None appeared from July to September 2026 (above). Check again when the export is approved, and at the payer account, where an organization's credits are applied: if one ever touches S3 transfer the meter will not complete as built, and the classifier needs a ruling on how a discounted byte is charged on. |
| +- **A store's first clock hour never resolves.** A ledger answers for hours that begin at or after the instant it began vouching. A charged line in the hour a store was minted in has no provable owner and holds the month, like any other unowned line. With no free allowance in this account, a store that serves a download in its first hour does that. Nothing releases such a hold today. The choices are an operator release door for a named bucket-hour, or a ruling that the first partial hour of a new store is the platform's cost. That is a product decision; until it is made the code holds. |
| - **Existing stores on AWS never complete yet.** A ledger claims completeness only when the provisioner can list every principal whose policy names the bucket and finds none. The AWS provisioner cannot list principals today (the console role has no IAM list permission), so on AWS no ledger claims completeness, new stores included, and store transfer holds. The principal inventory is the first step of the ownership attestation plan (`2026-10-01-bucket-ownership-attestation.md`). |
| - The statements catch-up revisits every month in a 36-month window that is open, was never written, or is missing an account's statement. It costs one read per account per metered month in a console's first pass and nothing after a statement has been seen closed. |
| - The per-month rebuild door for a statement closed before this existed is still missing (requirements audit step 1). |
diff --git a/docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md b/docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md| index e3d0645c5..e709d6ac8 100644 |
| --- a/docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md |
| +++ b/docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md |
| @@ -79,8 +79,53 @@ Not changed, with reasons: |
| Found while fixing, not fixed: |
| -- A teardown retried after a failed `DeleteUser` empties and deletes the bucket named on its record. If another app was granted that name in between, the retry destroys the new owner's bucket. It needs an operator to have adopted a name another app mints, then a failed revocation, then a reuse. It predates this branch and is a data-loss path, not a billing one. It should be filed as its own discussion. |
| +- A teardown retried after a failed `DeleteUser` empties and deletes the bucket named on its record. If another app was granted that name in between, the retry destroys the new owner's bucket. It needs an operator to have adopted a name another app mints, then a failed revocation, then a reuse. It predates this branch and is a data-loss path, not a billing one. It is filed as discussion 191. |
| - Stripe's refusal of a `proration_date` outside the current period is assumed from its documentation and enforced by the fake. Test mode is not authorized in this run. Confirm it there before `CONSOLE_BILLING_PRORATION` is set. |
| - `TestDurabilityHostPublishRegistersIncompleteSource` raced its temp dir removal against the ledger's late writer and failed about once in fifteen runs. The test helper now waits for the writer. Earlier green gates on this branch passed by luck on that test. |
| Operational consequences, unchanged: do not set `CONSOLE_STORE_EGRESS_REPORT_PREFIX` in production until store buckets have an attested ownership history, and do not set `CONSOLE_BILLING_PRORATION` until Paul has decided the policy and renewal reduction exists. New: on AWS no ownership ledger claims completeness until the provisioner can list principals. |
| + |
| +# Dispositions: round 4 (Astra and Opus) |
| + |
| +Reviewed commit `4bbe94b6`. Astra round 4 (`CODEX-FINDINGS-carloku-paid-launch-overnight-round4.md`, unedited): reject, three P1 and two P2. Opus round 4 (`OPUS-REVIEW-carloku-paid-launch-overnight-round4.md`, unedited): accept with fixes, eight P3; it found nothing that bills a customer for an unpaid day, bills too small an allowance, bills a day twice, leaks an identifier or lets attestation read true. Every finding was checked against the code. All were accepted. |
| + |
| +| Finding | Disposition | Where | Reproduction | |
| +| --- | --- | --- | --- | |
| +| Astra R1: a retried quantity charge and its allowance start at different instants | Accepted. A quantity change that is the account's outstanding operation landing takes effect at the operation's instant, the proration date the provider was given, whichever path sees it first. When that instant cannot be the assignment's (later history, a frozen month), the assignment is dated when observed and a review holds the account. | `billingservice.go` `reconcileBillingSubscription`, `billingstore.go` `applyBillingStateDated` | `TestQuantityRetryDatesTheAllowanceAtTheProrationInstant` (a retry twenty hours later), `TestQuantityLandingSeenByAWebhookIsDatedAtTheOperation`, `TestQuantityLandingThatCannotBeDatedFilesAReview`. Each fails with its part disabled. | |
| +| Astra R2: the observation hour can bill the new owner for an earlier owner's transfer | Accepted. A ledger answers only for hours that begin at or after the instant it began vouching. | `objstore/ownership.go` `OwnerAt` | `TestObservationHourDoesNotResolveToTheNewOwner` (transfer at 10:05, ledger from 10:40), and the mint-hour cases of `TestOwnerAt`, `TestMintingGrantCreatesACompleteLedger`, `TestCompletenessDatesFromTheObservation`. | |
| +| Astra R3: a missing platform statement hides the oldest tenant month | Accepted. A month is absent only when no account has a statement for it. A missing platform statement in a month that has any statement is an open month. | `console/economicspass.go` `statementMonthState` | `TestStatementCatchUpFindsAMonthWhosePlatformStatementIsMissing`. Fails with the old rule restored. | |
| +| Astra R4, Opus N3: a clock-skewed proration date is replayed for 22 hours | Accepted. The operation's instant is held inside the period (never before its start, and nothing is recorded at or past its end), the compare-and-set refuses a date outside the period, and an operation the provider refuses over its date is retired at once. | `billingquantity.go` `raiseQuantity`, `beginQuantityOperation`, `sendQuantityOperation`; `billingstripe` `Error.RefusedParam` | `TestQuantityOperationIsDatedInsideThePeriodUnderClockSkew`, the date cases of `TestBeginQuantityOperationIsACompareAndSet`, `TestQuantityWorkerCannotChargeAcrossARenewal` (now asserts the operation is retired). | |
| +| Astra R5: day-sum validation depends on map order | Accepted. Days are summed in date order. | `billingcalculation.go` `billingUsageOnPaidDays` | `TestBillingCalculationPartialMonthIsDeterministic`, on Astra's own three values. Fails within a few runs with the sort removed. | |
| +| Opus N1: the compare-and-set does not compare plan, band, terms or item | Accepted. The operation carries `billing_accounts.revision` and the transaction requires it unchanged. | `billingquantity.go` | `TestBeginQuantityOperationIsACompareAndSet`, with a revision case and the subscription clause pinned on its own (the pending addition is rebound so only the subscription differs). Each clause fails alone when removed. | |
| +| Opus N2: a day-sum mismatch holds silently | Accepted. Two errors: `billing_statement_days_unusable` (no daily meters at all, quiet) and `billing_statement_days_mismatch` (the statement contradicts itself, logged by the invoice pass on every attempt). | `billingcalculation.go`, `billinginvoice.go` | `TestBillingCalculationHoldsAPartialMonthOnUnusableDays`. | |
| +| Opus N4: an unreadable statement re-sweeps its month every pass | Accepted. A statement that will not parse is logged once per process and counts as present; it does not make the month open. A store error concludes nothing for the month this pass. | `console/economicspass.go` | `TestStatementMonthStateEdges`. | |
| +| Opus N5: `markOperationLanded` trusts a coincidental quantity | Accepted. The outcome is `landed_unverified`, a new value the audit guard admits. The reverse case (a landed operation's additions labelled `subscription_ended` when the subscription is over) is left: no provider call is made for an ended subscription, so nothing can verify it. | `billingquantity.go`, `billingquantityaudit.go` | `TestQuantityWorkerRecordsALandedOperationAfterARenewal`. | |
| +| Opus N6, and Astra on Opus 4: the hour comparison still holds across an hour boundary | Accepted. A tolerance of five minutes replaces the comparison of clock hours. | `console/durabilityfold.go` | `TestDurabilityFoldHoldsBeforeABoxRegisteredItsLedger`: two seconds across the top of an hour pass, ten minutes and an hour hold. | |
| +| Opus N7: two subscriptions in one month now file a review | Accepted as a known hold and written into the partial-month plan and the handoff. | documents | none | |
| +| Opus N8: the `GranteeProber` contract is a literal string match | Accepted. The interface comment now requires every kind of principal, inline and managed policies, bucket policies and any resource pattern that matches the name, and says the fake is not the contract. | `objstore/provisioner.go` | none | |
| +| Both: the retried teardown that deletes another app's bucket must be guarded, not noted | Accepted and fixed. Teardown reads the bucket's ownership ledger before it destroys anything and leaves the bucket and its scanner alone when another app has an open interval. Its own credentials are still revoked and its interval closed. The last holder's teardown deletes the bucket. Filed as discussion 191. | `objstore/walk.go` `Teardown` | `TestRetriedTeardownLeavesABucketAnotherAppNowHolds`, `TestTeardownOfOneSharerLeavesASharedBucket`. Both fail with the guard removed. | |
| + |
| +Tests the reviewers showed were weak, and what changed: |
| + |
| +- The send-window test stalled after the window's start. It now stalls between the provider read and the recording of the operation, and fails when the window is measured from any later instant. |
| +- The no-inventory test's wrapper also hid the bucket probe. It now keeps the probe and asserts it does. |
| +- `TestStatementDaysSumToTheMonthlyMeters` now feeds all five billed meters, from metrics, edge, storage, a replication ledger and an AWS report, and fails if any is zero. |
| +- Full-month bytes: `TestBillingCalculationFullMonthBytesAreUnchanged` asserts the frozen calculation carries none of the partial-month fields. |
| +- The production preparation gate is shown to apply to a partial month (`TestPrepareBillingCalculationRefusesUnprovenMeters`). No test drives a partial month through real evidence end to end; see the partial-month plan. |
| + |
| +Not changed, with reasons: |
| + |
| +- Atomicity of the mark and the acknowledgement is established by reading the transaction, as Astra says. No test injects a failure between two statements of one SQLite transaction. |
| +- The provider's handling of a proration date (outside the period, equal to its start, ahead of its clock, and whether the refusal names the parameter) is still unverified. Test mode is not authorized. If the refusal does not name `proration_date`, the operation is not retired at once and falls back to the replay limit, which is safe. |
| + |
| +New in this round, not asked for by a finding: |
| + |
| +- `TestRealFlagshipUsageTypesClassify` pins every S3 transfer usage type the flagship account's Cost Explorer returned for July to September 2026. The fixtures' `EUW1-` prefix is one that account never writes; Ireland is `EU-`. |
| +- Partial-month boundary tests (`TestBillingCalculationPaidDayBoundaries`, `...ALapseInsideADayTakesTheDayOut`). |
| +- The scoped attestation's console half and scope computation, unwired (attestation plan, "Decision and progress"). |
| +- `TestMovesPassCheckpointIsMeteredToTheRouteOwner` and its unmetered-fallback twin: the move worker's checkpoint is recorded against the route's owner under the checkpoint and lease purposes. |
| + |
| +Consequences worth knowing: |
| + |
| +- A store's first clock hour never resolves an owner. A charged line in it holds the month, and nothing releases that hold. Dormant on AWS today (no ledger claims completeness there). It needs a decision before the AWS principal inventory lands: an operator release for a named bucket-hour, or a ruling that the first partial hour of a new store is the platform's cost. |
| +- The whole-paid-day rule for partial months is not in the approved spec. It is built and pinned, and it must not bill anyone until Paul approves it. |
diff --git a/docs/superpowers/specs/CODEX-FINDINGS-carloku-paid-launch-overnight-round4.md b/docs/superpowers/specs/CODEX-FINDINGS-carloku-paid-launch-overnight-round4.md| new file mode 100644 |
| index 000000000..087b52235 |
| --- /dev/null |
| +++ b/docs/superpowers/specs/CODEX-FINDINGS-carloku-paid-launch-overnight-round4.md |
| @@ -0,0 +1,118 @@ |
| +## 1. Disposition table |
| + |
| +Reviewed `aed42815..4bbe94b6`, focusing on `e07f6475..4bbe94b6`. Files changed by other work during the review were re-read in full with `git show 4bbe94b6:<path>`. No files were modified, network commands run, or Stripe/AWS CLIs invoked. |
| + |
| +Repository tests were inspected, not executed. “Would pass without the fix” below is a source-based assessment, not a claim that mutation tests were rerun. Memory-only Python reproductions checked the arithmetic and boundary conditions identified below. Line references are to `4bbe94b6`; unqualified filenames in the table are under `internal/console/`. |
| + |
| +| Round 3 finding | Disposition and fix | Reproduction; would it pass without the fix? | |
| +|---|---|---| |
| +| **Astra R1 / Opus 1 — Stale proposal replaces a completed operation** | **Closed for the reported race.** `billingquantity.go:352` takes the membership write lock, checks outstanding operations, re-reads billing state and recomputes the target and pending generation at `:372` and `:384`. | `TestQuantityWorkerRefusesAStaleProposal`, `billingquantity_test.go:591`, now pauses before insertion. **No** with the former conflict behavior. `TestBeginQuantityOperationIsACompareAndSet`, `:638`, also fails without the combined checks, but does not independently pin every condition: removing `Target <= Quantity` still leaves its lower-target case rejected by target recomputation. | |
| +| **Astra R2 / Opus 3 — Renewal between GET and POST charges the wrong period** | **Partly closed.** `billingquantity.go:628` checks the local period end; `:631` sends the persisted date through `internal/billingstripe/client.go:645`. The provider-side precondition remains an assumption. Date creation also lacks a lower-bound check; see R4 below. | `TestQuantityWorkerCannotChargeAcrossARenewal`, `billingquantity_test.go:691`, and `TestQuantityWorkerDatesTheProrationInsideThePeriod`, `:752`: **No** if the date is omitted. Both establish behavior against the fake’s rule at `:66`, not Stripe’s actual boundary semantics. | |
| +| **Astra R3 — Absent bucket retains an unrecorded legacy grantee** | **Closed for surviving credentials.** `internal/objstore/walk.go:202` requires both probes; `:571` records a legacy estate before deleting it. | `TestGrantClaimsNothingWhileAnotherPrincipalNamesTheBucket`, `internal/objstore/ownership_test.go:659`: **No** without the pre-teardown record; after deleting that record again, it also checks the inventory protection. `TestFailedLegacyTeardownLeavesARecordTheNextGrantInherits`, `:709`: **No**, because it requires both intervals. The separate no-inventory test at `:744` is weaker than claimed: its wrapper also hides `BucketProber`, so it would already refuse completeness without the new inventory requirement. | |
| +| **Astra R4 / Opus 7 — Catch-up misses gaps, errors and tenant statements** | **Partly closed.** `economicspass.go:1300` walks the window; `:1382` preserves errors; `:1415` recognizes missing expected tenant statements; `:1375` caches closed statements. The oldest month can still disappear when only its platform statement is missing; see R3 below. | `TestStatementCatchUpReachesAcrossGapsAndPastSixMonths`, `meterfolds_test.go:589`; `…ClosesAHeldMonthBehindAGap`, `:615`; `…WritesAMissingAccountStatement`, `:646`; `…WalksPastAnUnreadableMonth`, `:683`: **No** when their respective protections are restored to the old behavior, including the six-month bound. All retain a platform statement for the oldest recoverable month. | |
| +| **Astra R5 — Crash after marking strands the operation** | **Closed.** Discovery includes outstanding operations at `billingquantity.go:104`; marking and acknowledgement share the transaction at `:236` and `:279`; cancellation acknowledges at `:201`. | `TestQuantityWorkerFindsAnOperationWithNothingPending`, `billingquantity_test.go:830`: **No** without operation discovery. `TestQuantityWorkerClosesAnOperationOfAnEndedSubscription`, `:863`: **No** without terminal acknowledgement. The first test’s completed-call assertion does **not** prove atomicity: it would also pass with two successful, separate commits. Atomicity is established here by inspecting the transaction. | |
| +| **Opus 2 — Landed operation becomes “uncharged” after renewal** | **Closed for the supplied scenario.** `billingquantity.go:674` calls `markOperationLanded`; its update at `:417` restricts marking to the operation’s subscription, original period and generation. | `TestQuantityWorkerRecordsALandedOperationAfterARenewal`, `billingquantity_test.go:782`: **No** without the landed-operation branch. It checks the outcome, reference, absence of an uncharged review and acknowledgement. | |
| +| **Opus 4 — Registration race permanently holds the first day** | **Partly closed.** `durabilityfold.go:79` fixes differences within one clock hour. A two-second difference from `08:59:59` to `09:00:01` still fails that comparison permanently, even if the published ledger covers the required span. | Extended `TestDurabilityFoldHoldsBeforeABoxRegisteredItsLedger`, `meterfolds_test.go:477`, especially `:510`: **No** with exact comparison restored. Its benign race stays inside the same hour; it does not test crossing an hour boundary. | |
| +| **Opus 5 — Completeness begins before the probe** | **Partly closed.** `internal/objstore/ownership.go:270` stores the observation timestamp. `OwnerAt` still accepts the whole hour containing that timestamp; see R2 below. | `TestCompletenessDatesFromTheObservation`, `internal/objstore/ownership_test.go:764`: **No** with grant-time dating restored. It checks an hour a day earlier, not transfer earlier within the observation hour. | |
| +| **Opus 6 — Credits and discounts hold every month** | **Closed as a documentation finding.** `docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md:40` explicitly requires the account check before approval. Actual account applicability remains undetermined. | No regression test applies to the requested operational check. | |
| +| **Opus 8 — Attestation plan assumes a nonexistent ledger union** | **Closed.** `docs/superpowers/plans/2026-10-01-durability-attestation-path.md:28` now describes the single-ledger limitation and the work required for another ledger. | No executable regression applies to this prose correction. | |
| + |
| +Additional limits on the verification claims: |
| + |
| +- `TestQuantityWorkerMeasuresThePauseFromTheProviderRead` (`billingquantity_test.go:558`) sleeps inside `quantityBeforeSend`. It still passes if the caller supplies `time.Now()` immediately before entering `sendQuantityOperation`, because the sleep happens afterward. It does not establish that time spent in the provider GET or before insertion counts. |
| +- `TestStatementDaysSumToTheMonthlyMeters` (`meterfolds_test.go:709`) supplies no durability or store-transfer activity and requires only one nonzero billed meter. Separate tests check one day of each omitted source, but the named conservation test does not exercise every source. |
| +- `TestBillingCalculationOwnsSnapshotAndDeterministicBytes` (`billingcalculation_test.go:237`) uses a full month without `Days`. It does not test partial-month determinism. The full-month checks at `:169` compare selected fields, not bytes against the previous implementation. |
| +- `TestInvoiceEngineBillsAPartialFirstMonthOnItsPaidDays` (`billinginvoice_test.go:1529`) uses the fixture’s replacement preparation function at `:342`, bypassing production evidence and completeness verification. |
| + |
| +For an unchanged legacy statement without `Days`, source inspection supports unchanged full-month serialization: the new fields are omitted and the original arithmetic remains selected. A partial month with nonzero monthly usage and no `Days` is refused. Whole-month completeness remains enforced by the production preparation path. |
| + |
| +## 2. New findings |
| + |
| +### R1. P1 — Retried quantity charges and resource allowances use different effective dates |
| + |
| +**Where:** [billingquantity.go:631](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/billingquantity.go:631), [billingquantity.go:497](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/billingquantity.go:497), [billingservice.go:470](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/billingservice.go:470), `internal/plans/month.go:143`. |
| + |
| +**Scenario:** A Business subscription starts on September 10 at quantity 10. On September 15 at 02:00, an operation to raise it to 110 is persisted, but the POST never executes. The retry succeeds at 22:00, within the 22-hour replay limit. |
| + |
| +The retry sends `proration_date=02:00`. Reconciliation receives the new pass’s `now`, so the quantity-110 assignment takes effect at 22:00. This is an ordinary quantity change: no renewal or clock review holds it. The worker marks the additions processed. |
| + |
| +The customer pays for the additional seats from 02:00, while the monthly allowance includes them only from 22:00. For 100 additional Business seats, September’s awake allowance is approximately **472.22 hours too small**: |
| + |
| +`100 × 170 hours × 20 / 720` |
| + |
| +Sufficient paid-day usage therefore incurs roughly €4.72 of additional awake overage, plus any corresponding storage, transfer or write overage. Partial-month day selection does not correct the allowance history. |
| + |
| +**Smallest acceptable fix:** Carry the confirmed operation’s effective proration instant into allowance reconciliation. Apply it only when history order and frozen-month checks permit; otherwise hold for review. Add a failed-first-send/retry-hours-later regression that checks both the provider date and the resulting monthly allowance. |
| + |
| +### R2. P1 — The observation hour can bill the new owner for an earlier owner’s transfer |
| + |
| +**Where:** [ownership.go:337](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/objstore/ownership.go:337), [walk.go:205](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/objstore/walk.go:205), `internal/console/storeegressfold.go:167`. |
| + |
| +**Scenario:** Before ledgers existed, B adopted A’s deterministic bucket name. B downloads data at 10:05. An older teardown successfully removes the bucket and credentials at 10:10, leaving no ledger. A receives a minting grant at 10:40 through a provisioner supporting both probes. |
| + |
| +Both probes correctly find nothing. The new ledger names A and records `CompleteSince=10:40`. The AWS line covers 10:00–11:00. `OwnerAt` accepts it because `CompleteSince.Before(11:00)` is true and A’s interval touches that hour. |
| + |
| +B’s 10:05 transfer is attributed to A. Present absence proves nothing about who used the name earlier in the same hour. |
| + |
| +This path is dormant on the current AWS provisioner, which lacks `GranteeProber`; the ownership implementation is nevertheless unsafe when both interfaces are available. |
| + |
| +**Smallest acceptable fix:** Refuse the observation hour unless evidence establishes exclusive ownership for the entire charged hour. Otherwise begin resolvable hours at the next UTC hour. Extend the observation test with an earlier owner whose bucket and credentials are both gone before the probe. |
| + |
| +### R3. P1 — A missing platform statement hides the oldest tenant month permanently |
| + |
| +**Where:** [economicspass.go:1394](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/economicspass.go:1394), [economicspass.go:1303](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/economicspass.go:1303), `internal/console/economicspass.go:1575`. |
| + |
| +**Scenario:** September is the first metered month. Its pass writes an open tenant statement, but the platform statement’s write fails. The console then remains down throughout October. |
| + |
| +On resuming in November, the normal pass creates November and October statements. Catch-up classifies September as absent immediately upon failing to find its platform statement. It never examines September’s tenant statement. With no earlier platform statement, `oldest` remains zero and September is not swept. |
| + |
| +Later passes find October as the oldest platform month. September remains outside the inferred metered range forever, despite its retained tenant statement and source evidence. |
| + |
| +**Smallest acceptable fix:** Do not return “month absent” solely from the platform object’s absence. Recognize existing tenant statements when establishing the oldest metered month, or use an independently persisted metering-start boundary. Add a regression where the oldest tenant statement exists but its platform statement does not. |
| + |
| +### R4. P2 — A clock-skewed proration date is retried unchanged for 22 hours |
| + |
| +**Where:** [billingquantity.go:578](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/billingquantity.go:578), `internal/console/billingquantity.go:372`, [billingquantity.go:683](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/billingquantity.go:683). |
| + |
| +**Scenario:** Console B has reconciled a renewal into the shared database. Console A’s clock is three seconds behind. A reads the same renewed subscription and records an operation whose local `CreatedAt` is before `PeriodStart`. |
| + |
| +Neither insertion nor sending checks that lower bound. Under the boundary rule already implemented by the fake, the provider refuses the POST. Once A’s clock catches up, recovery still sends the original invalid date. Every pass continues failing until the operation reaches the 22-hour abandonment limit; only a subsequent pass can create a valid operation. |
| + |
| +A brief clock difference therefore holds the addition and monthly freeze for almost a day. Behavior for equality with the period start, or a date ahead of Stripe’s clock, cannot be established from this repository. |
| + |
| +**Smallest acceptable fix:** Validate the date before persisting an operation. If a provider response definitively establishes that the request did not execute because its date is invalid, retire that operation safely and recompute instead of replaying it until expiry. Test a renewed database period ahead of the sending process’s clock. |
| + |
| +### R5. P2 — Day-sum validation alternates between hold and accept for identical inputs |
| + |
| +**Where:** [billingcalculation.go:156](/home/paulca/amadan.net/carlos/platform-paid-launch/internal/console/billingcalculation.go:156), `internal/console/billingcalculation.go:170`. |
| + |
| +**Scenario:** A partial September statement has three daily egress values of `1000`, `0.1` and `0.2` GB, and a monthly value of `1000.2999989997`. |
| + |
| +The validation sum iterates a Go map. Sequential floating-point addition produces: |
| + |
| +| Addition order | Daily sum | Result | |
| +|---|---:|---| |
| +| `1000`, `0.1`, `0.2` | `1000.3000000000001` | Hold | |
| +| `0.1`, `0.2`, `1000` | `1000.3` | Accept | |
| + |
| +Both outcomes were reproduced with memory-only, sequential binary64 arithmetic matching the code’s additions. The discrepancy sits at the permitted tolerance boundary. Repeating the same statement and history can therefore change whether a calculation is produced at all. |
| + |
| +**Smallest acceptable fix:** Validate and sum days in a fixed order, preferably the same chronological order used for counted usage. Add a partial-month regression at the tolerance boundary. |
| + |
| +### Assessment of the three deferred items |
| + |
| +- **Teardown deleting a replacement owner’s bucket:** This remains a real data-loss defect at `internal/objstore/walk.go:587`. It is wrongly left as merely a note without a protective refusal or a separately tracked fix. The existing test at `ownership_test.go:577` recreates the dangerous interleaving but checks only interval closure; it never checks that the replacement bucket survives. A minimal protection must refuse destructive bucket steps when another current grant owns the name. I could not verify whether a separate discussion exists without network access. |
| +- **Stripe’s date-boundary behavior:** Deferring live verification is appropriate under this run’s restrictions. It remains an explicit prerequisite, not a verified guarantee. The fake accepts equality with period start and does not model all clock-related refusals. |
| +- **Durability test cleanup race:** This was actually changed: `internal/host/durability_test.go:38` waits for late ledger work before cleanup. The source supports that repair; the reported failure frequency and repeated-run stability were not independently verified. |
| + |
| +Unreadable statement JSON also remains a recurring-cost case: catch-up sweeps the month every pass, while `usage.UpsertStatement` refuses to overwrite the corrupt object at `internal/usage/statement.go:98`. Repair requires intervention. The closed-statement cache is consistent with normal irreversible closure; direct deletion or reopening after caching remains invisible until restart or cache invalidation, as its comment acknowledges. |
| + |
| +## 3. Handoff claims the code contradicts |
| + |
| +- **`AGENT_HANDOFF.md:35` — completeness dates from observation.** The stored timestamp does; attribution includes earlier transfer within that same hour, as R2 demonstrates. |
| +- **`:36` — catch-up revisits every open or missing month within 36 months.** R3 leaves the oldest tenant month undiscovered when its platform statement is absent. |
| +- **`:38` — the request dates proration inside its computed period.** `CreatedAt` is taken from the sending process’s clock without checking `CreatedAt >= PeriodStart`; R4 violates that claim. |
| +- **`:40` and `:53` — a month with no paid day is refused and retried.** A subscription beginning September 30 at noon has a paid span but no wholly paid day. `AllowanceForMonth` accepts it, counted usage is zero, and the ordinary invoice floor can waive it. The refusal is for **no paid span**, which is different. |
| +- **`:77` — all findings were fixed with reproductions.** The table identifies remaining partial closures and tests that do not establish their claimed boundaries. |
| + |
| +**Verdict: reject.** |
| \ No newline at end of file |
diff --git a/docs/superpowers/specs/OPUS-REVIEW-carloku-paid-launch-overnight-round4.md b/docs/superpowers/specs/OPUS-REVIEW-carloku-paid-launch-overnight-round4.md| new file mode 100644 |
| index 000000000..9d79576b2 |
| --- /dev/null |
| +++ b/docs/superpowers/specs/OPUS-REVIEW-carloku-paid-launch-overnight-round4.md |
| @@ -0,0 +1,158 @@ |
| +# Opus production and authority review, round 4: Carloku paid launch, `aed42815..4bbe94b6` |
| + |
| +I read the changes in `e07f6475..4bbe94b6` as whole files. The targeted tests pass for plans, usage, objstore and the console (quantity, partial month, statement days, catch-up, durability fold, billing calculation, invoice engine, renewal, store egress). |
| + |
| +I also checked the "fails without the fix" claims. I applied each mutation to an exported copy in `$TMPDIR` and deleted the copy afterwards; nothing in the repo was modified. Eight of the nine mutations failed their named tests, as the dispositions claim. The ninth, the subscription clause of the compare-and-set on its own, did not fail any test (see R1). |
| + |
| +## 1. Disposition table |
| + |
| +| Finding | Status | Fix | Reproduction; fails without the fix? | |
| +| --- | --- | --- | --- | |
| +| Astra R1 / Opus 1: a stale proposal lowers the quantity | **Closed** | `billingquantity.go:358-392` (`beginQuantityOperation`: one outstanding operation; subscription, period, period end, billed quantity, active status, target and generation re-read under the membership lock) | `TestQuantityWorkerRefusesAStaleProposal` and `TestBeginQuantityOperationIsACompareAndSet`. **Partly verified.** The period, quantity, target, generation and outstanding-operation conditions are pinned. The subscription clause alone is not: the "another subscription" case is refused by the generation check, because pending additions for `sub_other` give `Newest=0`. I disabled that clause and both tests still passed. The claim "each condition alone" is overstated for that one clause. | |
| +| Astra R2 / Opus 3: a renewal between the provider read and the update charges the new period | **Closed in code; the provider behaviour is unconfirmed** | `billingquantity.go:628` (no send at or past the period end); `client.go:645-650` (`proration_date`) | `TestQuantityWorkerCannotChargeAcrossARenewal` and `…DatesTheProrationInsideThePeriod`. Both **fail** with `proration_date` removed. The refusal exists only in the fake. Stripe test mode must confirm it before `CONSOLE_BILLING_PRORATION` is set (see N3 for the clock-skew side). | |
| +| Astra R3: an absent bucket keeps an unrecorded legacy grantee | **Closed** | `walk.go:198-208` (`GranteeProber`); `walk.go:563-582` (incomplete ledger written before teardown) | `TestGrantClaimsNothingWhileAnotherPrincipalNamesTheBucket` **fails** with the grantee check removed. `TestFailedLegacyTeardownLeavesARecordTheNextGrantInherits` **fails** with the pre-teardown record removed. On AWS nothing can claim completeness until the inventory exists, which is the safe direction. | |
| +| Astra R4 / Opus 7: catch-up gaps, read errors, missing tenant statements | **Closed** | `economicspass.go:1290-1320` and `1380-1420` | `TestStatementCatchUpWritesAMissingAccountStatement` **fails** with the missing-account clause removed. I did not mutate the gap and unreadable-month tests myself. The new edges are in N4. | |
| +| Astra R5: a crash after the mark strands the operation | **Closed** | Mark and acknowledgement share one transaction (`markQuantityAdditionsProcessed`); discovery uses a `UNION` (`:104-105`); an ended subscription acknowledges its operation (`:207-211`) | `TestQuantityWorkerFindsAnOperationWithNothingPending` **fails** with the `UNION` removed. | |
| +| Opus 2: a landed operation is relabelled uncharged after a renewal | **Closed** (residual in N5) | `billingquantity.go:670-676` and `markOperationLanded` `:408` | `TestQuantityWorkerRecordsALandedOperationAfterARenewal` **fails** when replaced by `abandon()`. | |
| +| Opus 4: the durability span check holds a new box's first day for good | **Partly closed** | `durabilityfold.go:79` compares to the hour | The extended `TestDurabilityFoldHoldsBeforeABoxRegisteredItsLedger` **fails** with the exact comparison restored. A registration race of seconds that crosses an hour boundary still holds the day for good (N6). | |
| +| Opus 5: completeness dated from the grant block | **Closed** | `ownership.go:268-273` | `TestCompletenessDatesFromTheObservation` **fails** with `from` restored. | |
| +| Opus 6: credits and discounts hold store transfer | **Closed** (operational) | The collector plan and the handoff now require checking credits and discounts first | No test, which is right for an operational check. | |
| +| Opus 8: the attestation plan relies on a union the fold does not do | **Closed** (document) | `durability-attestation-path.md` | None needed. | |
| + |
| +On the three things found and not fixed: |
| + |
| +- **Teardown retry deletes a newly granted owner's bucket.** Leaving it out of this branch is right, but filing it must happen before the branch lands, not "should". There is now a cheap guard: the ledger can be read at `walk.go:575`, so a retry can refuse `EmptyBucket`/`DeleteBucket` (`:587`) when the ledger shows an open interval for a different account and app. |
| +- **`proration_date` refusal assumed from Stripe's documentation.** Rightly left as a gate. Add the future-dated case from N3 to the same test-mode check. |
| +- **The durability test temp-dir race.** Correctly fixed in the test helper. |
| + |
| +## 2. New findings, most severe first |
| + |
| +Nothing I found bills a customer for an unpaid day, bills too small an allowance, bills a day twice, leaks an identifier or secret, or lets attestation read true in production. All findings are P3. |
| + |
| +What I checked in partial-month billing: |
| + |
| +- **`AllowanceForMonth`:** |
| + - `Partial=false` holds only when the paid spans tile the month. |
| + - Each span is weighted by its paid time, so the allowance includes the boundary days that the usage leaves out. That is the intended rounding toward the customer. |
| + - Renewals dated at `PeriodStart` meet the previous `PaidThrough`, so the spans join. |
| + - An unproven renewal files a review. |
| + - A house or terms mix is refused. |
| +- **`billingUsageOnPaidDays`:** |
| + - It counts a day only when all 24 hours lie inside one span, and walks the days in order, so no day is counted twice and the result is deterministic. |
| + - A statement written before `Days` existed, with any billed meter above zero, is held (the `partial_first_month` invoice case). |
| + - A day outside the month is refused. |
| +- **The five billed meters:** |
| + - Each one's `PerAccount` addition has an `addDay` at the same call site: instance hours `:717`, edge egress `:806`, storage `:1014`, durability `durabilityfold.go:127`, store egress `storeegressfold.go:173-176`. |
| + - CUR lines must be whole hours. |
| + - `DayOf` is UTC. |
| +- **Frozen calculation:** |
| + - A full month still uses `base_units_floor_v1`, and `Partial`, `Covered` and `CountedDays` are omitted when empty, so a given statement serialises byte for byte as before. |
| + - The only change is that new statements carry `days` inside the embedded `Statement`. |
| + - The tolerance check sums in map order, but nothing it decides is persisted, and 1e-9 relative is far above the reordering error. |
| + |
| +### N1. P3: `beginQuantityOperation` does not compare the billing row's revision, plan, band, terms or item |
| + |
| +**Where:** `internal/console/billingquantity.go:372-373`. |
| + |
| +**Scenario:** |
| + |
| +1. A plan or band change lands between `quantityProviderItem` (which checked the item's price against the old plan) and `begin`. |
| +2. The subscription, period, quantity and status are unchanged, and the target comes out the same under the new plan's `MinQuantity`. |
| +3. The compare-and-set passes and sends the quantity to an item whose price has changed since it was checked. |
| + |
| +The amount is what the new plan charges for the seat, so this is not a wrong bill. But the compare-and-set does not compare everything the operation was computed from, which is what the disposition and the handoff claim. |
| + |
| +**Smallest fix:** |
| + |
| +- Carry `billing_accounts.revision` in the operation and require it to be unchanged inside the transaction. That covers every column at once. |
| +- Add a test case in which only the subscription differs and the pending generations still match, so the subscription clause is pinned on its own. |
| + |
| +### N2. P3: a sum mismatch in a partly covered month holds silently, with no review and no log |
| + |
| +**Where:** `billinginvoice.go:187` (`errBillingDays` is in `billingInvoiceQuiet`). |
| + |
| +**Scenario:** a fold bug makes one meter's days disagree with its monthly total. Every partly covered month that touches that meter, which is every subscriber's first and last month, holds quietly forever. That is the defect the invariant exists to catch. A legacy statement with no `Days` can reasonably be quiet. A disagreement inside a statement that does have days cannot. |
| + |
| +**Smallest fix:** split the error in two. Keep "no daily meters" quiet. Make "days do not sum to the total" diagnostic: log it once per month, or file a review. |
| + |
| +### N3. P3: clock skew on the operation instant can stall additions for 22 hours |
| + |
| +**Where:** `billingquantity.go:578` (`created := time.Now().Unix()`, sent as `proration_date`). |
| + |
| +**Scenario:** |
| + |
| +1. The console's clock is behind Stripe's by a few seconds, and the operation is created within those seconds after a renewal the console has already reconciled. |
| +2. `proration_date` then falls before Stripe's `current_period_start`, and Stripe refuses it. |
| +3. Every replay sends the same persisted date and is refused again, until `quantityOperationReplayLimit` (22h) lets `abandon()` run. |
| + |
| +If the console's clock is ahead and Stripe also refuses future dates, the same stall happens. On replay the fixed date charges what the customer owed from that instant, which is no more than they owe, so the amount is never wrong. The cost is liveness: the additions hold the account's freeze for up to 22 hours. |
| + |
| +**Smallest fix:** |
| + |
| +- Take `created` from `max(now, state.PeriodStart+1)`. |
| +- On a provider refusal that names `proration_date`, abandon at once instead of waiting 22 hours. |
| +- Confirm Stripe's handling of a future `proration_date` in the same test-mode check as R2. |
| + |
| +### N4. P3: an unreadable account statement re-sweeps its whole month every pass, for up to 36 months, and the sweep can never repair it |
| + |
| +**Where:** `economicspass.go:1409-1412` and `UpsertStatement`, which refuses to overwrite an object it cannot parse. |
| + |
| +**Scenario:** one account's statement object is corrupt. `statementMonthState` returns `Open`, so `statementsForMonth` runs a full month sweep every hour. That sweep's upsert for the corrupt account fails as it did before. The cost is real (every box-day object, every pass) and nothing changes. Separately, a statement deleted by an operator after it was seen closed is never revisited until the process restarts, because of `statementClosed`. That is documented, but there is no rebuild door. |
| + |
| +**Smallest fix:** treat an unreadable non-platform statement as needing a person. Log it once per process and do not count it towards `Open`, or file a review. Keep re-sweeping for absent and open statements only. |
| + |
| +### N5. P3: `markOperationLanded` trusts a coincidental quantity |
| + |
| +**Where:** `billingquantity.go:670-676`. |
| + |
| +**Scenario:** |
| + |
| +1. An operation never ran. |
| +2. An operator raises the quantity by hand to the same target in the renewed period. |
| +3. The additions are marked `charged` with this operation's reference, but nothing charged them in the period they were for. |
| + |
| +The same applies in reverse. `closeEndedQuantityAdditions` and `abandon()` on a changed subscription label a landed, charged operation's additions `subscription_ended`. |
| + |
| +These are record labels, not billing, but the outcome column is what an operator reads. |
| + |
| +**Smallest fix:** in the period-moved branch, confirm landing from the provider's invoice items or the subscription's quantity history. Failing that, mark the outcome as `landed_unverified` instead of `charged`. |
| + |
| +### N6. P3: comparing to the hour still holds a box's first day for good when the race crosses an hour boundary |
| + |
| +**Where:** `durabilityfold.go:79`. |
| + |
| +**Scenario:** metrics registers at `10:59:59` and the ledger registers at `11:00:01`. `Truncate(hour)` gives 10:00 and 11:00, so the day is incomplete. First-seen is write-once, so the hold is permanent unless the host backdates. The probability is about seconds/3600 per new box, not zero. |
| + |
| +**Smallest fix:** compare with a tolerance instead (`dFrom.Sub(from) <= time.Hour`). |
| + |
| +### N7. P3: two subscriptions in one month are now reachable, and file a review |
| + |
| +**Where:** `billinginvoice.go:311` and `invoiceIdentityFromHistory`. |
| + |
| +**Scenario:** a customer cancels on the 10th and resubscribes on the 20th. Before this change the month refused quietly. Now it prices, then `errBillingIdentityMixed` files `billing_invoice_identity_mixed`, which holds the account. This is safe, not a wrong bill, but a common customer action now pages an operator every time. |
| + |
| +**Smallest fix:** state this in the partial-month plan and the handoff as a known hold. Per-subscription invoicing can come later. |
| + |
| +### N8. P3: the `GranteeProber` contract is defined by a literal string match |
| + |
| +**Where:** `memprovisioner.go:212-230` and the `provisioner.go:45-58` doc comment. |
| + |
| +**Scenario:** the AWS implementation follows the fake. It lists IAM users whose inline policy names `arn:aws:s3:::<bucket>` literally, so it misses: |
| +- wildcard or prefix grants (`carlos-store-*`); |
| +- roles and groups; |
| +- managed policies. |
| + |
| +Completeness would then be claimed for a name that a platform or legacy role can reach. |
| + |
| +**Smallest fix:** before the AWS prober is written, have the interface comment require users, roles and groups; inline and attached policies; and any resource pattern that matches the name. |
| + |
| +## 3. Handoff claims the code contradicts |
| + |
| +- **`AGENT_HANDOFF.md` item 6:** "Statements carry each meter by UTC day". Only the five billed meters are recorded by day (`economicspass.go:420-424`, `addDay` sites). CPU, memory, requests, backhaul and fleet meters are not. The `usage.Statement.Days` comment, "Each meter's days sum to its entry in Meters", has the same flaw. |
| +- **Partial-month plan, "As built":** "`TestStatementDaysSumToTheMonthlyMeters` pins … every source". That fixture covers metrics, edge and storage only. Durability and store egress days are pinned by other tests (`meterfolds_test.go:119-122` and `:343`), so the claim is true across the suite but not of that one test. |
| +- **Round 3 dispositions, Astra R1:** "each condition alone … fail with the conditions removed". The subscription clause alone does not fail any test (N1). |
| +- **Handoff item 8:** "An operation is recorded by a compare-and-set on everything its target was computed from". Plan, band, terms and item are not compared (N1). |
| + |
| +## 4. Verdict |
| + |
| +**Accept with fixes.** All findings are P3. Before landing: pin the compare-and-set subscription clause or compare the row revision (N1), make the `errBillingDays` sum mismatch loud (N2), correct the four handoff and doc claims, and file the teardown data-loss discussion with the ledger guard. The existing gates stand: confirm `proration_date` refusal, including the future-dated case, in Stripe test mode, and leave both flags unset. |
diff --git a/implementation/carloku-paid-launch/AGENT_HANDOFF.md b/implementation/carloku-paid-launch/AGENT_HANDOFF.md| index 2ae73fd70..54f847a62 100644 |
| --- a/implementation/carloku-paid-launch/AGENT_HANDOFF.md |
| +++ b/implementation/carloku-paid-launch/AGENT_HANDOFF.md |
| @@ -30,36 +30,35 @@ When a review is approved, apply each string byte for byte: the site by replacin |
| 1. Plans and calculations, Stripe boundary, entitlements and membership, quantity history, invoice engine: as described in the September handoff (kept in git history at `aed42815`). Unchanged in this run. |
| 2. Console GET `/a/{sqid}/billing` (`billingpage.go`, `templates/billing.html`): current plan, owner-only chooser posting to the existing checkout door, `?country=` price preview computed from the plans terms, error and pending banners, portal button once a customer exists, read-only for members, byte-identical 404 for non-members, closed state when billing is off. `plans.Countries()` exposes the embedded country list. |
| -3. Durability ledger: the epoch read race is fixed (epoch and created-at are immutable after recover) with a `-race` regression. An unmetered replication fallback on a box whose ledger opened now files an escape (`DurabilityLedger.Escaped`): the box-day is incomplete and the owner is excluded for the run. A box whose ledger failed to open has no publisher and files nothing. The console fold holds a day when a box that metrics or edge expected has no ledger directory, has no day file, or is expected by the durability source for a shorter span, compared to the hour. The host backdates a late ledger's first-seen, so a late ledger is mostly caught by its missing day files. Attestation is still false everywhere in production. |
| -4. `internal/awsbilling`: Cost and Usage Report reader (versioned deliveries only), newest-delivery selection, digests, charged S3 transfer classifier. It holds on a charged usage line it does not count and on any non-usage line (fee, refund, credit) with a cost on a transfer usage type. |
| -5. `internal/objstore/ownership.go`: append-only bucket ownership ledger, opened at grant, closed at teardown. It resolves an owner only for a ledger that claims completeness. That needs a grant block recorded as minting, nothing delivered to the app yet, a probe showing the bucket does not exist, and an inventory showing no principal's policy names the bucket (`GranteeProber`). The AWS provisioner cannot list principals yet, so on AWS no ledger claims completeness, new stores included, and store transfer holds. Completeness dates from the observation. Teardown records a legacy store, incomplete, before destroying anything, and closes the interval only after the credentials are revoked. |
| -6. Statement folds: `console/durabilityfold.go` (`durability_writes_1k`, policy in `usage.BillableReplicationWrites`) and `console/storeegressfold.go` (`store_egress_gb`). `usage.MeterSource` names a source for both meters. Month evidence pins ownership ledgers by their month projection and knows the durability box directory. Statements carry each meter by UTC day (`Statement.Days`), summing to the monthly totals. With a transfer report configured, the statements catch-up revisits every month in a 36-month window that is open, was never written, or is missing an account's statement. |
| +3. Durability ledger: the epoch read race is fixed (epoch and created-at are immutable after recover) with a `-race` regression. An unmetered replication fallback on a box whose ledger opened now files an escape (`DurabilityLedger.Escaped`): the box-day is incomplete and the owner is excluded for the run. A box whose ledger failed to open has no publisher and files nothing. The console fold holds a day when a box that metrics or edge expected has no ledger directory, has no day file, or is expected by the durability source for a span more than five minutes shorter. Durability days are counted per account: a box-day attested with an exclusion set is complete for every account the box did not exclude. The move worker's checkpoint is recorded against the route's owner. Attestation is still false everywhere in production, and nothing in the agent sets it. |
| +4. `internal/awsbilling`: Cost and Usage Report reader (versioned deliveries only), newest-delivery selection, digests, charged S3 transfer classifier. It holds on a charged usage line it does not count and on any non-usage line (fee, refund, credit, discount) with a cost on a transfer usage type. Every transfer usage type the flagship account wrote from July to September 2026 is pinned in a test. |
| +5. `internal/objstore/ownership.go`: append-only bucket ownership ledger, opened at grant, closed at teardown. It resolves an owner only for a ledger that claims completeness, and only for hours that begin at or after the instant it began vouching (a store's first clock hour never resolves). Completeness needs a grant block recorded as minting, nothing delivered to the app yet, a probe showing the bucket does not exist, and an inventory showing no principal's policy names the bucket (`GranteeProber`). The AWS provisioner cannot list principals yet, so on AWS no ledger claims completeness, new stores included, and store transfer holds. Teardown records a legacy store, incomplete, before destroying anything; closes the interval only after the credentials are revoked; and leaves the bucket and its scanner alone when the ledger shows another app holding it (discussion 191). |
| +6. Statement folds: `console/durabilityfold.go` (`durability_writes_1k`, policy in `usage.BillableReplicationWrites`) and `console/storeegressfold.go` (`store_egress_gb`). `usage.MeterSource` names a source for both meters. Month evidence pins ownership ledgers by their month projection and knows the durability box directory. Statements carry the five billed meters by UTC day (`Statement.Days`), summing to the monthly totals; the other meters are not recorded by day. With a transfer report configured, the statements catch-up walks a 36-month window and sweeps every month that has an open statement, is missing a statement an account is owed (the platform's included), or is a gap between metered months. A statement that will not parse is logged once and not swept for. |
| 7. Operator API doors (`billingoperator.go`): list and resolve billing review holds, list and set the house marker. No CLI verb yet. |
| -8. Team quantity worker (`billingquantity.go`) behind `CONSOLE_BILLING_PRORATION` (`immediate` or `next_invoice`). Unset, which is how it must stay until Paul decides, it makes no provider call. An operation is recorded by a compare-and-set on everything its target was computed from, so a process that read an older state records and sends nothing. The request dates its proration inside the period it was computed for (`proration_date`), which the provider refuses after a renewal; that refusal is assumed from Stripe's documentation and has not been confirmed in test mode. Only additions of the subscription's current period can raise it; older ones are closed uncharged with a review; additions and operations of an ended subscription are closed. It does not yet lower the quantity at renewal. |
| +8. Team quantity worker (`billingquantity.go`) behind `CONSOLE_BILLING_PRORATION` (`immediate` or `next_invoice`). Unset, which is how it must stay until Paul decides, it makes no provider call. An operation is recorded by a compare-and-set on the billing row's revision, subscription, period, quantity and status, on the target and newest pending addition recomputed from the database, and on its own instant lying inside the period. The request dates its proration at that instant (`proration_date`), which the provider is expected to refuse after a renewal; an operation refused over its date is retired at once. The assignment the landing creates takes effect at the same instant, so a seat's charge and its allowance start together, or a review holds the account. The provider's side of this is taken from Stripe's documentation and has not been confirmed in test mode. Only additions of the subscription's current period can raise it; older ones are closed uncharged with a review; additions and operations of an ended subscription are closed. It does not yet lower the quantity at renewal. |
| 9. Stripe provisioning plan `stripe-provisioning.md` and print-only `stripe-provision.sh` (verified never to invoke the CLI). |
| -10. Partial-month billing: `plans.AllowanceForMonth` returns the paid spans of a month and the allowance weighted over them. A partly covered month (a first month, a month a subscription ends in, a lapse) bills only the UTC days wholly inside a paid span, against that allowance, and records the days it counted. Completeness is still whole-month. A month with no paid day is still refused quietly and never billed. |
| +10. Partial-month billing: `plans.AllowanceForMonth` returns the paid spans of a month and the allowance weighted over them. A partly covered month (a first month, a month a subscription ends in, a lapse) bills only the UTC days wholly inside a paid span, against that allowance, and records the days it counted. Completeness is still whole-month. **The whole-paid-day rule is not in the approved spec, which speaks only of prorating the allowance. It is a proposal that needs Paul's approval; the plan document states what it rounds away and the tests that pin its boundary.** A month with a paid span and no whole paid day bills nothing. A month with no paid span is refused quietly. Two subscriptions in one month price and then hold on `billing_invoice_identity_mixed`. |
| 11. Plans: `docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md`, `2026-10-01-durability-attestation-path.md`, `2026-10-01-bucket-ownership-attestation.md`, `2026-10-01-partial-month-billing.md` (built). |
| ## Why no overage can be invoiced yet, precisely |
| The monthly freeze requires all five billed meters complete. Two cannot be, in production, today: |
| -- `store_egress_gb`: no Cost and Usage Report export exists, so the source is unconfigured. It needs the scoped infrastructure approval in the collector plan, a first real delivery, a principal inventory in the AWS provisioner, and attested ownership for the stores that already exist. Check first whether the AWS account carries credits or discounts on S3 transfer: any such line holds the month. |
| -- `durability_writes_1k`: no box attests, because the external `carlos-litestream` binary replicates unit-backed routes outside the ledger. The attestation plan gives the two ways out. Do not set the flag to pass a test. |
| +- `store_egress_gb`: no Cost and Usage Report export exists, so the source is unconfigured. It needs the scoped infrastructure approval in the collector plan, a first real delivery, a principal inventory in the AWS provisioner, and attested ownership for the stores that already exist. A read-only look at the account's billing on 2026-10-01 (collector plan) found no export, no credit or discount line on S3 from July to September, no free transfer allowance reaching the account, and 1,395 GB of inter-region transfer out of Ireland in September that looks like the platform's own bucket. |
| +- `durability_writes_1k`: no box attests, because the external `carlos-litestream` binary replicates unit-backed and always-on routes outside the ledger. The chosen way out is the scoped attestation (attestation plan, "Decision and progress"): its console half and scope computation are built and tested, and the reader of the replicator's state and the agent's call are not. Do not set the flag to pass a test. |
| ## Still missing from the full requirements audit |
| - Quantity at renewal: the worker raises a subscription for added members but nothing lowers it at renewal for members who left, so a renewal bills the old quantity. Must be built before team plans are sold. The proration policy itself is Paul's decision and the switch is unset. |
| -- Partial months: built (item 10). Left over: a month with no paid day is refused quietly and retried, where the design records it as waived. |
| +- Partial months: built (item 10), pending Paul's approval of the usage rule. A month with no paid span is refused quietly where the design records it as waived. |
| - Months spanning two tax codes hold with a review; per-line tax codes are not implemented. |
| - The operator doors have no `carlos` verb and no documentation page, and have not had their own independent review. |
| - Ownership history for store buckets: on AWS no ledger can vouch for who had access (no principal inventory), and existing and adopted buckets never could, so charged transfer holds. The evidence-backed way out is designed in `docs/superpowers/plans/2026-10-01-bucket-ownership-attestation.md` (match store records against an IAM inventory, claim completeness from that instant, never earlier). Not built. Transfer before a bucket's attestation can never be attributed, so attest before the first billable month. |
| - Free tier: no Free entitlement, no app cap, no storage refusal, no per-plan hibernation idle, no flush-only replication class, nothing at runtime reads entitlements. |
| - Dormancy archive and warnings, recognised-revenue pool accounting at 15 percent, the books site: not started. |
| - Statement rebuild door for a closed month: missing. |
| -- Move and checkpoint metering tests in `internal/host/movespass_test.go`: missing. |
| - An operator verb to backfill bucket ownership for existing stores: missing. |
| -- A teardown retried after a failed revocation deletes the bucket named on its record, even if another app has since been granted that name. Predates this branch; data loss, not billing; not fixed. See the round-three dispositions. |
| +- A store's first clock hour holds the month if it has a charged line, and nothing releases the hold. Needs a decision before the AWS principal inventory lands (collector plan). |
| ## Verification in this run |
| @@ -74,7 +73,7 @@ Merchant `acct_1UD7LXI4Nrr6AEsO`, Team Tito Limited, Ireland, EUR; Irish standar |
| ## Next actions, in order |
| 1. Apply approved copy from both reviews when `result.json` arrives. |
| -2. Independent review: Astra rejected rounds 1, 2 and 3 (ten, eight and five findings); Opus accepted with fixes twice (eight and eight). All were accepted and fixed with reproductions (`docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md`). Round four of both must pass on the exact tip before anything lands; do not read "fixed" as "accepted". Partial-month billing has had no independent review yet and is in round four's scope. |
| +2. Independent review: Astra rejected rounds 1 to 4 (ten, eight, five and five findings); Opus accepted with fixes three times (eight each). All were accepted and fixed with reproductions (`docs/superpowers/specs/CODEX-DISPOSITIONS-carloku-paid-launch-overnight.md`). Round five of both must pass on the exact tip before anything lands; do not read "fixed" as "accepted". The scoped-attestation code and the teardown guard have had no independent review yet. |
| 3. Scoped approvals: Cost and Usage Report export; Stripe catalog, portal, webhook and the `rk_live` key; then a test-mode rehearsal and a real purchase. |
| 4. Build the principal inventory and the bucket ownership attestation (designed in `docs/superpowers/plans/`), quantity reduction at renewal, a `carlos` verb and documentation for the operator doors, then Free-tier enforcement. |
| -5. Choose and build the attestation path. Until then replication writes hold every month. |
| +5. Finish the scoped attestation: the reader of the replicator's state, the agent's call behind a switch, their review, a week on dev. Until then replication writes hold every month. |
diff --git a/implementation/carloku-paid-launch/requirements-audit.json b/implementation/carloku-paid-launch/requirements-audit.json| index de601b5a7..3e6dc8e7d 100644 |
| --- a/implementation/carloku-paid-launch/requirements-audit.json |
| +++ b/implementation/carloku-paid-launch/requirements-audit.json |
| @@ -21,21 +21,21 @@ |
| { |
| "step": 3, |
| "requirement": "durable collection and completeness", |
| - "observed_status": "edge proof implemented; durability and store-transfer sources now fold into statements with their own completeness (durabilityfold.go, storeegressfold.go) and month evidence; neither can read complete in production yet", |
| + "observed_status": "edge proof implemented; durability and store-transfer sources fold into statements with their own completeness (durabilityfold.go, storeegressfold.go) and month evidence; durability days are counted per account so a scoped attestation holds only the accounts it excludes; neither source can read complete in production yet", |
| "inspection_anchor": "internal/usage/edgespool.go; internal/usage/evidence.go; internal/usage/evidence_month.go", |
| "complete": false |
| }, |
| { |
| "step": 4, |
| "requirement": "object-store transfer", |
| - "observed_status": "collector implemented locally on the AWS Cost and Usage Report: charged-line classifier, newest-delivery reader with digests, append-only bucket ownership ledger opened at grant and closed at teardown, monthly fold that holds on no delivery, uninvoiced month, unclassified charge, adjustment line or unowned bucket, and holds the close until provable. Not complete: no Data Export or bucket policy exists (scoped approval pending, plan in docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md); on AWS no ownership ledger can claim completeness until the provisioner can list principals, and existing and adopted buckets need the attestation door (docs/superpowers/plans/2026-10-01-bucket-ownership-attestation.md); credits or discounts on S3 transfer in the AWS account would hold every month; no real delivery has been read", |
| + "observed_status": "collector implemented locally on the AWS Cost and Usage Report: charged-line classifier pinned against every transfer usage type the flagship account wrote from July to September 2026, newest-delivery reader with digests, append-only bucket ownership ledger opened at grant and closed at teardown, monthly fold that holds on no delivery, uninvoiced month, unclassified charge, adjustment line or unowned bucket-hour, and holds the close until provable. Read-only inspection on 2026-10-01: no Data Export exists, S3 carried only Usage lines (no credits or discounts), no free transfer allowance reaches the account. Not complete: the export and bucket policy need scoped approval (docs/superpowers/plans/2026-10-01-store-transfer-cur-collector.md); on AWS no ownership ledger can claim completeness until the provisioner can list principals, and existing and adopted buckets need the attestation door; a store's first clock hour holds with nothing to release it; no real delivery has been read", |
| "inspection_anchor": "internal/awsbilling; internal/objstore/ownership.go; internal/console/storeegressfold.go", |
| "complete": false |
| }, |
| { |
| "step": 5, |
| "requirement": "replication writes", |
| - "observed_status": "ledger, hooks and host integration implemented; epoch read race fixed with a -race regression; every unmetered fallback now files an escape that makes the box-day incomplete; console fold and billable-write policy implemented and tested; production attestation remains false because the root litestream unit is uninstrumented (plan in docs/superpowers/plans/2026-10-01-durability-attestation-path.md); move and checkpoint route tests still missing", |
| + "observed_status": "ledger, hooks and host integration implemented; epoch read race fixed with a -race regression; every unmetered fallback files an escape that makes the box-day incomplete; console fold and billable-write policy implemented and tested; the move worker's checkpoint is tested as metered to the route owner with an escape on the unmetered fallback; scoped attestation chosen (docs/superpowers/plans/2026-10-01-durability-attestation-path.md): per-account fold and scope computation built and tested, the replicator-state reader and the agent call not built, so production attestation remains false", |
| "inspection_anchor": "internal/usage/durabilityledger.go; internal/host/durability.go; internal/console/durabilityfold.go", |
| "complete": false |
| }, |
| @@ -49,7 +49,7 @@ |
| { |
| "step": 7, |
| "requirement": "durable billing and effective terms", |
| - "observed_status": "history exists; invoice journal/engine implemented locally and recovery race tests pass; a partly covered month (first month, ending month, lapse) bills the UTC days wholly inside a paid span against the allowance weighted over those spans, with the counted days frozen in the calculation; a month with no paid day is still refused quietly; team quantity worker implemented behind an unset policy switch and does not lower quantity at renewal; partial-month billing awaits independent review", |
| + "observed_status": "history exists; invoice journal/engine implemented locally and recovery race tests pass; a partly covered month bills the UTC days wholly inside a paid span against the allowance weighted over those spans, with the counted days frozen in the calculation and the boundary pinned by tests; that usage rule is not in the approved spec and awaits Paul's approval; a quantity operation's assignment takes effect at the instant the provider prorates from; a month with no paid span is refused quietly; team quantity worker behind an unset policy switch does not lower quantity at renewal", |
| "inspection_anchor": "internal/console/billingstore.go; internal/console/billinginvoicestore.go", |
| "complete": false |
| }, |