Phase 12: pricing model alignment + discount ladder + quota purchase model (D-21) #13
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Sub-issue of hero_onboarding#1.
Closes meta-issue Q#7 + aligns the pricing model to the meta-issue pricing table ($10/5VMs-month + $20/10VMs-month). Pre-Phase-12 code shipped a single-VM-$10-for-1-week placeholder; this rewrites the flow as a quota purchase model (Reading B): pay for a plan once → gain an N-VM allowance for the next 30 days → spin up VMs one-at-a-time over the period.
What landed
Schema (back-compat-safe, all new fields Option):
Billing+6 optional fields:current_plan_id,vm_quota_total,vm_quota_used,vm_quota_period_end,first_paid_at,last_active_atVmAllocation+plan_id?: strUsageRecord+applies_to?: ResourceCategory(new enum:hero_os_hourly | llm | vm)Server:
crates/hero_onboarding_server/src/plans.rs(~270 LOC, 12 unit tests) — PlanConfig + parse_plans_json + default_plans matching meta-issue ($10/5VMs-month + $20/10VMs-month) + validate_plans + find_plan_by_idcrates/hero_onboarding_server/src/discount_ladder.rs(~280 LOC, 21 unit tests) —effective_cost_centspure fn (Q#7 multiplier table),tier_for_tenure_days,has_active_plan,should_set_first_paid_at,touch_last_active,run_tickPOST /plan/buyroute (cookie + KYC + balance pre-flight + active-plan gate; 6 error codes)vm_allocate_postfor quota model (active-plan check + quota check + plan_id snapshot + expires_at override to matchvm_quota_period_end+ quota_used increment; per-VM cost =plan.cost_cents / plan.vm_countfor audit)POST /admin/discount-ladder-tickadmin-secret-gated routeusage_aggregate::apply_record(multiplier table at decrement site +touch_last_active)webhook_poststampsfirst_paid_aton first credit (set-once invariant)RecordUsagePayload+applies_toproducer-side pipe-throughDashboard: plan-selector buttons (no active plan) OR quota panel + Spin up VM button (active plan); 6 new error codes +
plan_purchasedevent banner; discount tier label next to credit balance.CLI: new
hero_onboarding_discount_ladder_cronaction (24h default;HERO_ONBOARDING_DISCOUNT_LADDER_CRON_INTERVAL_MSoverride). FORWARDED_ENV +2.Admin daemon: BillingRow +6 fields; AllocationRow +
plan_id; newdiscount-ladder --oncesubcommand mirror ofaggregate --once;/users+4 columns;/allocations+1 column.Runbook: new §3.7 Plan configuration + §3.8 Discount ladder operator semantics (~330 LOC).
D-21
Minted at
decisions/D-21-discount-ladder-mechanics.md(workspace, not in this repo). Locks 6 surfaces:first_paid_at(no inactivity reset in v0; slot reserved for the ~15 LOC bolt-on later).none ×1.0,week ×0.5,month ×0.25(75% total at month-tier). Flip to additive cap is a 1-char change.default_plans()fallback matching meta-issue. Flip to OSIS rootobject is ~40 LOC + 7 trigger stubs./plan/buyrejects with?error=plan_activeifvm_quota_period_end > now. Flip to upgrade-while-active is ~10 LOC.Acceptance
cargo test --workspace110/110 (+33 vs s2-013 baseline of 77: +12plans+ +21discount_ladder)cargo fmt --checkcleancargo clippy --workspace --all-targets -- -D warningscleanlab build --release --install --workspaceVICTORY 3/3 (build #16)lab infocheck3/3 clean / 0 findingsscripts/smoke_discount_ladder.sh24/24 GREENscripts/smoke_vm_allocate.sh(rewritten for quota model) 27/27 GREENPhase B findings
webhook_post:1630(cited :1713) +vm_allocate_post:2501(cited :2635). Substantive shapes hold.email-provider-sendgrid. Per race rule, Phase 12 mints D-21.ResourceKind+ResourceCategorykept separate. ResourceKind is producer-side measurement unit (vm_hour,llm_token,hero_os_hour,other); ResourceCategory is aggregator-side discount-applicability category (hero_os_hourly,llm,vm). 1-1 mappable but schema language has no type aliases. Back-compat defaultapplies_to: None→ treated ashero_os_hourly.?: Option<T>for back-compat with pre-Phase-12 OSIS rows (codegen emits serde-strict fields without#[serde(default)]).Phase B.5 SKIPPED per standing criteria (no theorem / wire protocol / migration / crypto; pure-fn business logic).
Tracking
development(commit TBD recorded at /stop2)sessions/2-014-hero-onboarding-phase-12-pricing-discount.ymlSigned-by: mik-tf mik-tf@noreply.invalid
Squash-merged to
developmentasf667272. Feature branchtrack-agent-2/phase-12-pricing-discountdeleted (remote + local). Acceptance gates GREEN: cargo test 110/110, fmt + clippy clean, lab build VICTORY 3/3 (build #16), lab infocheck 3/3 clean, smoke_discount_ladder 24/24, smoke_vm_allocate 27/27.Signed-by: mik-tf mik-tf@noreply.invalid