Admin Dashboard Site Map
Hierarchical map of every page in the internal admin dashboard (admin_dashboard/ SPA). Companion to the consumer site-map.md, the marketing marketing-site-map.md, and the audience-facing admin-dashboard.md guide.
Scope: admin dashboard only. The consumer app and the marketing landing are mapped separately.
Source of truth: admin_dashboard/src/router.ts. Regenerate this doc whenever a route is added, removed, or its requiresRole meta changes. Render PNG export with cd docs_site && npm run docs:diagrams.
Legend
flowchart LR super(["super_admin only"]):::super admin(["admin"]):::admin mod(["moderator"]):::mod support(["support"]):::support marketing(["marketing"]):::marketing open(["any signed-in admin"]):::open gateRole guard:::gate pub(["Public route"]):::public classDef super fill:#fee2e2,stroke:#b91c1c,color:#7f1d1d classDef admin fill:#fef3c7,stroke:#d97706,color:#78350f classDef mod fill:#dbeafe,stroke:#2563eb,color:#1e3a8a classDef support fill:#dcfce7,stroke:#16a34a,color:#14532d classDef marketing fill:#fed7aa,stroke:#c2410c,color:#7c2d12 classDef open fill:#f3e8ff,stroke:#7c3aed,color:#4c1d95 classDef gate fill:#fce7f3,stroke:#be185d,color:#831843 classDef public fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
Color encodes the most restrictive role required to load the route. A view labeled admin is reachable by both super_admin and admin; a view labeled super_admin is reachable only by super_admin. See the route table below for the full requiresRole array on each entry.
super_admin— full access, only role that can loadsystem/demo-data.admin— operational admin: AI Workforce, analytics, monitoring, moderation, users.moderator— moderation queue only.support— user lookup, feedback triage, GDPR queue.marketing— AI Workforce only (Ops Board, Employee Detail, Run Detail, Agents); cannot reach analytics, moderation, users, or any other admin surface.- Any signed-in admin — Dashboard and
system/self-healthenforcerequiresAuthonly; norequiresRoleis declared, so any user whose Clerk session resolves to aMerecord may load them (in practice the layout itself is gated by Clerk on/). - Public —
/sign-inis the only route outsideAdminLayout.
Site map
flowchart TD
Entry["app.objectuve.com (consumer)"]:::ext -->|"/admin bridge"| SignIn
subgraph Public["Public surface"]
direction TB
SignIn(["/sign-in"]):::public
end
subgraph Gates["Auth + role guards"]
direction TB
ClerkClerk session check (App.vue watch):::gate
RoleGuardrouter.beforeEach → ME_QUERY.adminRoles:::gate
end
subgraph Layout["AdminLayout (sidebar + header)"]
direction TB
subgraph Core["Core (any admin)"]
direction TB
Dashboard["/ (Dashboard)"]:::open
SelfHealth["/system/self-health"]:::open
end
subgraph People["People & content"]
direction TB
Users["/users"]:::support
Moderation["/moderation"]:::mod
ContentReports["/content-reports"]:::mod
CommunityCuration["/communities/curation"]:::admin
SeasonalEvents["/communities/seasonal-events"]:::admin
Feedback["/feedback"]:::support
GdprQueue["/gdpr/queue"]:::support
end
subgraph Insights["Insights"]
direction TB
Analytics["/analytics"]:::admin
OnboardingFunnel["/funnel/onboarding"]:::admin
Monitoring["/monitoring"]:::admin
BadgeStats["/badges"]:::admin
Plans["/plans"]:::admin
AuditLog["/audit-log"]:::admin
end
subgraph Workforce["AI Workforce"]
direction TB
AIList["/ai-workforce (Ops Board — landing)"]:::marketing
EmployeeDetail["/ai-workforce/:id"]:::marketing
RunDetail["/ai-workforce/:employeeId/runs/:runId"]:::marketing
Agents["/agents"]:::marketing
end
subgraph System["System"]
direction TB
DemoData["/system/demo-data"]:::super
end
Unauthorized["/unauthorized"]:::open
end
SignIn --> Clerk
Clerk -- "no session" --> SignIn
Clerk -- "session" --> RoleGuard
RoleGuard -- "role match" --> Dashboard
RoleGuard -- "role mismatch" --> Unauthorized
RoleGuard -- "ME_QUERY error" --> SignIn
Dashboard --> Users
Dashboard --> Moderation
Dashboard --> ContentReports
Dashboard --> CommunityCuration
Dashboard --> SeasonalEvents
Dashboard --> Feedback
Dashboard --> Analytics
Dashboard --> OnboardingFunnel
Dashboard --> Monitoring
Dashboard --> BadgeStats
Dashboard --> Plans
Dashboard --> AuditLog
Dashboard --> AIList
Dashboard --> Agents
Dashboard --> GdprQueue
Dashboard --> SelfHealth
Dashboard --> DemoData
AIList --> EmployeeDetail
EmployeeDetail --> RunDetail
classDef super fill:#fee2e2,stroke:#b91c1c,color:#7f1d1d
classDef admin fill:#fef3c7,stroke:#d97706,color:#78350f
classDef mod fill:#dbeafe,stroke:#2563eb,color:#1e3a8a
classDef support fill:#dcfce7,stroke:#16a34a,color:#14532d
classDef marketing fill:#fed7aa,stroke:#c2410c,color:#7c2d12
classDef open fill:#f3e8ff,stroke:#7c3aed,color:#4c1d95
classDef gate fill:#fce7f3,stroke:#be185d,color:#831843
classDef public fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
classDef ext fill:#e5e7eb,stroke:#6b7280,color:#1f2937

Route table
Authoritative list. Diff against grep -E "path:" admin_dashboard/src/router.ts after any router change.
Component-backed routes
| Path | Name | Component | requiresRole | Breadcrumb trail |
|---|---|---|---|---|
/ | dashboard | Dashboard.vue | (auth only) | Dashboard |
/users | users | UsersView.vue | super_admin, admin, support | Admin › Users |
/moderation | moderation | ModerationView.vue | super_admin, admin, moderator | Admin › Moderation Queue |
/analytics | analytics | AnalyticsView.vue | super_admin, admin | Admin › Analytics |
/funnel/onboarding | OnboardingFunnel | OnboardingFunnelView.vue | super_admin, admin | Admin › Onboarding Funnel |
/monitoring | monitoring | MonitoringView.vue | super_admin, admin | Admin › Monitoring |
/feedback | feedback | FeedbackView.vue | super_admin, admin, support | Admin › Feedback |
/ai-workforce | AIWorkforce | OpsBoardView.vue | super_admin, admin, marketing | Admin › AI Workforce |
/ai-workforce/:id | EmployeeDetail | EmployeeDetailView.vue | super_admin, admin, marketing | Admin › AI Workforce › Employee |
/ai-workforce/:employeeId/runs/:runId | RunDetail | RunDetailView.vue | super_admin, admin, marketing | Admin › AI Workforce › Run |
/agents | Agents | AIWorkforceView.vue | super_admin, admin, marketing | Admin › AI Workforce › Agents |
/audit-log | AuditLog | AuditLogView.vue | super_admin, admin | Admin › Audit Log |
/badges | BadgeStats | BadgeStatsView.vue | super_admin, admin | Admin › Badge Stats |
/teams/opt-outs | TeamsOptOut | TeamsOptOutView.vue | super_admin, admin | Admin › Team Leaderboard Opt-Outs |
/teams/monitoring | TeamsMonitoring | TeamsMonitoringView.vue | super_admin, admin | Admin › Teams |
/content-reports | ContentReports | ContentReportsView.vue | super_admin, admin, moderator | Admin › Content Reports |
/communities/curation | CommunityCuration | CommunityCurationView.vue | super_admin, admin | Admin › Community Curation |
/communities/seasonal-events | SeasonalEvents | SeasonalEventsView.vue | super_admin, admin | Admin › Seasonal Events |
/plans | Plans | PlansView.vue | super_admin, admin | Admin › Plans |
/gdpr/queue | GdprQueue | GdprQueueView.vue | super_admin, support | Admin › GDPR Queue |
/system/self-health | self-health | SelfHealthView.vue | (auth only) | Admin › System › Self-Health |
/system/demo-data | demo-data | DemoDataView.vue | super_admin | Admin › System › Demo Data |
/unauthorized | unauthorized | UnauthorizedView.vue | (auth only) | — |
/sign-in | sign-in | SignIn.vue | public | — |
Redirects (no component)
| Path | Redirects to | Why |
|---|---|---|
/ops-board | /ai-workforce | Pre-cutover board URL (OBJ-1562). |
/review-queue | /ai-workforce | Retired standalone Review Queue (OBJ-1562) — its artifact-review flow now lives in the board's Focus Detail overlay. |
Total: 26 routes — 1 public sign-in, 24 nested under AdminLayout (2 of them redirect-only), plus the layout's '' child (Dashboard).
CI-enforced. Drift between this table and
router.tsfails the Route Drift workflow. Run locally withcd docs_site && npm run docs:check-routes.
Role × view matrix
A quick read of who can see what. ✓ = role can load the route. Routes that declare no requiresRole (Dashboard, Self-Health, Unauthorized) are reachable by any signed-in user whose Me record resolves.
| Route | super_admin | admin | moderator | support | marketing |
|---|---|---|---|---|---|
/ (Dashboard) | ✓ | ✓ | ✓ | ✓ | ✓ |
/users | ✓ | ✓ | ✓ | ||
/moderation | ✓ | ✓ | ✓ | ||
/analytics | ✓ | ✓ | |||
/funnel/onboarding | ✓ | ✓ | |||
/monitoring | ✓ | ✓ | |||
/feedback | ✓ | ✓ | ✓ | ||
/ai-workforce (+ children, landing) | ✓ | ✓ | ✓ | ||
/ai-workforce/:id | ✓ | ✓ | ✓ | ||
/ai-workforce/:employeeId/runs/:runId | ✓ | ✓ | ✓ | ||
/agents | ✓ | ✓ | ✓ | ||
/audit-log | ✓ | ✓ | |||
/badges | ✓ | ✓ | |||
/teams/opt-outs | ✓ | ✓ | |||
/teams/monitoring | ✓ | ✓ | |||
/content-reports | ✓ | ✓ | ✓ | ||
/communities/curation | ✓ | ✓ | |||
/communities/seasonal-events | ✓ | ✓ | |||
/plans | ✓ | ✓ | |||
/gdpr/queue | ✓ | ✓ | |||
/system/self-health | ✓ | ✓ | ✓ | ✓ | ✓ |
/system/demo-data | ✓ |
Guard mechanics
The role check is a single router.beforeEach in router.ts:171:
- If
to.meta.requiresRoleis absent or empty, allow — Dashboard, Self-Health, Unauthorized, and Sign-In fall into this bucket. - Otherwise run
ME_QUERYagainst Apollo withfetchPolicy: 'cache-first'. Repeat navigations within a session are synchronous (cache hit); the first navigation pays one round-trip. - Read
data?.me?.adminRoles(array of strings). If any element ofrequiresRoleis present inadminRoles, allow. - If no role matches, redirect to
/unauthorized?attempted=<fullPath>. Theattemptedquery is whatUnauthorizedViewrenders in its "you tried to reach X" message. - If
ME_QUERYthrows (expired Clerk session, network blip), redirect to/sign-in?redirect=<attempted path>— the user re-authenticates, then lands back where they were headed instead of at the dashboard (OBJ-2534).
The guard runs after App.vue's Clerk watcher has confirmed a session, so a signed-out user never reaches the role check — they're bounced to /sign-in by the auth layer first.
Notes
- Dashboard is the de-facto home — every route is reachable from the sidebar in
AdminLayout, but no<router-link>enforces a deep-link order. The Mermaid diagram shows Dashboard as the root for orientation only. - AI Workforce employee + run details are sibling routes, not nested under the board. The breadcrumb trail (
Admin › AI Workforce › Employee) reconstructs the hierarchy in the UI even though the router treats them as flat siblings. /ai-workforceis the Live Ops Board (OBJ-1562 route cutover) — the v4.8 unified work-item view overAiEmployee → AiRun → AiArtifact(OpsBoardView.vue) is now the AI Workforce landing. The former agent-grid view (AIWorkforceView.vue— config, filters, trigger/pause) moved to the secondary/agentsroute rather than being folded into the board./ops-boardand/review-queueare retired, redirect-only aliases; the standalone Review Queue's approve/reject flow now lives in the board's Focus Detail overlay.marketingis scoped to AI Workforce only (quick task 260904-gj7) — a single-purpose role for marketing-crew reviewers who approve/reject artifacts and monitor employees, without the broaderadminrole's access to users, moderation, analytics, or other admin surfaces. The router's post-login redirect sends amarketing-only session straight to/ai-workforcerather than/(Dashboard), since Dashboard's own stat cards aren't scoped for a marketing-only viewer./system/self-healthdeliberately has norequiresRole— it's the on-call diagnostic page, intentionally reachable by any admin who can log in. Sensitive operational data lives on/monitoring(admin+) and/system/demo-data(super_admin only)./adminin the consumer app is the bridge — see the consumer site map andAdminRedirect.vue. It checksme.adminRolesand either redirects toadmin.objectuve.com(production) orlocalhost:4002(dev), or sends non-admins to/unauthorizedon the consumer side.- No deep-link auth bypass — even direct hits to
/ai-workforce/abc/runs/xyzpass through the samebeforeEachguard before the view loads.
For the consumer app sitemap and user flows, see site-map.md and user-flows.md.
Last updated: 2026-09-04