Skip to content

Asset Admin — Distributor Site

Version: 1.1.0 Date: 2026-04-26 Site Key: asset-admin-distributor Site Family: CRUD-Sites (with embedded Metric pages) App URL: assets.omnivoltaic.com Dev Port: 3200 Extends: all-sites.md


Site Purpose

Authenticated operational portal for Omnivoltaic distributors, distributor staff, general agents, super admins, and customers. Provides full lifecycle management of PayGo asset accounts, fleets, items, customers, personnel, payments, events, and support tickets. Embeds fleet health and device monitoring dashboards powered by live telemetry.

This is the first documented site in the CRUD-Sites family. It is also the first surface where Metric-family pages appear within a CRUD app shell.


Roles and Access

The app is scoped to five authenticated roles. Role is decoded from the JWT access token stored in localStorage as access_token. Role names match the JWT roleName claim exactly, including the space in GENERAL AGENT.

Role (JWT roleName) Description
SUPER_ADMIN Cross-distributor administrator
DISTRIBUTOR Root distributor account
DISTRIBUTOR_STAFF Staff operating under a distributor
GENERAL AGENT Field agent
CUSTOMER End customer (limited surface)

Visibility is implemented through a positive whitelist (allowedRoles) on each navigation item and page. The runtime equivalent in the existing app is canViewMenu(menuId) over a menuPermissions map keyed by role.


Six top-level sections. The same menuId values used at runtime in the existing app are declared here so that scaffold output preserves the permission model.

Section menuId Allowed Roles
Dashboards (/dashboards) dashboard SUPER_ADMIN, DISTRIBUTOR, DISTRIBUTOR_STAFF, CUSTOMER
Personnel staff DISTRIBUTOR, DISTRIBUTOR_STAFF
  Distributor Staff (/staff/distributor-staff) distributor_staff DISTRIBUTOR
  Agents (/staff/agents) agents DISTRIBUTOR_STAFF
Accounts accounts DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT
  Customers (/accounts/customers) DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT
  PayGo (/accounts/asset-accounts) DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT
  Payments (/accounts/asset-accounts/payments) DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT
  Pay Plans (/accounts/payment-plans) DISTRIBUTOR, DISTRIBUTOR_STAFF
  Message Templates (/accounts/message-template) DISTRIBUTOR, DISTRIBUTOR_STAFF
  Message Groups (/accounts/message-group) DISTRIBUTOR, DISTRIBUTOR_STAFF
Assets thing DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT
  Fleets (/thing/fleet) DISTRIBUTOR, DISTRIBUTOR_STAFF
  Items (/thing/item) DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT
Events (/events/items) events SUPER_ADMIN, DISTRIBUTOR, DISTRIBUTOR_STAFF
Support (/support/tickets) support SUPER_ADMIN, DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT, CUSTOMER

Data Sources

Source URL Used For
GraphQL (federated) https://federated-graphql-api.omnivoltaic.com/graphql All entity CRUD and fleet health queries
REST API https://api.omnivoltaic.com Auth login, support tickets, agent listings
Dash API https://dash.omnivoltaic.com Device monitoring, device-by-viewport map

Pages

All 31 pages declared by the intent. Page Family is crud, metric, or auth. Auth pages are public.

Auth (public)

Page Key Route Theme
signIn /signin SignInPage
signUp /signup SignUpPage
signUpWithRoleToken /signup/[...roleToken] SignUpPage (token-bound invitation)
resetPassword /reset-password ResetPasswordPage (request flow)
passwordResetWithToken /auth/passwordreset/[token] ResetPasswordPage (set-new-password flow)

Dashboards — Metric family

Page Key: dashboards · Route: /dashboards · Theme: DashboardShellPage Allowed Roles: SUPER_ADMIN, DISTRIBUTOR, DISTRIBUTOR_STAFF, CUSTOMER (NOT GENERAL AGENT)

Three tabs:

  • AssetsFleetHealthDashboard, GraphQL getFleetHealthSummary with pagination. SUPER_ADMIN falls back to viewport-based device loading to avoid gateway overload.
  • Device MonitoringDeviceMonitoringDashboard, Dash API, map enabled, viewport-based loading via /devices/by-viewport.
  • Custom DashboardsCustomDashboardBuilder, configuration persisted to localStorage under dashboardConfig.

Personnel — CRUD

Page Key Route Theme Allowed Roles
distributorStaff /staff/distributor-staff RecordListPage DISTRIBUTOR
distributorStaffAdd /staff/distributor-staff/add RecordFormPage DISTRIBUTOR
agents /staff/agents RecordListPage DISTRIBUTOR_STAFF
agentsAdd /staff/agents/add RecordFormPage DISTRIBUTOR_STAFF

Accounts — Customers — CRUD

Page Key Route Theme
customers /accounts/customers RecordListPage
customersAdd /accounts/customers/add RecordFormPage
customersEdit /accounts/customers/edit/[id] RecordFormPage

Allowed roles for all three: DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT.

Accounts — PayGo Asset Accounts — CRUD

PayGo accounts have a list page plus six per-account workflow/detail routes. Allowed roles for all: DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT.

Page Key Route Theme Purpose
assetAccounts /accounts/asset-accounts RecordListPage List all PayGo accounts
assetAccountActivate /accounts/asset-accounts/activate/[id] WorkflowPage Activate account
assetAccountPair /accounts/asset-accounts/pair/[id] WorkflowPage Pair account to an item
assetAccountLinkPayPlan /accounts/asset-accounts/link-payplan/[id] WorkflowPage Attach a pay plan
assetAccountCodeGeneration /accounts/asset-accounts/code-generation/[id] WorkflowPage Generate unlock codes (days / reset / free)
assetAccountCodeHistory /accounts/asset-accounts/code-history/[id] RecordDetailPage View code history
assetAccountPayments /accounts/asset-accounts/payments/[id] RecordDetailPage Per-account payment history
payments /accounts/asset-accounts/payments RecordListPage Aggregated payments across all accounts

Accounts — Pay Plans — CRUD

Allowed roles: DISTRIBUTOR, DISTRIBUTOR_STAFF.

Page Key Route Theme
paymentPlans /accounts/payment-plans RecordListPage
paymentPlansAdd /accounts/payment-plans/add RecordFormPage
paymentPlansEdit /accounts/payment-plans/edit/[id] RecordFormPage

Accounts — Messaging — CRUD

Allowed roles: DISTRIBUTOR, DISTRIBUTOR_STAFF.

Page Key Route Theme
messageTemplates /accounts/message-template RecordListPage
messageGroups /accounts/message-group RecordListPage

Assets — CRUD

Page Key Route Theme Allowed Roles
fleets /thing/fleet RecordListPage DISTRIBUTOR, DISTRIBUTOR_STAFF
items /thing/item RecordListPage DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT

Item operations include CSV export and assignment to agents.

Events — Metric family

Page Key: itemEvents · Route: /events/items · Theme: RecordListPage Allowed Roles: SUPER_ADMIN, DISTRIBUTOR, DISTRIBUTOR_STAFF (NOT GENERAL AGENT)

Code events and item events log. Filterable by item and by distributor.

Support — CRUD

REST-backed (not GraphQL). Allowed roles: SUPER_ADMIN, DISTRIBUTOR, DISTRIBUTOR_STAFF, GENERAL AGENT, CUSTOMER.

Page Key Route Theme
supportTickets /support/tickets RecordListPage
supportTicketsNew /support/tickets/new RecordFormPage

The new-ticket form pulls product and subscription context from REST.


Intent Notes

On CRUD vs Metric page families

This site combines both families in a single app shell. The sidebar shell and all entity management pages (staff, customers, accounts, fleets, items, pay plans, messaging, support) are crud family. The fleet health dashboard, device monitoring, and item events log are metric family. Both families obey the same governing rule from docs/governance/site-intent-scaffold-responsibilities.md: metadata controls structure, headless content and DTOs carry data.

On the existing implementation

webapp-asset-admin-distributor-v2 is the existing implementation from which this intent was derived. It uses the Mosaic Next.js template as its UI base, consistent with the CRUD-Sites policy in docs/governance/style-policy.md. The intent declared here is the canonical description of what the app does. Future scaffold output for dirac-uxi-crud should consume this intent.

On role-based visibility

Role gates are part of the intent, not just a runtime concern. The intent uses positive allowedRoles whitelists on both navigation items and pages. This matches the existing app's canViewMenu(menuId) permission model exactly, including:

  • Dashboards is hidden from GENERAL AGENT (they have no fleet-health view)
  • Distributor Staff is visible only to DISTRIBUTOR (the root account)
  • Agents is visible only to DISTRIBUTOR_STAFF (staff manage agents)
  • Events is hidden from GENERAL AGENT and CUSTOMER
  • Support is the only surface visible to CUSTOMER

Scaffold must propagate allowedRoles to both the sidebar render and the route guard layer.

On validation

The intent is validated against docs/contracts/crud-intent.schema.json via scripts/validate-crud-intent.js. The validator checks JSON Schema conformance and verifies that every allowedRoles entry is declared in auth.roles.


Change Log

v1.1.0 — 2026-04-26

  • Switched to positive allowedRoles whitelist model to match the runtime canViewMenu permission model
  • Corrected role names to match JWT exactly: GENERAL AGENT (with space), and added SUPER_ADMIN and CUSTOMER
  • Added menuId to nav items so scaffold preserves the runtime permission keys
  • Added missing routes: /signup/[...roleToken], /auth/passwordreset/[token], /accounts/asset-accounts/payments/[id]
  • Added explicit route field on every page
  • Removed nonexistent fleetDetail page

v1.0.0 — 2026-04-26

  • Initial intent document derived from webapp-asset-admin-distributor-v2
  • First documented site in the CRUD-Sites family
  • First surface to declare Metric-family pages within a CRUD app shell