| 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 |
| |