Unified inbox (work items)
Contributor and operator reference. For the full product vision, phased rollout, and edge-case decisions, read The inbox is the product.
What it is
Section titled βWhat it isβThe unified inbox is a work queue backed by the workItems table. Email- and upload-sourced orders appear as rows; users review in full-page flows, with optional team dashboard metrics, snooze, and keyboard-driven navigation. When the legacy path is off, the app reads work items instead of scanning emailEvents metadata alone.
Feature flags
Section titled βFeature flagsβ| Flag | Role |
|---|---|
unified_inbox_v2 |
Org-scoped Flagsmith flag toggling work-item UI, redirects, and APIs that assume work items. |
email_enabled |
Shows inbox / email-based entry points (used together in staging setups). |
inline_inbox_label_rules_v1 |
Org-scoped. Lets the sweep apply customer auto-archive rules (inbox_routing_rules). Off means rules are stored but never fire. |
inbox_archive_erp_edi_duplicates_v1 |
Org-scoped, default off. Lets the same sweep archive items the ERP dedupe lookup already tagged with an EDI- job number. Off leaves the tag advisory. |
inbox_conversation_view_v1 |
Org-scoped, default off. Replaces the cockpitβs Email and Thread tabs with one Conversation tab: the threadβs messages, archive and trash activity, and internal notes with @mentions. Off makes the conversation and notes routes return 404. |
inbox_sla_engine_v1 |
Org-scoped, default off. SLA engine: deadlines computed for new items, open-before-terminal then slaDueAt sort, and the rowβs SLA pill with its priority-override card. Off hides the pill and 404s the SLA policy and priority routes. |
Script to enable the first two in a Flagsmith environment: infrastructure/flagsmith/scripts/enable_unified_inbox_for_env.py. Flag definitions ship in infrastructure/flagsmith/configs/flags.json. Local fallback defaults live in apps/webapp/src/middleware/feature-flags.ts.
Data layer
Section titled βData layerβ- Schema:
packages/db/src/schema/work-items.ts - Internal notes:
packages/db/src/schema/inbox-notes.ts. A note belongs to the work item it was written on and, when that item came from threaded mail, to its email thread, so it shows on every item in the thread. - Dual-write: Work items are created in the same transactional paths as inbound email (
/api/webhook/inbound-email) and PDF upload handlers so legacy and v2 stay consistent during rollout. - State & Lifecycle Model (RFC Option A.5): Under RFC β
work_itemsState Model, archiving is a lifecycle-only timestamp operation (archived_at), withstatus = 'archived'retained only for legacy rows under thework_items_archived_status_consistentCHECK constraint (status != 'archived' OR archived_at IS NOT NULL). User-facinguxStateis derived server-side viauxStateSql(apps/webapp/src/lib/inbox/work-item-ux-state-sql.tsandapps/webapp/src/lib/inbox/work-item-inbox-query.ts).
Webapp (Astro + React) β Three-Pane Cockpit Architecture
Section titled βWebapp (Astro + React) β Three-Pane Cockpit ArchitectureβBoth operator and supervisor inbox surfaces render inside the dark cockpit frame (ShellFrame.astro + AppRail.astro / RailNav.tsx):
- Operator Three-Pane Cockpit (
/inboxβapps/webapp/src/pages/inbox.astro):- Wrapped in
CockpitShell.astro(<ShellFrame scroll="hidden">+ AstroClientRoutersoft transitions) and mounted viaInboxCockpit.tsx(apps/webapp/src/components/inbox/InboxCockpit.tsx):- Pane 1 β Left Rail (
56px):AppRail.astro/RailNav.tsx(navigation, notifications, help, org/account menu). - Pane 2 β Queue List (
CockpitRow.tsx): Flat virtualized/paginated work-item list with queue tabs (Mine,Available,Branch), lifecycle selector (active | archived | deleted), status filters (needs_review,needs_fix,processing,ready,failed), search, bulk actions, and Superhuman-style keyboard navigation (j/k,e,Enter,/). - Pane 3 β Detail & Inline Preview (
CockpitDetail.tsx+CockpitItemPreview.tsx): Inline PDF/spreadsheet/email preview, PO/sender metadata,AuroraRoutingCard, and state-awareSubmitButton/ βFull reviewβ action (/orders/pdf/[documentId]/review).
- Pane 1 β Left Rail (
- Wrapped in
- Supervisor Team Surface (
/teamβapps/webapp/src/pages/team.astro):- Gated by
inbox.view.team(hasElevatedInboxAccess); rendersSupervisorInboxRoot.tsx(ConservativeInboxtable +SupervisorKanbanboard +SupervisorDetailDrawer).
- Gated by
- Queries / helpers:
apps/webapp/src/lib/inbox/* - Review URLs:
apps/webapp/src/lib/inbox/work-item-review-url.ts,inbox-return-to.ts - Representative APIs:
apps/webapp/src/pages/api/work-items/*(dashboard, bulk actions, snooze, check-updates, test order, admin backfill trigger, conversation, notes) - Single-item visibility:
apps/webapp/src/lib/inbox/visible-work-item.ts, the check the detail, thread, conversation, and notes routes share. - Temporal client helpers:
apps/webapp/src/lib/temporal.ts(startWorkItemBackfillWorkflow, PDF extraction unchanged onpdf-extractionqueue)
Temporal (TypeScript worker)
Section titled βTemporal (TypeScript worker)βPackage: apps/ts-temporal-worker
Task queue: erp-unlocked-ts
| Workflow | Purpose |
|---|---|
WorkItemBackfillWorkflow |
Migrate existing email events into workItems (idempotent; fixed workflow id work-item-backfill). |
WorkItemUnsnoozeWorkflow |
Periodic unsnooze of rows past snoozedUntil (intended as a schedule; see workflow file for CLI hints). |
Requires TEMPORAL_ADDRESS (and related TLS vars) where the webapp starts backfill or PDF workflows.
Related
Section titled βRelatedβ- Deferred product work:
debt/backlog/projects/unified-inbox/TODOS.md - Email pipeline (high level): The inbox is the product (diagrams and dual-write notes)
- User operations guide: Inbox RBAC and SLA (RBAC capabilities, SLA policy controls, supervisor/admin dashboard actions)
- Auto-archive rules and the ERP duplicate sweep:
debt/projects/inbox-label-taxonomy/plan.md(why rules are keyed on customer name, theexcludeSendersnarrowing, and theEDI-/J-split)