Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user