# 16 — Legacy (A1) user dashboard nav (agent 16/20) **Status:** Frontend nav + route guards aligned to the legacy image allow-list. **Coordinates with:** [`03-roles-matrix.md`](./03-roles-matrix.md), [`05-legacy-seed.md`](./05-legacy-seed.md) (agent 5), [`../plan-permissions/09-dashboard-gating.md`](../plan-permissions/09-dashboard-gating.md). --- ## PROBLEM Legacy tenants (A1 / Local Demo Co cohort) must see a flat primary nav matching the product screenshot — **without** Background Tasks / Processing, stores, or marketing suite chrome. --- ## Target nav (image order) | # | Label | Route | Feature key | |---|-------|-------|-------------| | 1 | Dashboard | `/dashboard` | `dashboard.overview` | | 2 | Products | `/products` | `catalog.products` | | 3 | Feeds | `/feeds` | `feeds.list` | | 4 | Export Feeds | `/export-feeds` | `feeds.export_feeds` | | 5 | Categories | `/categories` | `catalog.categories` | | 6 | Attributes | `/attributes` | `catalog.attributes` | | 7 | Standard Fields | `/standard-fields` | `catalog.standard_fields` | | 8 | Usage & Billing | `/billing` | `billing.overview` | | 9 | Settings | `/settings` | `settings.profile` | **Must be OFF (no nav link):** `processing.monitor` (Background Tasks), `stores.*`, `marketing.*`, `integrations.*`, `support.center`, catalog extras. When only the allow-list is ON, the **More** panel is omitted entirely (no empty More control). --- ## Implementation (this agent) | Piece | Path | Change | |-------|------|--------| | Primary nav order + labels | `apps/web/src/lib/components/Nav.svelte` | Flat primary = image list; Stores/Processing/marketing under More; hide More when empty | | Constants + upgrade titles | `apps/web/src/lib/plan-capabilities.ts` | `LEGACY_PRIMARY_NAV`, `LEGACY_NAV_DENIED_FEATURES`; upgrade copy for processing/stores/support/… | | Command palette | `apps/web/src/lib/components/CommandPalette.svelte` | Same labels; destinations filtered by `planCapabilities.can` | | Route guard (existing) | `PlanRouteGuard.svelte` | Deep-link to denied route → `PlanUpgradePanel` | | Dashboard chrome | `DashboardStats.svelte`, `dashboard/+page.svelte` | Hide processing quick link / stats / “View all” when `processing.monitor` OFF; gate store reconnect | **ASSUMPTION:** Nav visibility is driven solely by `GET /api/billing/capabilities` (and `/me` credits.features) — no client-side plan-name hardcoding. Backend legacy seed (agent 5) must return the deny map. --- ## API verification (after legacy seed) ### Expected for an A1 / Legacy company session ```http GET /api/billing/capabilities ``` | Key | Expected | |-----|----------| | `dashboard.overview` … `settings.profile` (nav parents) | `true` | | `processing.monitor` | `false` | | `stores.hub` | `false` | | `marketing.campaigns` / `brand_kit` / `seo` / … | `false` | | `integrations.ai` / `email` | `false` | | `support.center` | `false` | ### Live check (2026-08-05, local) | Check | Result | |-------|--------| | Demo login → Local Demo Co | Active plan resolved as **Enterprise** (`is_custom=true`) via capabilities | | Enterprise features | All nav parents **ON** including `processing.monitor` / `stores.hub` / marketing | | Admin `GET /api/admin/plans/5/features` (plan **A1**) | Name matches legacy pattern, but stored `features` JSON is a **partial** sparse map (shell/dashboard extras OFF only). Resolved still had `processing.monitor=true` on the **running** API process at verify time | | Company assignment | Local Demo Co was **not** on plan A1 / Legacy — still Enterprise | **Blocker for end-to-end image match on demo:** agent 5 seed must (1) apply full `SparseLegacyOverrides` to plan **A1** (or mark `is_legacy` and re-seed), (2) assign Local Demo Co / A1 tenant to that plan, (3) restart API so `DefaultPlanFeaturesEx` / `EnsureLegacyPlanFeatureSeeds` are live. Frontend is ready once capabilities return the legacy map. ### Manual UI checklist (once capabilities correct) - [ ] Sidebar shows exactly the 9 labels above (order + casing) - [ ] No “Processing” / Background Tasks, Stores, Campaigns, Brand, SEO, Support - [ ] No **More** panel (unless platform admin — then only Platform admin) - [ ] Direct `/processing`, `/stores`, `/campaigns` → upgrade panel, not empty shell - [ ] Command palette omits Processing / Support when denied --- ## Verification commands ```bash cd apps/web && npm run check ``` Go (seed / matrix; agent 5): ```bash cd apps/api && go test ./internal/billing/ -run Legacy -count=1 ``` --- ## CONTRACT - Public feature keys unchanged. - `PlanRouteGuard` behavior unchanged (in-place upgrade panel). - Platform admin (`showAdmin`) may still see Platform admin under More — orthogonal to plan matrix.