Files
descrybe/docs/admin-roles-support/03-roles-matrix.md
T
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

11 KiB
Raw Blame History

03 — Roles & legacy plan matrix (agent 3/20)

Status: Design contract for admin roles + legacy cohort packaging.
Machine-readable twin: 03-roles-matrix.json.
Feature keys: align with docs/plan-permissions/01-feature-keys.json.
Plan defaults (public ladder): docs/plan-permissions/06-defaults-matrix.json.


PROBLEM

Migrated / legacy tenants (example: A1 → Local Demo Co catalog) must see a narrow product surface matching the legacy nav only — not the full v2 Operate/Setup marketing suite. Separately, platform roles need a clear permission ceiling that composes with plan feature keys.


Effective resolution

effective(feature) =
  role_allows(role, feature)
  AND plan_allows(company.plan, feature)
  AND global_section_enabled(section(feature))
  AND global_feature_enabled(feature)
  • Company end-users (legacy_user, standard_user): plan matrix is the primary gate; role is the ceiling.
  • Staff roles (admin, developer, support_staff): role ceiling is wide; company plan still applies when acting as a tenant unless impersonation / platform override is explicit.
  • Platform admin routes (/admin/*) are orthogonal to dashboard feature_keys — gated by users.is_platform_admin (and future staff flags), not by plan JSON.

ASSUMPTION: legacy_user / standard_user are product-cohort roles derived from plan name patterns (and/or an explicit plans.cohort = legacy|standard when implemented), not company membership admin|member.
ASSUMPTION: A1 company / plan example maps to the legacy plan profile (see plan name patterns below).


Legacy nav allow-list (ONLY)

These are the only user-facing nav destinations for the legacy cohort. Everything else is OFF.

Nav label Route Parent feature key(s)
Dashboard /dashboard dashboard.overview
Products /products catalog.products
Feeds /feeds feeds.list (+ mapping)
Export Feeds /export-feeds feeds.export_feeds
Categories /categories catalog.categories
Attributes /attributes catalog.attributes
Standard Fields /standard-fields catalog.standard_fields
Usage & Billing /billing billing.overview
Settings /settings settings.profile (+ settings tabs)

Explicitly excluded from legacy

Surface Reason
Background Tasks / Processing (processing.monitor) Out of legacy nav
Stores / Woo / Shopify Out of scope
Marketing campaigns, content calendar Out of scope
Brand kit / brand AI Out of scope
SEO Out of scope
Reviews Out of scope
AI integrations / Email sending Integration extras beyond feeds
Support center (tickets) Support-heavy; not essential for legacy nav
Structured descriptions / vector categories Extra catalog tools, no legacy nav
Platform admin chrome Staff-only (admin / developer)

Legacy feature allow-list (ON keys)

Canonical ON set for plan profile legacy (and role legacy_user). All other keys in 01-feature-keys.json are OFF.

Shell

  • shell.navigation
  • shell.command_palette
  • shell.company_switcher
  • shell.tutorial
  • shell.account_menu
  • shell.billing_recovery_banner

OFF: shell.support_notifications

Dashboard

  • dashboard.overview
  • dashboard.stats
  • dashboard.quick_links
  • dashboard.recent_jobs (informational only; no Processing nav)
  • dashboard.news_feed
  • dashboard.activation_checklist
  • dashboard.migrated_checklist
  • dashboard.etl_gaps
  • dashboard.upgrade_banners

OFF: dashboard.store_reconnect

Catalog

  • catalog.products (+ all product tabs)
  • catalog.products.tab_processed
  • catalog.products.tab_needs_review
  • catalog.products.tab_error
  • catalog.products.tab_processing
  • catalog.products.tab_unprocessed
  • catalog.products.process_categories
  • catalog.products.process_attributes
  • catalog.products.process_ai_titles
  • catalog.products.process_ai_descriptions
  • catalog.products.enrichment_review
  • catalog.products.export_selection
  • catalog.products.upgrade_prompt
  • catalog.categories
  • catalog.categories.title_formula
  • catalog.categories.description_formula
  • catalog.attributes
  • catalog.attributes.bulk_import
  • catalog.standard_fields
  • catalog.standard_fields.groups

OFF: catalog.structured_descriptions, catalog.vector_categories

Feeds (import + export + CSV uploads needed for feeds)

  • feeds.list
  • feeds.add_url
  • feeds.add_csv
  • feeds.sync
  • feeds.mapping
  • feeds.mapping.select_item
  • feeds.mapping.map_fields
  • feeds.export_feeds
  • feeds.export_feeds.create
  • feeds.export_feeds.generate
  • feeds.uploads

Billing (Usage & Billing)

  • billing.overview
  • billing.customer_portal
  • billing.quick_upgrade
  • billing.plans_compare
  • billing.checkout

Settings

  • settings.profile
  • settings.company
  • settings.alerts
  • settings.api_keys
  • settings.team
  • settings.team_invite

Capabilities (core catalog/feeds only)

  • capability.sku_cap
  • capability.ai_credits
  • capability.ai_processing
  • capability.eprel
  • capability.normalize_specs_fill
  • capability.feed_source_limit
  • capability.export_feed_limit
  • capability.storage_limit
  • capability.api_access

OFF: capability.campaign_ai, capability.email_live_send, capability.brand_ai_apply, capability.seo_ai_rewrite, capability.byok

Entire sections OFF for legacy

  • stores.* — all keys
  • processing.* — processing.monitor
  • marketing.* — all keys
  • integrations.* — all keys
  • support.* — all keys

Plan name patterns → profile

Pattern (case-insensitive) Profile Notes
exact legacy legacy Explicit legacy package
^a1(\b|[\s_-]) / contains a1 slovenija legacy A1 company / plan example
company display historically A1 Slovenija (MySQL 97e1a309-…) legacy Even if renamed to Local Demo Co for demo
exact free | starter | growth | business | enterprise standard (+ ladder tier) Public ladder
is_custom=true and name does not match legacy patterns custom All-on defaults per plan-permissions contract
unknown / empty standard / Free Fail closed to Free matrix

A1 example = legacy. Treat A1s assigned plan (or a dedicated Legacy plan row seeded for that tenant) as the legacy profile.


Roles

Role key Who Plan / feature source Ceiling
legacy_user End-user on a legacy-pattern company/plan legacy matrix Legacy allow-list only
standard_user End-user on public ladder Plan matrix from 06-defaults-matrix (Free→Enterprise) Full catalog; plan denies Free/Starter AI/BYOK/etc.
admin Platform admin (users.is_platform_admin) N/A for /admin/*; full dashboard keys ON All feature keys + AdminNav
developer Engineering / ops with platform access Same as admin + debug catalog extras always ON All keys; intended for non-prod diagnostics
support_staff Support agents Support + read-heavy tenant assist Support keys ON; marketing/integrations mostly OFF; no destructive platform settings

Role notes

legacy_user

  • Sees only the legacy nav allow-list.
  • AI titles/descriptions + credits remain ON (legacy customers processed catalog data).
  • No stores, processing monitor, marketing, brand, SEO, integrations extras, or support ticket UI.

standard_user

  • Full v2 dashboard surface as allowed by their public plan (see 06-defaults-matrix.json).
  • Role matrix in JSON is the ceiling (all registry keys true); Free/Starter denials still apply via plan.

admin (platform)

  • is_platform_admin = true.
  • All dashboard feature keys ON.
  • Platform surfaces: Overview, Users, Analytics, Platform billing, Support, Stuck Products, Platform settings (AdminNav.svelte).
  • May impersonate users (non-prod / gated admin APIs).

developer

  • Same feature ceiling as admin.
  • Explicitly keeps debug/extra catalog keys ON (catalog.vector_categories, catalog.structured_descriptions).
  • Expected to use platform admin + API tooling; not a customer-facing role.

support_staff

  • Dashboard: shell + dashboard overview/stats + support.* ON.
  • Catalog/feeds/billing: read-assist — parent keys ON so staff can open customer context when impersonating; write-heavy marketing/integrations OFF.
  • Platform: Support queue (/admin/support), Users (limited), Stuck Products; not Platform settings or Platform billing write.
  • [UNCERTAIN] No dedicated is_support_staff column today — design assumes a future staff flag or group; until then map to a subset of platform-admin users.

Role × section summary

Section legacy_user standard_user admin developer support_staff
shell (core) ON ON ON ON ON
shell.support_notifications OFF ON ON ON ON
dashboard (core) ON ON ON ON ON
dashboard.store_reconnect OFF ON ON ON OFF
catalog (products/categories/attributes/standard fields) ON ON ON ON ON†
catalog extras (structured/vector) OFF ON ON ON OFF
feeds (+ export + uploads) ON ON ON ON ON†
stores OFF ON ON ON OFF
processing.monitor OFF ON ON ON ON†
marketing OFF ON ON ON OFF
integrations OFF ON ON ON OFF
billing ON ON ON ON ON†
settings ON ON ON ON ON†
support OFF ON ON ON ON
capabilities (core AI/SKU/feeds) ON plan ON ON ON†
capabilities (campaign/email/brand/seo/byok) OFF plan ON ON OFF
/admin/* OFF OFF ON ON partial

† support_staff: intended for assisted sessions / impersonation; not for self-serve marketing ops.


COMPOSITION with company membership

Existing company membership roles (admin | member) stay orthogonal:

Concern Gate
Invite / team / API keys / Stripe portal company admin (or platform admin)
Which nav/features appear plan profile + product role (legacy_user / standard_user)
Platform console is_platform_admin / staff role

Do not overload company membership admin with platform admin.


IMPLEMENTATION HOOKS (non-binding)

Need Likely home
Resolve legacy profile from plan name DefaultPlanFeatures / plan name normalizer beside public ladder
Seed Legacy plan row EnsureDefaultPlans + assign to A1/demo migrated tenant
Staff role flag users column or staff group — [UNCERTAIN] until agent/schema decides
Nav filter existing feature on Nav.svelte items + ResolveFeatures

VERIFICATION checklist

  • Legacy matrix ON keys ⊆ 01-feature-keys.json
  • No processing.monitor, stores.*, marketing.*, integrations.*, support.* ON for legacy
  • A1 / legacy name patterns resolve to legacy profile
  • standard_user ceiling does not bypass Free/Starter denials in 06-defaults-matrix
  • Platform admin retains /admin/* independent of plan JSON