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.
Navigation — Sidebar¶
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:
- Assets —
FleetHealthDashboard, GraphQLgetFleetHealthSummarywith pagination. SUPER_ADMIN falls back to viewport-based device loading to avoid gateway overload. - Device Monitoring —
DeviceMonitoringDashboard, Dash API, map enabled, viewport-based loading via/devices/by-viewport. - Custom Dashboards —
CustomDashboardBuilder, configuration persisted tolocalStorageunderdashboardConfig.
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 AGENTandCUSTOMER - 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
allowedRoleswhitelist model to match the runtimecanViewMenupermission model - Corrected role names to match JWT exactly:
GENERAL AGENT(with space), and addedSUPER_ADMINandCUSTOMER - Added
menuIdto nav items so scaffold preserves the runtime permission keys - Added missing routes:
/signup/[...roleToken],/auth/passwordreset/[token],/accounts/asset-accounts/payments/[id] - Added explicit
routefield on every page - Removed nonexistent
fleetDetailpage
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