carlos / platform Public

Readiness, enablement and handoff: bands.p3 resolved with the approved explanation; currency_options stated as the code enforces it; what is still code apart from approvals

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 780180f92c6ba98a6bd8f80301cb79252cc37791 parent 0e6ff48
4 files changed, +62 −13
  • .claude/HANDOFF.md +3 −1
  • implementation/carloku-paid-launch/ENABLEMENT.md +20 −4
  • implementation/carloku-paid-launch/READINESS.md +38 −7
  • implementation/carloku-paid-launch/stripe-provisioning.md +1 −1

CI passed — run details

diff --git a/.claude/HANDOFF.md b/.claude/HANDOFF.md
index 88c63dc85..85eb9dfb8 100644
--- a/.claude/HANDOFF.md
+++ b/.claude/HANDOFF.md
@@ -26,11 +26,13 @@ Branches (all on the forge, none merged; the local gate is not CI):
**NEEDED:**
- Paul, commercial: approve the 36 amounts as an `approved` book version (approval L) together with the USD/GBP overage rates and floors in `OVERAGE-RATES-PROPOSAL.md`, or state other figures; the HALF code word; the proration policy (B); the partial-month rule (C).
-- Paul, copy: the console billing page's 40 strings; the store-refusal copy (`OUTSTANDING.md` 19g); a new sentence for the pricing page's `bands.p3` ("The euro price is what is charged" is wrong under fixed currencies); the approved pricing and currency strings themselves need nothing more.
+- Paul, copy: the console billing page's 40 strings; the store-refusal copy (`OUTSTANDING.md` 19g). `bands.p3` is done: the approved currency explanation replaced the converted-euro sentence (site `e091e3f`, 07:0x); it now reads the same as the note under the currency selector.
- Paul, rulings: evidence for a held bucket-hour (J); storage on a bucket a store has left (K); the cutover note (M: purchases before the book stay legacy EUR; binary first, variables second).
- Scoped approvals, prepared as plans only: Stripe test mode (E) for the fence test and the rehearsal; Stripe live provisioning (F) after the approved book; the Cost and Usage Report export and the scratch-object write (G); Path B on a dev box (H).
- Reviews to read when they land: the currency branch's twelfth (`logs/opus-currency-review12.md`, `astra-currency-review12.md`) and the replicator's tenth (`opus-replicator-review10.md` is in; `astra-replicator-review10.md` pending).
+**STILL TO BUILD (code, not approvals; no fake completes these):** quantity reduction at renewal (`OUTSTANDING.md` 14), the Free tier (15), dormancy and pool accounting (16), per-line tax codes across a change (17), the operator doors (18, plus the quantity-history gap door and a rejected-events listing), the meters' own code (replicator unwired with deep items open; store transfer has no source), the two key-memory defects (7, 9). `READINESS.md` has the list with what each means. The tests on the currency branch establish the subscription and currency path against fakes, nothing beyond it.
+
**RECOMMENDED:**
- Read the twelfth currency review. If it confirms round eleven's fixes (both accepted rounds ten and eleven with fixes; the fixes are in `25487506` and `781bb1c2`) and CI is green on the tip, merge the currency branch into this branch: a merge commit pushed to this branch, as the observe-routes fix was at `47c97fa6` (`amadan branch merge` lands a branch on main and is not what this step is), then gate the merged tip. If it does not confirm, the next commit answers it the same way. Rule on K to let the storage branch follow.
- Publish the approved book version as soon as L is given; it is a new entry in `internal/plans/pricebook.json`, the export regenerated and copied to the site, and the 36 lookup keys renamed.
diff --git a/implementation/carloku-paid-launch/ENABLEMENT.md b/implementation/carloku-paid-launch/ENABLEMENT.md
index eb9d2da9a..8971fd6e5 100644
--- a/implementation/carloku-paid-launch/ENABLEMENT.md
+++ b/implementation/carloku-paid-launch/ENABLEMENT.md
@@ -17,7 +17,7 @@ disagree, `stripe-provisioning.md` is wrong and this file says so.
| Thing | Count | Where it is defined | Exists today |
| --- | --- | --- | --- |
| Products | 3 (personal, community, business), tax codes `txcd_10102001`, `txcd_10102001`, `txcd_10102000` | plan step 1 | no |
-| Prices | 36: 3 plans x 4 bands x 3 currencies, yearly, licensed, tax exclusive, one currency each, no `currency_options` | plan step 2; `internal/plans/pricebook.json` | no |
+| Prices | 36: 3 plans x 4 bands x 3 currencies, yearly, licensed, tax exclusive, one currency each; no currency option but the price's own (Stripe may answer an expanded `currency_options` with an entry under the price's own currency at its own amount; that passes, any other entry is refused) | plan step 2; `internal/plans/pricebook.json` | no |
| Coupons | 2 (50% forever with the public code HALF; 100% house, no code) | plan step 3 | no |
| Portal configuration | 1, locked | plan step 4 | no |
| Webhook endpoint | 1, six events, API `2025-02-24.acacia` | plan step 5 | no |
@@ -34,8 +34,14 @@ Amounts are per member per year in the currency's minor unit, exactly
`metadata[terms_version]=2026-09-07-v1`, `metadata[price_book]`,
`metadata[currency]`, `metadata[plan]`, `metadata[band]`. The console
compares the five metadata values, the price's own `currency` and
-`unit_amount`, `tax_behavior`, the recurring interval and usage type, and the
-absence of `currency_options`, against the book before it sells on a price.
+`unit_amount`, `tax_behavior`, the recurring interval and usage type, and
+that `currency_options` holds nothing but the price's own currency at its
+own amount (`priceCurrencyOptionsAreOwn`; `stripe-provision.sh --check`
+applies the same rule), against the book before it sells on a price. The
+provisioning script's step-2 notes still say "no `currency_options`, ever";
+that wording is to be aligned with the rule in the next currency-branch
+commit (the plans test reads the script's text, so it is not changed
+mid-review).
| Plan | Currency | A | B | C | D |
| --- | --- | --- | --- | --- | --- |
@@ -175,7 +181,7 @@ scope. Those that gate enabling payments, plus what this run added:
| # | Approval | State after the night |
| --- | --- | --- |
-| A | Copy | Pricing page grouped review and the five currency strings: approved 2026-10-01 and applied. Still open: the HALF code word, console billing page copy (40 strings), store-refusal copy. One approved string is now wrong: `bands.p3`, "The euro price is what is charged", under fixed currencies; it needs a new sentence and its own review |
+| A | Copy | Pricing page grouped review and the five currency strings: approved 2026-10-01 and applied. `bands.p3` ("The euro price is what is charged") replaced on 2026-10-02 by the approved currency explanation drafted for that slot (site `e091e3f`). Still open: the HALF code word, console billing page copy (40 strings), store-refusal copy |
| B | Proration policy | open |
| C | Partial-month rule | open |
| E | Stripe test mode | open; needed before the fence test and the rehearsal |
@@ -199,5 +205,15 @@ approvals granted. It does not mean payments switched on.
every commit, gate log, review verdict and CI run.
- Not code: approvals A (remaining parts), B, E, F, L, M; the test-mode
rehearsal; the live provisioning; the first live proof.
+- Still code, before the complete metered model can invoice or team plans
+ can be sold, and not completed by any test against a fake: quantity
+ reduction at renewal (`OUTSTANDING.md` 14), the Free tier (15), dormancy
+ and pool accounting (16), per-line tax codes across a change (17), the
+ operator doors (18, plus the quantity-history gap and the rejected-events
+ listing the currency reviews name), the two meters' own code (the
+ replicator branch is unwired with deep items open; the store transfer
+ meter has no code because it has no source), and the two open defects
+ past Stripe's key memory (7, 9). Approvals G and H gate the meters'
+ deployment, not their completion.
- Not part of enabling subscriptions, still part of the complete metered
model: items 1 to 4 and 6 to 9 of `OUTSTANDING.md`.
diff --git a/implementation/carloku-paid-launch/READINESS.md b/implementation/carloku-paid-launch/READINESS.md
index bf55c4d87..4e7b2d56d 100644
--- a/implementation/carloku-paid-launch/READINESS.md
+++ b/implementation/carloku-paid-launch/READINESS.md
@@ -86,16 +86,47 @@ reconcile, calculation, invoice and recovery tests in
## Approvals needed to enable
-A (remaining parts: HALF code word, console billing copy, store-refusal copy,
-a new `bands.p3` sentence), B, C, E, F, L (the approved book version and the
-USD/GBP overage rates in `OVERAGE-RATES-PROPOSAL.md`), M (the cutover note).
-Each is scoped in `ENABLEMENT.md` section 8 and `OUTSTANDING.md`.
+A (remaining parts: HALF code word, console billing copy, store-refusal
+copy), B, C, E, F, L (the approved book version and the USD/GBP overage
+rates in `OVERAGE-RATES-PROPOSAL.md`), M (the cutover note). Each is scoped
+in `ENABLEMENT.md` section 8 and `OUTSTANDING.md`.
+
+## Still to build, apart from any approval
+
+These are code, not approvals, and no test against a fake completes them.
+What the tests above establish is the subscription and currency path as
+modelled; the complete metered model and team plans need the following
+built and reviewed first (numbers are `OUTSTANDING.md` items):
+
+- Quantity reduction at renewal (14): absent; a renewal bills the old
+ quantity, so team plans cannot be sold.
+- The Free tier (15): no entitlement, app cap, storage refusal, per-plan
+ idle or flush-only class.
+- Dormancy archive and warnings, recognised-revenue pool accounting, the
+ books site (16).
+- Per-line tax codes for a month spanning two codes (17; it holds with a
+ review today).
+- Operator doors (18): the `carlos` verbs for the existing doors, a
+ statement rebuild for a closed month, bucket-ownership backfill; and,
+ from the currency reviews, a door to clear a quantity-history gap whose
+ cause is established, and a listing of rejected webhook events.
+- The meters' own code: replication writes (the replicator branch, unwired,
+ with the deep items listed in its row; approval H gates deploying it, not
+ finishing it) and store transfer (no code, because no source; approval G
+ gives it a source).
+- The two open defects past Stripe's key memory (7, 9).
+
+Approvals E and F then prove the subscription path against Stripe; nothing
+above is proven by the fakes.
## Known defects and conflicts, open
-- `bands.p3` on the pricing page says the euro price is what is charged;
- under fixed currencies that is wrong. Approved copy; not edited; needs its
- own review.
+- `bands.p3` on the pricing page: resolved 2026-10-02 (site `e091e3f`).
+ The sentence that promised a converted euro price is replaced by the
+ approved currency explanation drafted for that slot, "Choose USD, EUR or
+ GBP for your subscription and usage bills." (copy-review/currency); the
+ same sentence is also the control note under the currency selector, so it
+ appears twice on the page. Every other string is as approved.
- `OUTSTANDING.md` items 7 and 9 (late requests past Stripe's key memory)
are open defects, held, not waived.
- The replicator's deep open items after its eighth review are in its
diff --git a/implementation/carloku-paid-launch/stripe-provisioning.md b/implementation/carloku-paid-launch/stripe-provisioning.md
index ad67c8fc8..f99251ad7 100644
--- a/implementation/carloku-paid-launch/stripe-provisioning.md
+++ b/implementation/carloku-paid-launch/stripe-provisioning.md
@@ -99,7 +99,7 @@ Twelve prices, exactly the `required_catalog` in `stripe-live-readiness.json`.
Every price has these fixed fields: `currency=eur`, `tax_behavior=exclusive`,
`billing_scheme=per_unit`, `recurring[interval]=year`,
`recurring[interval_count]=1`, `recurring[usage_type]=licensed`. No
-`currency_options` on any price (it would switch off Adaptive Pricing, and the
+`currency_options` on any price beyond its own currency (the console refuses a price whose options name another currency; an entry under the price's own currency at its own amount passes, see ENABLEMENT.md section 2); the earlier text here said "it would switch off Adaptive Pricing, and the
console refuses a price that has any). Never pass `payment_method_types`
anywhere.