Admin Cockpit · Surface walkthrough

Governance · Unified inbox

A per-surface walkthrough of the Admin Cockpit admin surface: layout, states, interactions, data, and cross-references.

drafted
8sections4 minread

On this page

Context. surface admin · domain governance · route /inbox · auth signed-in (admin) · source apps/oshun/admin/src/app/inbox/page.tsx

Last walked.

Purpose#

Folds the six per-workspace queues (review, moderation, support, privacy, incident, model) into a single triage surface backed by the BFF inbox composer. operatorPromise: "Inbox lets a reviewer clear cross-workspace urgency without context-switching between disparate cockpits."

Entry points#

  • Sidebar item "Inbox" (AdminSidebar — governance group)
  • Dashboard urgency / SLA tile → inbox (from OSHUN_ADMIN_WORKSPACE_RELATIONSHIPS dashboard → inbox entry)
  • Deep link /inbox#filters=…&detail=<itemId>useAdminQueueState hydrates filter / sort / detail state from the URL hash so a copy-pasted URL reproduces the same triage view (see V1-AWEB-094 comment in UnifiedInboxPanel.tsx)

Layout regions#

Inside AdminShell:

  • <WorkspaceEntryPoint workspaceId="inbox" accessible detail> — always rendered first; surfaces the "Access not granted" / "Workspace data unavailable" notice when applicable (shell/04-workspace-pattern.md)
  • <UnifiedInboxPanel> — rendered only when detail.accessible AND snapshot (from extractInboxSnapshot) is non-null. Sections inside the panel:
    • Header band: h2 "Unified inbox"; subtitle "Cross-workspace triage across review, moderation, support, privacy, incident, and model queues."; right-aligned "visible of total items shown"
    • Metrics row: four cells — Total open / Overdue / Due soon / Unassigned (from metrics)
    • Query bar: <AdminQueryFilterInput> — typed workspace:review priority:critical sla:overdue filter input (V1-AWEB-096)
    • Filters row: workspace checkboxes (6), priority checkboxes (5), SLA checkboxes (5), Assignee select (All / Assigned to me / Unassigned), free-text Search input, Sort select (4 options)
    • Bulk action toolbar: appears only when ≥1 row selected; target-operator input + Bulk acknowledge / Bulk assign / Clear buttons + live bulkSubmit status region
    • List + drawer: ul[data-testid="unified-inbox-list-drawer"] with one <li> per visible item; right-side AdminInlineDrawer when queue.state.detailId is set

States#

  • Anonymous → middleware redirects to /unauthorized?reason=missing-session&returnTo=/inbox
  • Signed-in (admin) + scope ok + BFF returns inbox detail with items → panel renders, both WorkspaceEntryPoint summary block and UnifiedInboxPanel mount (the entry-point renders above the panel; visually redundant but intentional per page code)
  • Signed-in (admin) + scope ok + BFF returns workspace-unavailableWorkspaceEntryPoint shows "Workspace data unavailable"; UnifiedInboxPanel does NOT render (guarded by detail.accessible && snapshot)
  • Signed-in (admin) + missing scope → WorkspaceEntryPoint "Access not granted"; panel hidden
  • Filters applied but no matches → p[data-testid="unified-inbox-empty"] "No items match the current filters."
  • Bulk submit submitting / success / errorspan[data-testid="unified-inbox-bulk-status"] with role="status" and aria-live="polite"
  • Bulk-assign over MAX_INBOX_BULK_ACTION_BATCH_SIZE items → Bulk acknowledge / Bulk assign disabled
  • Bulk-assign with mixed eligibility (assignEligibility.denied > 0) → button title surfaces the eligible / denied counts
  • No current operator id → "Assigned to me" option disabled in Assignee select

Interactions#

  • AdminQueryFilterInput typed bar (input)
    • Function: parses key:value tokens (workspace, priority, sla, assignee) and free-text into a structured filter via handleParsedQuery; empty input is a no-op
    • Replaces queue.state.filters + queue.state.query through queue.replace
  • Workspace filter checkboxes (×6: review / moderation / support / privacy / incident / model) — toggle pushes/removes an { key: 'workspace', op: 'eq', value } filter
  • Priority filter checkboxes (×5: critical / high / medium / low / unknown)
  • SLA filter checkboxes (×5: overdue / due_soon / on_track / no_sla / paused)
  • Assignee select — values all / me / unassigned; me disabled when currentOperatorId === null
  • Search input<input type="search">; updates queue.state.query
  • Sort select — 4 options from ADMIN_INBOX_SORTS: sla_then_priority (default), priority_then_sla, last_updated_desc, workspace_then_priority
  • Row checkbox (per row) — aria-label="Select <title>"; toggles selection set
  • Row title link<Link href={item.originUrl}>; jumps to the source workspace's detail surface
  • Row "Inspect" buttonaria-label="Inspect <title>"; opens AdminInlineDrawer by setting queue.state.detailId
  • Bulk-assign target input — free-text reviewer id (e.g. reviewer-sec-01); required for Bulk assign
  • Bulk acknowledge (button) — disabled while submitting or over batch max; POST /api/admin/inbox/bulk-action with action: 'acknowledge'
  • Bulk assign (button) — disabled when no eligible items; submits action: 'assign' with targetOperatorId
  • Clear (button) — resets selectedIds and bulkSubmit state

Data & contracts#

  • Reads: loadWorkspaceDetail('inbox', session)/v1/admin/workspaces/inbox (BFF inbox composer getInboxWorkspace); snapshot extracted via extractInboxSnapshot yields items: AdminInboxItem[] and metrics: AdminInboxMetrics (contracts in @oshun/contracts)
  • Writes: POST /api/admin/inbox/bulk-action with { action: 'acknowledge'|'assign', itemIds, targetOperatorId? }; response { bulkActionRecord: AdminInboxBulkActionRecord }
  • Realtime: None. Server-rendered items array is static per navigation; no SSE/WS in this panel
  • Auth/role check: middleware (any admin session) + page (canEnterAdminWorkspace(scopes, 'inbox') → required scopes ['admin:*', 'admin:studio'])

Cross-references#

  • Shell: shell/01-app-shell.md, shell/04-workspace-pattern.md
  • Workspace definition: libs/oshun/navigation/src/admin-ia.ts (inboxbackendStatus: 'bff-backed', bffWorkspaceId: 'inbox', kind: 'unified-queue')
  • Sibling routes (handoff destinations from inbox per relationships): review.md, ../safety/trust-safety.md, ../operations/support.md, ../operations/privacy.md, ../safety/incidents.md
  • Component sources: apps/oshun/admin/src/components/UnifiedInboxPanel.tsx, apps/oshun/admin/src/components/AdminQueryFilterInput.tsx, apps/oshun/admin/src/lib/use-admin-queue-state.ts, apps/oshun/admin/src/lib/inbox-detail.ts
  • V1 PWA equivalent (consumer-shell operator surface): WALKTHROUGH/operator/operator-admin.md for cross-product context

Open questions / known gaps#

  • Whether the page intentionally renders WorkspaceEntryPoint AND UnifiedInboxPanel together in the happy path, or whether the entry-point block is meant to be hidden once the panel mounts
  • Document the AdminInlineDrawer content rendered when detailId is set (it is referenced but not walked above line 720; nested interactions live in that component)
  • Confirm MAX_INBOX_BULK_ACTION_BATCH_SIZE value and whether it's exposed on the wire (it is enforced client-side; the BFF also caps?)