Files
greeneclipse 8580c996c3 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.
2026-08-09 22:47:43 +02:00

5.0 KiB
Raw Permalink Blame History

08 — Admin Permissions UI (agent 8/20)

Owns: Admin → Billing → Permissions tab (PlanPermissionsPanel + admin-plan-permissions client).
Entry: /admin/billing → Permissions.
Docs home: README.md (when present) · prior matrix: ../plan-permissions/.


PROBLEM

Make plan feature editing clean and usable: named profiles (Legacy / Free / Starter…), bulk section toggles, search/filters, clear default vs custom, and one-click Legacy for A1-like plans — wired to real admin APIs (no stub mode).


Features delivered

  1. Plan profiles — Legacy, Free, Starter, Growth, Business, Enterprise/all-on. Apply writes a full override matrix via PUT /api/admin/plans/{id}/features.
  2. Legacy (A1) — Allowlist nav (Dashboard, Products, Feeds, Export Feeds, Categories, Attributes, Standard Fields, Billing, Settings). processing.monitor and stores/marketing/integrations/support extras stay OFF. Prominent Apply Legacy (A1) when the selected plan is A1-like (A1*, name contains legacy, or is_legacy).
  3. Bulk section toggles — Per-plan Enable/Disable section (all keys in that section). Global section masters stay in the right rail (optional “+ features” updates global feature-gate rows).
  4. Search / filters — Text (key or label), section filter, state filter (all / enabled / disabled / differs from plan-name default).
  5. Default vs custom — Badges: Legacy / Default ladder / Custom deal; Defaults vs Custom overrides; profile chip shows ✓ when the resolved matrix matches a named profile; Clear overrides sends {}.
  6. Real APIs — No 404 stub / in-session-only path. Mutations use feature endpoints; errors surface in alerts.

Source files

File Intent
apps/web/src/lib/components/admin/PlanPermissionsPanel.svelte Permissions checklist UI
apps/web/src/lib/admin-plan-permissions.ts Profiles, Legacy detect, API client
apps/web/src/lib/plan-feature-catalog.ts Catalog / sections (shared)
apps/web/src/routes/admin/billing/+page.svelte Hosts Permissions tab

API contract used

Method Path Use
GET /api/admin/plans List packages
GET|PUT /api/admin/plans/{id}/features Load / replace overrides
POST /api/admin/plans/{id}/features/enable-all Full ON
POST /api/admin/plans/{id}/features/disable-all Full OFF
GET|PUT /api/admin/feature-gates Global masters
PUT /api/admin/feature-gates/sections/{section} Global section switch

Auth: session + platform admin + CSRF.


Legacy allowlist (summary)

Canonical ON set matches 03-roles-matrix.md / legacy_user — including AI titles/descriptions, API keys, and capability.ai_processing / api_access. Shell skips shell.support_notifications; dashboard skips dashboard.store_reconnect.

OFF (among others): processing.monitor, all stores.*, all marketing.*, integrations, support tickets, campaign/email/brand/SEO/BYOK capabilities.

Machine source: LEGACY_FEATURE_ALLOWLIST in admin-plan-permissions.ts. Backend seed (agent 5) should align; UI Apply Legacy persists even if seed lags.


Visual language

Uses admin shell tokens (border-border, bg-card, text-muted-foreground, bg-primary/15 active chips) — same vocabulary as AdminNav / agent 7 shell — not hard-coded slate cards.


Manual verify

  1. Platform admin → /admin/billingPermissions.
  2. Select Free → profile chip should show Free ✓ (or Apply Free). Toggle one key → Custom overrides + Differs badge.
  3. Select A1 (or create an A1-named deal) → Apply Legacy (A1)processing.monitor off; Products/Feeds on. Reload → persisted.
  4. Section Enable section / Disable section on Catalog for the selected plan only.
  5. Flip a Global section switch; confirm tenant capabilities respect it (agent 9/16).
  6. Clear overrides → Defaults badge; resolved view matches plan-name defaults (Legacy-like names still resolve Legacy on the client when empty).

Coordination

Agent Touchpoint
3 / 4 Roles matrix + contract — profiles follow Legacy allow-nav
5 Backend Legacy seed / is_legacy — UI already detects A1 + is_legacy
7 Admin shell tokens — Permissions uses the same
9 Plans table → Edit features deep-link (unchanged prop selectedPlanId)
16 User nav gating consumes capabilities after Legacy apply
19 Defaults alignment — keep LEGACY_FEATURE_ALLOWLIST in sync with seeds

ASSUMPTIONS

  1. ASSUMPTION: Empty plans.features means “use defaults”; Apply Profile always writes an explicit full map.
  2. ASSUMPTION: Until agent 5 seeds Legacy on the API, A1 empty overrides may resolve all-ON server-side; Apply Legacy is the reliable admin path.
  3. Global “Off + features” updates global feature masters, not every plans overrides.