Implement the ux-first-run change: a state-derived setup checklist on
/operator/setup with a landing region that recedes once required steps
are done, and empty states that distinguish blocked from empty across
operator and member surfaces. Also add production deployment and
environment reference docs, plus a config-key completeness test.
Squash the pre-production migration history into fresh core, fedwiki,
and stripe baselines and reduce the canonical source list to those
three streams.
Update sqlc configs, generated queries, raw SQL, tests, and docs while
keeping provider tables schema-qualified.
BREAKING: existing local database volumes must be wiped because goose
version history restarts from the new baselines.
Add first-class default-price support: a product has a single default price
that readiness, the member catalog, and checkout all track.
- Migration 00016: is_default column + partial unique index (one default per
product) + backfill (oldest active price per product).
- New queries: GetDefaultPriceByProduct, ClearDefaultPrice, MarkDefaultPrice,
DeactivatePrice (guarded by is_default = FALSE).
- CreatePrice: first price for a product auto-becomes default (NOT EXISTS probe);
success copy differentiates auto-default from subsequent non-default prices.
- Per-row price affordances: Sync (posts price_id, hx-vals), Make default
(clear-then-set transaction), Deactivate (default-price guard).
- computePriceReadiness tracks the default price; resolvePurchasable documented
as the shared purchasability gate.
- SyncProductToStripe: selectable price (explicit price_id or default);
product-idempotent — product-synced guard prevents duplicate Stripe products.
- All error paths route through web.FieldErrorsFromDB (422) or slog+generic text,
never err.Error().
- Render tests for default badge, per-row affordance visibility, form-level
FieldErrors alert.
Closes: openspec/changes/multi-price-support