Files
Hanzo AI c61b58d92d Add Subscription Plans admin editor (commerce plan SoT, increment 3a-console)
admin.hanzo.ai CMS editor for the platform subscription/DNS plan authority
(commerce models/plan — the SoT GET /v1/billing/plans + the internal-ledger
renewal charge read). Sibling of the Catalog editor over the same SuperAdmin
CRUD pattern (/v1/plans/entries), reusing its tested money + metadata logic.

- PlansCatalogModule: table (filter by category, monthly/annual price, custom/
  per-seat flags) + SlideOver create/edit form (name/price/annual/category/
  contactSales/popular/perSeat/trialDays + metadata) + delete confirm + seed.
  LIVE BILLING CONTROL: price edits change the real renewal charge (explicit
  warning); SLUG IMMUTABLE on edit (matches the commerce guard); contactSales =
  custom (null price), distinct from a free $0 tier.
- plans-admin.ts: /v1/plans/entries client (bare-JSON REST, defensive normalizers)
  via cloudProxyV1Url — works on the go:embed cloud console and standalone alike.
- app/v1/plans/[...path]: dedicated user-bearer proxy to commerce (sibling of
  /v1/catalog); allowPlansSurface least-privilege allow-list (entries CRUD + seed).
  commerce requireSuperAdmin (owner==admin) is the authoritative gate.
- pricing/MetadataEditor: extracted the shared key/value editor (DRY — catalog +
  plans now use one component). plans/logic reuses catalog/logic money helpers.
- registry: 'plan-catalog' admin entry (Observe, admin:true).

No 'published' field (Plan has none — not invented). Verify: tsc 0 errors;
vitest 2833 passed (+8: plans logic + proxy-allow); next build + build:embed
green (/v1/plans registered); commerce api/plan handler tests green; live
Playwright proof (5 plans render, edit pro $20->$25 -> PUT /v1/plans/entries/pro
price 2500, slug immutable, metadata type-exact -> table reflects $25.00/mo).
2026-07-22 13:54:38 -07:00
..