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_RELATIONSHIPSdashboard → inboxentry) - Deep link
/inbox#filters=…&detail=<itemId>—useAdminQueueStatehydrates filter / sort / detail state from the URL hash so a copy-pasted URL reproduces the same triage view (see V1-AWEB-094 comment inUnifiedInboxPanel.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 whendetail.accessibleANDsnapshot(fromextractInboxSnapshot) 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 "
visibleoftotalitems shown" - Metrics row: four cells — Total open / Overdue / Due soon / Unassigned
(from
metrics) - Query bar:
<AdminQueryFilterInput>— typedworkspace:review priority:critical sla:overduefilter 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
bulkSubmitstatus region - List + drawer:
ul[data-testid="unified-inbox-list-drawer"]with one<li>per visible item; right-sideAdminInlineDrawerwhenqueue.state.detailIdis set
- Header band: h2 "Unified inbox"; subtitle "Cross-workspace triage across
review, moderation, support, privacy, incident, and model queues.";
right-aligned "
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
WorkspaceEntryPointsummary block andUnifiedInboxPanelmount (the entry-point renders above the panel; visually redundant but intentional per page code) - Signed-in (admin) + scope ok + BFF returns
workspace-unavailable→WorkspaceEntryPointshows "Workspace data unavailable";UnifiedInboxPaneldoes NOT render (guarded bydetail.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/error→span[data-testid="unified-inbox-bulk-status"]withrole="status"andaria-live="polite" - Bulk-assign over
MAX_INBOX_BULK_ACTION_BATCH_SIZEitems → 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:valuetokens (workspace,priority,sla,assignee) and free-text into a structured filter viahandleParsedQuery; empty input is a no-op - Replaces
queue.state.filters+queue.state.querythroughqueue.replace
- Function: parses
- 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;medisabled whencurrentOperatorId === null - Search input —
<input type="search">; updatesqueue.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" button —
aria-label="Inspect <title>"; opensAdminInlineDrawerby settingqueue.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-actionwithaction: 'acknowledge' - Bulk assign (button) — disabled when no eligible items; submits
action: 'assign'withtargetOperatorId - Clear (button) — resets
selectedIdsand bulkSubmit state
Data & contracts#
- Reads:
loadWorkspaceDetail('inbox', session)→/v1/admin/workspaces/inbox(BFF inbox composergetInboxWorkspace); snapshot extracted viaextractInboxSnapshotyieldsitems: AdminInboxItem[]andmetrics: AdminInboxMetrics(contracts in@oshun/contracts) - Writes:
POST /api/admin/inbox/bulk-actionwith{ 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(inbox—backendStatus: '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.mdfor cross-product context
Open questions / known gaps#
- Whether the page intentionally renders
WorkspaceEntryPointANDUnifiedInboxPaneltogether in the happy path, or whether the entry-point block is meant to be hidden once the panel mounts - Document the
AdminInlineDrawercontent rendered whendetailIdis set (it is referenced but not walked above line 720; nested interactions live in that component) - Confirm
MAX_INBOX_BULK_ACTION_BATCH_SIZEvalue and whether it's exposed on the wire (it is enforced client-side; the BFF also caps?)