carlos / platform Public

pricing: round-two revisions, and Business drops to a 30k write inclusion

Round two disposed twelve of fourteen findings as addressed and raised
four new ones. The P1: immutable terms fix what a plan meant but not
which plan and how many members applied during the usage month, and
since the catch-up stage invoices days after month end, reading today's
quantity gives the wrong answer. Ten members joining on the first of
the month would erase the previous month's excess entirely. Entitlement
assignments are now effective-dated and resolved as of the usage month.

Adding meter keys to statements does not make anything price them, so
migrating the Go and JavaScript cost consumers is now its own build
step; until it lands the dashboard's cost figure is wrong and feeds
pool draw directly.

Business's replication inclusion drops from 50k writes to 30k, which
brings inclusions to 19.97% and back inside the fifth bound the rule
claims. A rule the price book itself breaks is worse than no rule.

Stripe Tax's 0.5% is now modelled from the start rather than deferred,
since registrations are a launch prerequisite, and standalone overage
invoices carry Invoicing's 0.4% rather than Billing's 0.7%. The
durability worked example was stated per member but computed per
account; it now says which. Discounted margins recomputed to 53-59%.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 1bd3f19db8c4ba583927331cc97d30f0fbbf691b parent 4d545db
2 files changed, +166 −53
  • docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md +104 −53
  • docs/superpowers/specs/CODEX-FINDINGS-carloku-pricing-round2.md +62 −0
diff --git a/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md b/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md
index e2d49e230..e61600d98 100644
--- a/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md
+++ b/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md
@@ -72,12 +72,16 @@ These are the numbers the books page publishes.
| Egress | €0.0828/GB | AWS data transfer out |
| S3 requests | €0.0046/1k | blended, PUT-heavy |
| Awake hour (one small app's box share) | **€0.002** | derived, see below |
-| Stripe | **1.5% card + 0.7% Billing + €0.25** per charge | Stripe Ireland pricing, EUR settlement, no FX |
+| Stripe, subscriptions | **1.5% card + 0.7% Billing + 0.5% Tax + €0.25** | Stripe Ireland pricing, EUR settlement, no FX |
+| Stripe, overage invoices | **1.5% card + 0.4% Invoicing + 0.5% Tax + €0.25** | standalone invoices are not Billing subscriptions |
-Stripe Billing's 0.7% applies to every recurring charge and the earlier draft
-omitted it (codex 12). Stripe Tax adds a further 0.5% on transactions in
-registered jurisdictions once registrations exist; that is not yet modelled
-and must be added at the first review, when the registrations are real.
+The first draft counted card processing alone (codex 12). Billing's 0.7%
+applies to every recurring charge; Tax's 0.5% applies in registered
+jurisdictions, and since registrations are a launch prerequisite it is
+modelled from the start rather than deferred (codex round 2). Standalone
+overage invoices carry Invoicing's 0.4% instead of Billing's 0.7%, which
+matters because the €1 overage floor is close to the point where fees eat
+the invoice.
**The awake-hour anchor is derived from real data, not assumed.** The
2026-08-15 measurement found an always-on ~190 MB app allocates $1.20–1.80 of
@@ -92,7 +96,7 @@ costs storage alone — hibernation is the product and the price says so.
| **Free** | €0 | 1 | 3 apps, 100 awake h, 250 MB storage, 1 GB egress, 2-minute hibernation, no point-in-time restore |
| **Personal** | €24/year | 1 | 85 awake h, 2 GB storage, 2 GB egress |
| **Community** | €5/member/year, 10-member minimum (€50) | unlimited | 17 awake h, 0.5 GB storage, 0.4 GB egress |
-| **Business** | €50/member/year, 10-member minimum (€500) | unlimited | 170 awake h, 5 GB storage, 3 GB egress, 50k replication writes, priority support |
+| **Business** | €50/member/year, 10-member minimum (€500) | unlimited | 170 awake h, 5 GB storage, 3 GB egress, 30k replication writes, priority support |
**All inclusions are per member per MONTH** (codex 3). They pool at the
account and are subtracted from that month's statement, so the allowance
@@ -113,9 +117,9 @@ Billing** + €0.25 (codex 12 — the earlier draft omitted the Billing fee).
| Plan | Gross/yr | Net after Stripe | Cost/yr | Margin | Inclusions as % of price | Break-even storage |
| --- | --- | --- | --- | --- | --- | --- |
-| Personal | €24.00 | €23.22 | €4.54 | 77.9% | 18.9% | 76 GB |
-| Community (10) | €50.00 | €48.65 | €9.32 | 78.7% | 18.6% | 160 GB |
-| Business (10) | €500.00 | €488.75 | €110.90 | 75.6% | 22.2% | 1,538 GB |
+| Personal | €24.00 | €23.10 | €4.54 | 77.4% | 18.9% | 75 GB |
+| Community (10) | €50.00 | €48.40 | €9.32 | 78.2% | 18.6% | 159 GB |
+| Business (10) | €500.00 | €486.25 | €99.86 | 77.3% | 20.0% | 1,572 GB |
**Break-even storage is the number that matters**, and it is Eleven's test:
the storage a plan could fill forever while still covering itself. These are
@@ -128,10 +132,12 @@ been the worst possible first impression.
Every inclusion still sits an order of magnitude beneath its break-even, so
no plan can structurally lose money while feeling unlimited in practice.
-**Inclusions are 18.6–22.2% of price, not exactly 20%** (codex 13). The rule
-sizes them; round numbers a human can remember win the last percent. The
-rule's claim is the bound — inclusions never exceed a fifth of the price —
-not an exact equality.
+**Inclusions are 18.6–20.0% of price** (codex 13). The rule sizes them; round
+numbers a human can remember win the last fraction of a percent. The claim is
+the bound — inclusions never exceed a fifth of the price — not an exact
+equality. Business's replication inclusion was cut from 50k writes to 30k
+precisely to keep it inside that bound (codex round 2), because a rule the
+price book itself breaks is worse than no rule.
### Overage rates
@@ -157,18 +163,23 @@ this work** (ruling, Paul 2026-09-07). Sizing it is not optional:
| Replication writes /member/month | Business cost/yr | Margin |
| --- | --- | --- |
-| 0 | €83.30 | 81.1% |
-| 50k **(included)** | €110.90 | 75.6% |
-| 100k | €138.50 | 70.0% |
-| 500k | €359.30 | 25.9% |
-| ~700k | — | break-even |
-| 1M | €635.30 | **−29.3%** |
-
-An unbounded "tight durability" inclusion goes loss-making at roughly 700k
-writes per member per month. So Business includes **50k writes per member per
-month** and meters beyond it at €0.023/1k. A continuous writer at 1M/month
-pays about €2,760/year against €552 of cost — fair by construction, since you
-pay for the durability you actually consumed.
+| 0 | €83.30 | 80.6% |
+| 30k **(included)** | €99.86 | 77.3% |
+| 100k | €138.50 | 69.5% |
+| 300k | €248.90 | 47.5% |
+| ~730k | — | break-even |
+| 1M | €635.30 | **−29.8%** |
+
+An unbounded "tight durability" inclusion goes loss-making at roughly 730k
+writes per member per month. So Business includes **30k writes per member per
+month**, pooled, and meters beyond it at €0.023/1k.
+
+Worked example, stated on its proper basis (codex round 2 — the first draft
+conflated a per-member figure with an account total): a ten-member Business
+account pools 300k included writes a month. An app generating **1M writes a
+month across the whole account** pays about **€193/year** of overage against
+**€55/year** of replication cost. Fair by construction, since you pay for the
+durability you actually consumed.
**Do not reuse `requests_1k` for this** (codex 5). That meter is fed
exclusively from edge HTTP request counts
@@ -196,14 +207,14 @@ price and receives 35% of the inclusions. This is the direct reading of
"80/20, but indexed": the rule is what's indexed, not just the number.
The property this buys is the one that matters for a business publishing its
-books: **margin is identical in every country.**
+books: **margin is very nearly identical in every country.**
| Band | Personal price | Cost to us | Margin |
| --- | --- | --- | --- |
-| A (1.00) | €24.00 | €4.54 | 77.9% |
-| B (0.75) | €18.00 | €3.40 | 77.5% |
-| C (0.50) | €12.00 | €2.27 | 76.8% |
-| D (0.35) | €8.40 | €1.59 | 75.9% |
+| A (1.00) | €24.00 | €4.54 | 77.4% |
+| B (0.75) | €18.00 | €3.40 | 77.0% |
+| C (0.50) | €12.00 | €2.27 | 76.3% |
+| D (0.35) | €8.40 | €1.59 | 75.4% |
**Margin drifts about two points across the bands, it is not flat** (codex
13). Infrastructure cost scales exactly with the band, but Stripe's fixed
@@ -245,8 +256,12 @@ A public promotion code, 50% off, `duration: forever`, unlimited redemptions,
printed on the pricing page. No form, no email, no proof. Renewals keep it.
**Price only — inclusions are not halved.** This is the giveaway, and halving
-what someone receives would defeat its purpose. Margin falls to 55–59%
-depending on band, which is profitable and intentional.
+what someone receives would defeat its purpose. Margin falls to **53–59%**
+depending on plan and band — Personal 57.4% at band A and 53.6% at band D,
+Community 59.0% and 57.1%, Business 57.3% and 52.7% (codex round 2, which
+caught the earlier range being stale after the inclusion changes). Every
+combination stays comfortably profitable, which is what makes the offer
+sustainable rather than performative.
It stacks with the affordability index because the index is a Price and the
code is the session's one coupon slot.
@@ -445,8 +460,9 @@ Only then does the monthly step run:
1. read the **closed** month's statement, after the catch-up stage has
declared it final,
2. subtract pooled inclusions (quantity × per-member monthly inclusion ×
- band factor), using **the terms version the account holds**, not today's
- plans file (see below),
+ band factor) resolved **as of the usage month** from the effective-dated
+ assignments, never from today's account state or today's plans file
+ (see below),
3. price the excess at that terms version's overage rates,
4. raise a Stripe invoice with one line per meter **if the total clears a
€1 floor**, waiving below that (chasing €0.40 costs more than €0.40),
@@ -462,6 +478,20 @@ terms version covering allowances, overage rates and band factor. The review
promise is only enforceable if the terms an account accepted are still
readable a year later.
+**Entitlement assignments are effective-dated, not current state (codex round
+2, P1).** Immutable terms fix *what a plan meant*; they do not fix *which
+plan and how many members applied during the usage month*. Because the
+catch-up stage invoices a closed month days after it ended, reading today's
+quantity produces the wrong answer. Ten Business members using 2,500 awake
+hours in September have 1,700 included and 800 excess; if ten more join on
+1 October before September is invoiced, a naive read gives 3,400 included and
+erases the excess entirely. An accepted plan change does the same to the
+rates. So the store holds effective-dated quantity and terms assignments, the
+month's calculation resolves entitlements **as of that month**, and the
+billing record binds to them. A within-month change prorates the allowance by
+the days each assignment was in force, matching how Stripe prorates the
+subscription itself.
+
**No Stripe meters, no Metronome.** Stripe's current guidance routes new
usage-based billing to Metronome, but our statements are already the source of
truth, computed hourly against real AWS bills. Paying a second metering system
@@ -584,35 +614,56 @@ this spec is not a small one.
completeness policy replacing the any-source `CoveredDays` (codex 5).
4. `store_egress_gb` meter — per-tenant S3 data-transfer attribution
(codex 7).
-5. `durability_writes_1k` meter — per-tenant replication-write attribution,
- plus a flush-only replication class and plan propagation (codex 6, 8).
-6. Per-account-month billing records with operation-scoped idempotency
- (codex 1).
-7. Plans JSON with **immutable terms versions** (plan keys, monthly
+5. `durability_writes_1k` meter — per-tenant replication-write attribution
+ (codex 6). The flush-only replication class and its plan propagation
+ (codex 8) belong with the entitlement layer at step 13, not here: the
+ collector stands alone, the policy needs a plan to read.
+6. **Migrate the cost consumers to the new meters** (codex round 2). Adding
+ meter keys to statements does not make anything price them: `PriceAccount`
+ enumerates its inputs explicitly (`compute.go:100`), and so does its
+ mirrored JavaScript (`templates/economics.html:662`). Until both consume
+ `store_egress_gb` and `durability_writes_1k` — and stop pricing edge HTTP
+ requests at an S3 request rate — the dashboard's `CostUSD` is wrong, and
+ it feeds pool draw directly (`economicsview.go:568`). Fixing the pool's
+ revenue side at step 15 does not repair its expenditure side.
+7. Per-account-month billing records with operation-scoped idempotency
+ (codex 1), and **effective-dated quantity and terms assignments** so a
+ closed month resolves the entitlements that actually applied to it
+ (codex round 2).
+8. Plans JSON with **immutable terms versions** (plan keys, monthly
inclusions, overage rates, band factors, country→band map) as committed
data with a schema, beside the scenarios (codex 9).
-8. Stripe catalogue: 3 Products, 12 Prices, 2 coupons, 1 promotion code.
-9. `house` marker on accounts + console door.
-10. Checkout + portal doors on the console; band selection from billing
+9. Stripe catalogue: 3 Products, 12 Prices, 2 coupons, 1 promotion code.
+10. `house` marker on accounts + console door.
+11. Checkout + portal doors on the console; band selection from billing
country; an explicit proration-collection choice.
-11. Webhook endpoint and entitlement writes.
-12. Monthly overage pass with the €1 floor.
+12. Webhook endpoint and entitlement writes.
13. Caps enforcement (hibernation idle per plan, app count, storage refusal,
- pool degradation steps).
-14. Dormancy archive at 90 days with 60/80-day warnings.
-15. Pool funded from recognised subscription revenue rather than modelled
+ pool degradation steps, and the flush-only replication class from step 5).
+14. Monthly overage pass with the €1 floor.
+15. Dormancy archive at 90 days with 60/80-day warnings.
+16. Pool funded from recognised subscription revenue rather than modelled
revenue (codex 10).
-16. Books site: publisher pass shipping a static release + three pages
+17. Books site: publisher pass shipping a static release + three pages
(codex 11).
-17. `CARLOS_STRIPE_SECRET_KEY` and `CARLOS_STRIPE_WEBHOOK_SECRET` read in
+18. `CARLOS_STRIPE_SECRET_KEY` and `CARLOS_STRIPE_WEBHOOK_SECRET` read in
`cmd/console/main.go` `serve()`, supplied from the pinfra EnvironmentFile
exactly as `CARLOS_RELEASE_KEY` is. **A restricted key (`rk_`), not a
secret key.** Never in the deployment bucket, never in `apps/*/config.json`.
-**Sequencing.** 1–6 are independently useful — they improve the modelling
-instrument whether or not anyone ever pays — and can land while the Stripe
-account's tax registrations are still pending. 7–12 are the commercial layer.
-13–14 gate the free tier being safe to offer. 15–16 gate publishing the books.
+**Sequencing.** Steps 1–6 are the collectors and the cost maths. They are
+independently useful — they make the modelling instrument correct whether or
+not anyone ever pays — and can land while the tax registrations are still
+pending. Steps 7–12 are the commercial layer. Step 13 gates the free tier
+being safe to offer, and also carries the replication policy that step 5's
+collector cannot apply on its own. Step 14 is the first thing that charges
+anyone and must not start before 1–7 are done. Steps 16–17 gate publishing
+the books.
+
+The earlier draft overstated how independent the collectors were (codex round
+2): plan propagation needs an entitlement layer to read, and the billing
+records at step 7 prepare billing rather than improving modelling. The split
+above separates the collectors from what activates them.
## Open questions and follow-ups
diff --git a/docs/superpowers/specs/CODEX-FINDINGS-carloku-pricing-round2.md b/docs/superpowers/specs/CODEX-FINDINGS-carloku-pricing-round2.md
new file mode 100644
index 000000000..3d4f4c87c
--- /dev/null
+++ b/docs/superpowers/specs/CODEX-FINDINGS-carloku-pricing-round2.md
@@ -0,0 +1,62 @@
+## 1. Disposition table
+
+Reviewed **`4d545db`**, against the revised text and current code. **12 ADDRESSED, 2 PARTIAL.** No files changed. “ADDRESSED” means complete at design-spec level.
+
+| # | Round-one finding | Disposition | Revised-text evidence / remaining gap |
+|---|---|---|---|
+| 1 | Repeat invoices despite idempotency keys | **ADDRESSED** | P4 requires durable account/month records, calculation snapshots, Stripe IDs, completion state and operation-specific keys; build step 6. |
+| 2 | Previous month never receives final usage | **ADDRESSED** | P1 requires previous-month catch-up and a late-data policy; invoicing explicitly waits for closure; build step 1. |
+| 3 | Annual allowance subtracted monthly | **ADDRESSED** | Lines 97–103 explicitly establish monthly inclusions, no annual balance and no rollover. |
+| 4 | Route deletion erases historical attribution | **ADDRESSED** | P2 requires collection-time ownership or effective-dated history; build step 2. |
+| 5 | Lossy collection and misleading coverage | **ADDRESSED** | P3 and build step 3 require invoice-grade collection, durable writes and per-meter completeness. |
+| 6 | Unmetered replication-write costs | **ADDRESSED** | `durability_writes_1k` has a defined unit, rate, bounded monthly Business inclusion and build step 5. |
+| 7 | Direct object-store egress escapes billing | **ADDRESSED** | P5 introduces `store_egress_gb`, sharing the egress allowance, with an explicit pre-invoice gate and build step 4. |
+| 8 | Free lacks flush-only replication | **ADDRESSED** | The Free section names the new class and plan propagation; build step 5 includes both. |
+| 9 | Mutable plans defeat grandfathering | **ADDRESSED** | Subscriptions pin retained, immutable terms covering allowances, rates and band factors; build step 7. |
+| 10 | Pool funded by hypothetical revenue | **ADDRESSED** | Recognised subscription income, service-period allocation, discounts and refunds are specified; build step 15 gates publication. |
+| 11 | Bucket JSON cannot update the static site | **ADDRESSED** | The publication mechanism is corrected, static provision records are acknowledged, and build step 16 selects publishing a new static release. |
+| 12 | Stripe product fees omitted | **PARTIAL** | Billing’s 0.7% is incorporated, but [lines 75–80]( /home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md:75) defer Tax until the first review despite registrations being a launch prerequisite, and standalone overage invoices still omit the 0.4% Invoicing fee. |
+| 13 | Allowances and country-margin claim violate the formula | **PARTIAL** | Business costs **22.1808%**, contradicting the “never exceed a fifth” bound at [line 133](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md:133), while [line 199](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md:199) still claims identical margins immediately before correctly showing their drift. |
+| 14 | Storage break-even spends already-allocated revenue | **ADDRESSED** | The calculation now subtracts compute, egress and included replication costs before allocating the residual to storage. |
+
+Stripe’s current Irish pricing confirms the outstanding fees in #12. [Stripe pricing](https://stripe.com/ie/pricing).
+
+## 2. New findings only
+
+1. **[P1] A quantity or plan change can retrospectively change the previous month’s invoice.**
+
+ The revised algorithm reads the closed month’s usage but applies **the quantity and terms version the account currently holds** ([spec:447](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md:447)). The stored account fields describe current state; the billing snapshot preserves whatever calculation is first made. Neither establishes which entitlements applied during the usage month. The existing [`Statement`](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/internal/usage/statement.go:19) contains monthly meter totals, with no entitlement history.
+
+ For example, ten Business members consume 2,500 awake hours in September: 1,700 included, 800 excess. Ten members added on October 1, before September’s catch-up invoice, make the specified subtraction use 3,400 included hours and erase September’s excess. An accepted plan change can similarly substitute different historical rates.
+
+ **Fix:** retain effective-dated quantity and terms assignments, define allowance treatment for changes within a month, and bind the billing snapshot to the entitlements applicable during that month. Immutable plan definitions solve grandfathering; historical account assignments solve this separate boundary problem.
+
+2. **[P2] The new meters lack an explicit migration of the cost calculations that fund pool draw and the published books.**
+
+ The revision assigns collection of both meters, but expressly leaves the erroneous `requests_1k` cost treatment to an independent fix ([spec:173](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md:173)). Existing [`PriceAccount`](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/internal/economics/compute.go:100) explicitly prices only edge egress, edge requests and storage alongside allocated compute. Adding meter keys to statements does not make it consume them. Its [JavaScript counterpart](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/internal/console/templates/economics.html:662) has the same explicit inputs.
+
+ Consequently, both collectors can land while the dashboard still ignores actual store transfer and replication costs and charges fictional S3 costs for edge HTTP requests. That incorrect `CostUSD` flows directly into [pool draw](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/internal/console/economicsview.go:568). Replacing the pool’s revenue source in step 15 does not repair its expenditure side.
+
+ **Fix:** make the Go/JavaScript cost-consumer migration part of meter steps 4–5, including removal of the edge-request/S3-cost substitution. This needs a scope assignment, not implementation detail.
+
+3. **[P2] The durability worked example ignores its inclusion and silently multiplies the stated workload by ten.**
+
+ [Lines 169–171](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md:169) say a continuous writer producing 1M writes/month pays €2,760/year against €552 cost. Using the [request-rate anchor](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/internal/economics/scenario.go:145), those numbers represent **ten members each producing 1M writes/month**, before subtracting any inclusion.
+
+ With that intended ten-member workload, annual replication overage is:
+
+ `10 × 12 × (1,000 − 50) × €0.023 = €2,622`
+
+ Actual replication cost remains €552. If the sentence means one writer producing **1M total writes/month** in a minimum Business account, pooled inclusion is 500k/month: annual overage is **€138**, against **€55.20** replication cost. These amounts exclude the subscription.
+
+ **Fix:** state the workload’s account/member basis and subtract the fixed inclusion.
+
+4. **[P2] The discounted-margin claim was not updated for the revised Business inclusion.**
+
+ [Lines 247–249](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/docs/superpowers/specs/2026-09-07-carloku-pricing-plans-design.md:247) still claim 55–59% margin. With the revised inclusions and stated card-plus-Billing fees, discounted Business yields **53.34% in band A** and **53.15% in band D**. Personal reaches **54.06% in band D**. These reproduce from the [code’s storage, request and egress anchors](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/pricing-plans-spec/internal/economics/scenario.go:144), before Tax.
+
+ **Fix:** recompute the claim per plan; the discount remains profitable under these assumptions.
+
+The **main arithmetic tables are now sound under their stated fee assumptions**. Annual inclusion costs reproduce as €4.53504 / €9.324 / €110.904; residual storage break-evens are 75.594 / 159.876 / 1,538.051 GB. The displayed margins, affordability-band table, durability sensitivity rows and Free’s €3.45708 estimate also reproduce.
+
+The **six prerequisites form a coherent pre-invoice gate**: ownership, completeness and closure must cover both new meters as well as existing sources. Building them while tax registrations are pending is sound. The final sequencing claim overstates their independence, however: step 5’s **plan propagation** needs the plan/entitlement layer, and step 6 prepares billing rather than improving modelling. Separate those activation dependencies from the collectors, and include the cost-consumer migration above.
\ No newline at end of file