# 05 — Legacy plan feature seed (agent 5/20) **Status:** Implemented in `apps/api/internal/billing`. **Coordinates with:** [`03-roles-matrix.md`](./03-roles-matrix.md), [`04-contract.md`](./04-contract.md), [`docs/plan-permissions/06-defaults-matrix.md`](../plan-permissions/06-defaults-matrix.md). --- ## PROBLEM A1 / migrated packages previously resolved as **custom all-ON**, which exposed Background Tasks (`processing.monitor`), stores, marketing, etc. Legacy tenants must get the **image-nav** matrix only. --- ## Behavior | Concern | Implementation | |---------|----------------| | Profile | `PlanProfileLegacy` / `ResolvePlanProfile` | | Allow-list | `LegacyFeatureAllowed` + `legacyFeatureAllowlist` in `legacy_plan.go` | | Defaults | `DefaultPlanFeatures` / `DefaultPlanFeaturesEx` check legacy **before** custom all-ON | | Sparse store | `SparseLegacyOverrides` / `SparseDefaultOverridesEx` | | Detect | `IsLegacyPlanName` (exact `legacy`, `A1` / `A1 …`), `IsLegacyPlan(name, is_legacy)`, `IsLegacyCompanyID` | | Column | `plans.is_legacy` via `028_plan_is_legacy.sql` (additive; code falls back if missing) | | Seed | `EnsureDefaultFeatureSeeds` → `EnsureLegacyPlanFeatureSeeds` → `EnsureLegacyDefaults` | | Reset | `ApplyDefaultMatrix` writes sparse legacy for legacy plans | | Create | `prepareCustomPackageCreateFeatures` seeds sparse legacy for A1-named plans | ### Seed / backfill rules (`EnsureLegacyDefaults`) 1. Upsert plan row named **Legacy** (`is_legacy=true`). 2. For each plan matching name or `is_legacy`: - **empty** `features` → write `SparseLegacyOverrides` - **full enable-all** map (prior custom create) → repair to sparse legacy - **`is_legacy=true`** → re-apply sparse legacy - **non-empty customized** (not enable-all, not flagged) → **leave alone** 3. Assign Legacy plan to A1 cohort companies (`legacy_company_id` / A1 name / Local Demo Co stand-in). ### Explicitly OFF (examples) - `processing.monitor` (Background Tasks) - all `stores.*`, `marketing.*`, `integrations.*`, `support.*` - `catalog.structured_descriptions`, `catalog.vector_categories` - `shell.support_notifications`, `dashboard.store_reconnect` - `capability.byok`, campaign/email/brand/seo capabilities ### Explicitly ON (image-nav) Dashboard, Products, Feeds, Export Feeds, Categories, Attributes, Standard Fields, Usage & Billing, Settings — plus required shell/capabilities for catalog AI. --- ## Verification ```bash cd apps/api go test ./internal/billing/ -count=1 -run "Legacy|DefaultPlanFeatures|SparseDefault|IsCustomPackage|Prepare" ``` --- ## ASSUMPTIONS 1. Name patterns from agent 3 win over `is_custom` for matrix resolution. 2. Non-legacy client deals (e.g. Merkur) remain enable-all custom. 3. Local Demo Co may be treated as A1 stand-in during demo seed when remapped.