Skip to content
Last updated Give Feedback

Super-admin overview

apps/super-admin ships in every customer distribution (option c+ per ADR-015). Standard tier customers see license + entitlement panels. Enterprise tier unlocks tenant provisioning + white-label config + marketplace publisher.

The console runs on port 3002 (or https://superadmin.<your-domain> in production). It’s separate from apps/admin (the per-tenant operator UI on port 3001) — super-admin operates on the platform; admin operates on a single tenant.

PanelPathWhat it doesLicense gate
Dashboard/dashboardCross-tenant KPIs (active tenants, MRR, license status, error rates)always
Tenants/tenantsProvision, suspend, restore, delete tenantstenant_provisioning
Plans/plansSubscription tiers + price points + white-label / marketplace flagsalways
Permissions/permissionsPlugins + niches enabled per planalways
Plugins/pluginsCatalog + per-tenant enable / disable / version pinningmarketplace_publisher (publish)
Niche Packages/niche-packagesManage the four canonical packages + custom variantsalways
Licenses/licensesIssue, revoke, refund, re-send licensesalways
Customer Installs/installsHeartbeat health + grace state per running customer copyalways
Themes/themesTheme catalog + per-tenant activationalways
Audit Log/audit-logForensic license events (issue / revoke / heartbeat / suspect)always
Activity/activityCross-panel activity feed (actor + action + target + ts)always
Configurare/settingsSystem settings (SMTP, ANAF SPV link-up, branding, custom domains)white_label (branding)

The “License gate” column maps to entries in the customer JWT features array — see License.

Cross-tenant KPIs:

  • Active tenants count + delta (this week / this month)
  • MRR projection from active subscriptions (license-server data)
  • License health — number of installs in ok / warning / reduced / locked grace state
  • Error rate (last 24 h) from the observability stack — pulled from SENTRY_DSN if configured
  • Latest events — recent license issuances, tenant creations, plugin enables

Use it as the first stop after login. Anything red → drill into the matching panel.

Two layers control what each operator can do:

  1. Operator role — set per super-admin user account. Roles are owner, support, read-only. The owner has full access; support can read everything but only mutate tenant + plugin records (not plans / settings); read-only sees data but no mutation buttons.
  2. License feature gates — even an owner operator cannot unlock panels that the customer’s license doesn’t grant. e.g. a customer on pro tier can’t see the white-label config — the route 404s server-side regardless of UI state.

The double layer means a stolen super-admin token cannot, on its own, unlock features the customer never paid for.

Login at /login with the email + password set during onboarding. Production deployments must enable 2FA (TOTP) — the toggle is in /settings → Security. The login page also enforces a 5-attempt rate limit per IP.

If the operator forgets the password and 2FA is enabled, recovery requires both:

  • The recovery code printed during 2FA setup (one-time, can’t be re-issued)
  • A console-level reset run by the platform owner: node --experimental-strip-types apps/super-admin/scripts/reset-operator.ts <email>

There is intentionally no email-based password reset. Super-admin is too high-trust for self-service recovery.

Every super-admin write is recorded. The log row schema:

{
ts: ISO timestamp,
actor_id: super-admin user id,
actor_email: snapshot,
action: 'tenant.create' | 'tenant.suspend' | 'license.issue' | 'license.revoke' | ...,
target_type: 'tenant' | 'license' | 'plugin' | 'plan' | 'settings',
target_id: uuid,
before: jsonb (snapshot before mutation),
after: jsonb,
ip: inet,
user_agent: text,
}

Read-only operators can view the log but cannot delete entries. The log is append-only at the DB level — even the platform owner cannot rewrite it without dropping the table outright.

The super-admin shell uses an indigo accent (#4f46e5-ish) — distinct from the orange/cyan tenant admin and the blue docs. The split is intentional and load-bearing per CLAUDE.md §0 — operators must immediately know which surface they’re on. Don’t unify the palette.

  • Tenants — provisioning lifecycle
  • Licenses — issue / revoke / refund flows
  • Plans — tier matrix + white-label + marketplace publisher
  • Plugins — catalog + per-tenant enable + publishing
  • Customer Onboarding — first-time provisioning playbook
  • License — JWT shape + tier matrix