h.work Platform — User Operations Manual
Platform: h.work (Humanity Protocol internal AI + Expert managed-service platform)
Last updated: 2026-06-26 (additions: AM cross-client rollups — Experts / SLA / Billing — §6.7, #1300; Gmail API + DWD email channel shipped #1722; Tavus integration DB/security/API series #2052/#2054/#2055; clarified/ops/personas/*route retention) Source references:frontend/src/contexts/AuthContext.tsx, allpage.tsxandlayout.tsxunder/client/*,/workspace/*,/ops/*,e2e/specs,CLAUDE.md, ADR-007, ADR-018, ADR-024 through ADR-028.
What changed this quarter
If you're returning to this manual after a few weeks away, these are the operator-visible shifts you need to internalize. Each links to the section that covers it.
| Area | What changed | Where to read |
|---|---|---|
| RAG runtime | RAGflow retired; Haystack 2.x + Hayhooks + pgvector + OpenRouter is the new stack. Per-env cost ~$2k → $440. No RAGflow operations remain. | §9: ADR-024, ADR-025, ADR-026 |
| Billing rail | Orb retired; Lago self-hosted is canonical. Dev on Railway; staging + prod on AWS. /ops/billing is the platform-wide view (AM + SuperAdmin since PR #1155). | §7.3 /ops/billing |
| AM cross-client rollups | AMs get portfolio-wide rollups across their assigned clients: Experts (/ops/experts), SLA breaches (/ops/sla), Billing (/ops/billing). Per-AM org scoping via AmOrgScopeGuard; SuperAdmin sees all orgs. Shipped #1300 (closes #1244). | §6.7 + docs/features/am-rollups.md |
| Agent runtime | railway_per_org runtime kind retired; supported kinds are shared_railway (default) and ecs_per_org (premium). ECS prod cutover #701 closed 2026-06-15 — staging+prod are canonically AWS ECS Fargate. | §9: ADR-028, ADR-038 |
| Schema migrations | TypeORM-only. Raw SQL under api/src/database/migrations/ is CI-blocked. Set RUN_MIGRATIONS_ON_BOOT=true for deploy-time migrations. | §9: ADR-027 |
| Expert workspace productivity | Customer history timeline and KB search panel landed inside /workspace/queue (2026-06-03). Response templates were trialled in the same cluster and removed on 2026-06-05 — the agent draft is the primary surface; see §5.3 Productivity primitives. | §5.3 Productivity primitives |
| Expert application + Tavus interviews | /ops/expert-applications gained a Tavus video-interview track: send-to-interview, retry-invite, hard-delete, post-interview Approve. Recordings mirrored to R2 with 7-year retention. | §7.3 /ops/expert-applications |
| Specialist email | Gmail API inbound polling + DWD-impersonated outbound shipped 2026-06-05 (PR #1722). ONE Google Workspace service account with domain-wide delegation impersonates each Specialist's mailbox (bob@h.work); no per-Specialist OAuth tokens. Cloudflare Worker stays as fallback during a 2-week prod soak (#1440/#1441 still open). Resend is reserved for invites/onboarding/transactional. | docs/features/channels.md |
| Tavus integration | Tavus DB schema (tavus_personas + video_calls) landed via #2052; security guardrails via #2054; on-demand video call API via #2055. The Persona Manager API module was renamed to Tavus integration (PR #1345, 2026-06-02); the frontend /ops/personas/* routes were deliberately retained (rename PRs closed without merge). | §7.3 /ops/personas/* + docs/decisions/tavus/ |
If a procedure in this manual contradicts the changes above, the table above wins — and please file a doc-correction issue with type:feature, area:backend, role:pm so the procedure gets updated.
Table of Contents
- Platform Overview & Terminology
- Authentication & JWT Model
- Role:
org_admin— Client Organisation Administrator - Role:
org_member— Client Organisation Member - Role:
expert— Humanity Protocol Expert - Role:
account_manager— Account Manager (AM) - Role:
superadmin— SuperAdmin - Cross-Role Reference: Route Ownership
- ADR Cross-References
1. Platform Overview & Terminology
h.work is not a helpdesk. It is a managed AI + Expert service layer used internally by Humanity Protocol (HP) staff to deliver responses to client companies.
| Concept | Correct term | Never say |
|---|---|---|
| AI persona assigned to a client | Specialist | agent, bot, assistant |
| HP human reviewer | Expert | specialist (for humans) |
| The company using the platform | client (UI) / org (code) | workspace, account, tenant |
| HP person managing clients | AM / Account Manager | account rep |
| Platform-wide administrator | SuperAdmin | admin (too ambiguous) |
Request flow summary:
- A client employee sends a message to their assigned Specialist persona.
- The AI agent drafts a reply (confidence + risk scored).
- If
confidence < thresholdorrisk_level >= HIGH→ anExpertQueueItemis created. - An Expert reviews, edits, and sends the reply as the Specialist.
- Default threshold is
101— meaning all replies go to Expert review unless an AM explicitly lowers it.
2. Authentication & JWT Model
Login URL: /login
Token storage: localStorage key hw_token (JWT, persisted until explicit logout)
Session model: No client-side expiry. The server validates the token on every API call. Logout is always explicit.
Role detection (AuthContext.tsx → getRoleRedirect())
platformRole = JWT payload.platformRole ?? payload.role ?? orgMemberships[0].orgRole
platformRole | Post-login redirect |
|---|---|
superadmin | /ops/clients |
account_manager | /ops/clients |
expert | /workspace/queue |
org_admin, org_member, owner, admin, member, billing | /client/chat |
Multi-tab sync: A StorageEvent listener on hw_token keeps all open tabs in sync — logging in or out from one tab propagates immediately.
Logout: Disconnects the WebSocket, clears the token, and redirects to /login.
3. Role: org_admin — Client Organisation Administrator
3.1 Login + Redirect Target
- Login page:
/login - Post-login redirect:
/client/chat - JWT field:
orgMemberships[0].orgRole = "admin"(or"owner")
3.2 Route Table
| Route | Description | Accessible to org_admin? |
|---|---|---|
/client/chat | Main chat interface with Specialist | ✅ |
/client/chat?id=<convId> | Direct link to a specific conversation | ✅ |
/client/chat/:id | Server-side 307 redirect → /client/chat?id=:id | ✅ (redirect only) |
/client/approvals | Runtime approval & input requests from Specialist | ✅ |
/client/specialist | Specialist profile/info page | ✅ |
/client/settings/profile | Edit display name, avatar, email notification prefs | ✅ |
/client/settings/team | Manage team members and invites | ✅ |
/client/settings/channels | Connect/manage communication channels | ✅ (admin-only access) |
/client/settings/billing | View plan, usage, billing history | ✅ (admin/owner/billing) |
/client/settings/billing/upgrade | Upgrade plan flow | ✅ |
/client/settings/billing/upgrade/success | Upgrade success confirmation | ✅ |
/client/settings/whatsapp | WhatsApp-specific settings | ✅ |
/client/admin/knowledge-base | Upload & manage KB documents for the Specialist | ✅ |
/client/admin/channels/new | Add a new channel integration | ✅ |
/client/admin/channels/[id] | Manage a specific channel integration | ✅ |
/client/admin/integrations | Redirects → channels | ✅ |
/client/admin/integrations/new | Redirects → channels/new | ✅ |
/client/admin/integrations/[id] | Redirects → channels/[id] | ✅ |
/client/admin/team | Redirects → /client/settings/team | ✅ |
/client/admin/billing | Redirects → /client/settings/billing | ✅ |
/client/admin/analytics | Redirects → /client/admin/billing | ✅ |
/client/admin/tickets | Ticket view (legacy redirect path) | ✅ |
/client/specialists/[id]/onboarding | Specialist onboarding wizard | ✅ |
/client/specialists/[id]/meetings | Specialist meeting management | ✅ |
/client/specialists/[id]/meetings/[meetingId] | Specific meeting detail | ✅ |
/client/reconsent | Re-consent page (banner-triggered) | ✅ |
/client/page | Root /client page (redirect to /client/chat) | ✅ |
3.3 Per-Page Operations
/client/chat
- Displays: Full-width two-panel chat interface. Left: thread list with conversation subjects and timestamps. Right: selected conversation thread with message history.
- Actions:
- Start new conversation (send first message to Specialist)
- Type and send a message in the compose area
- Switch between existing conversations by clicking thread rows
- Navigate to
/client/approvalsvia page link
- Forms: Message compose text area + Send button
- Role gates: None within the chat itself — all authenticated org members see the same surface
/client/approvals
- Displays: List of runtime approval and input requests from the Specialist that require a client response.
- Actions:
- Review pending requests
- Submit required approval or input (nothing executes until the request is resolved)
- "Back to chat" button → navigates to
/client/chat
- Forms: Per-request approval/input submission forms
- Note: Nothing is sent or executed on your behalf until the required approval or input is submitted.
/client/admin/knowledge-base
- Displays: Document table with columns for filename, parse status (pending / parsed / failed), chunk count, upload date. Live WebSocket updates on parse status.
- Actions:
- Search bar (
KbSearchBar) — full-text search across uploaded KB documents - Upload area (
KbUploadArea) — drag-and-drop or file-picker upload (up to 50 docs per page, paginated) - Filter by parse status — All / Pending / Parsed / Failed
- Open document detail modal — click a row to open
KbDocumentDetailModal - Delete document — from within the detail modal
- Pagination —
</>controls (50 docs per page)
- Search bar (
- Forms: File upload form, search input
/client/settings/profile
- Displays: Two-column card layout: Profile card + Email Notifications card.
- Actions:
- Upload or change avatar photo (camera icon click →
AvatarUploadwidget) - Edit Display name text field
- Email field (read-only — cannot change email here)
- Save changes button — saves display name and avatar URL
- Email notification toggles (auto-save on toggle):
- New reply from Specialist
- Conversation resolved
- Team member added
- Invoice generated
- Upload or change avatar photo (camera icon click →
/client/settings/team
- Displays: Member table (Name + Email, Role badge, Last active, Actions column). Pending invites section below.
- Actions (org_admin / owner only):
- Invite member button → opens inline form with email + role selector (member / admin / billing)
- Change role dropdown per member (cannot demote if only 1 admin/owner total)
- Remove member (confirmation dialog) — cannot undo
- Revoke invite (confirmation dialog)
- Resend invite button per pending invite
- Transfer Ownership button → modal to select a new owner (current user becomes admin)
- Leave workspace button (for non-owner members)
- Forms: Invite form (email + role), Transfer Ownership modal
- Guards: Cannot demote the last admin or owner. Cannot remove yourself if owner.
/client/settings/channels
- Displays: Channel grid (Email, WhatsApp, Telegram, Slack, Microsoft Teams, WeChat). Each card shows:
- Channel icon and name
- Status badge: Connected / Available / Coming Soon
- Connected details (e.g., number of WhatsApp numbers linked, "Default — always on" for Email)
- Test result (if tested)
- Actions per card:
- Set up → expands inline explainer or navigates to setup flow
- Manage → navigates to
/client/admin/channels/[id] - Test → sends a test ping and shows pass/fail result
- Remove → confirmation dialog; stops messages on that channel (history preserved)
- WhatsApp Manage → expands
WhatsAppPairingPanelinline
- Email routing section (below channel grid):
- Add domains or specific email addresses to the routing whitelist (type → domain/email → Add)
- Remove existing whitelist entries (× button)
- Until a domain is added, only invited team member emails reach the Specialist
/client/settings/billing
- Displays: Current plan badge (free / trial / starter / pro / enterprise), trial countdown if applicable, usage bars (conversations used vs. limit, messages used vs. limit), billing history chart (bar chart, monthly), plan details.
- Actions:
- Upgrade button → navigates to
/client/settings/billing/upgrade - View billing history
- Upgrade button → navigates to
3.4 Navigation Structure
The client area uses two separate side-navigation contexts depending on which sub-area is active:
Settings layout sidebar (/client/settings/*):
- ← Back to Chat link
- Settings heading
- Section 1 (always visible): Profile · Team
- Section 2 (admin/owner/billing only): Channels · Billing
- Footer: Sign Out button + dark mode toggle
Admin layout sidebar (/client/admin/*):
- ← Chat back link
- Org name + "Admin" label
- Team (→
/client/admin/team) — redirects to Settings/Team - Channels (→
/client/admin/channels) - Knowledge Base (→
/client/admin/knowledge-base) - Billing (→
/client/admin/billing) — redirects to Settings/Billing - Footer: Log out button
Main chat area (/client/chat):
- The chat surface itself contains navigation to Approvals, Settings, and Admin via context menus/links embedded in the
PortalChatcomponent.
3.5 Permission Boundaries
org_admin cannot:
- Access
/workspace/*routes (Expert workspace) — redirected to/client/chat - Access
/ops/*routes (Account Manager / SuperAdmin ops) — redirected to root - Create or edit Specialists — Specialist configuration is HP-side only
- View other organisations' data (org-scoped RLS enforced at API layer)
- Hard-delete the organisation (production-gated)
- Access the queue of pending Expert review items
- See Expert assignment details (which Expert is reviewing their conversations)
3.6 Golden-Path Flow: Upload a KB Document & Verify It Parsed
- Log in → land on
/client/chat - Navigate to Admin → Knowledge Base (or go directly to
/client/admin/knowledge-base) - Drag-and-drop a PDF or click the upload area to select a file
- Watch the parse status badge update in real-time via WebSocket (
kb.document.parsedevent) - Once status shows Parsed, click the row to open the detail modal and verify chunk count
- The Specialist will now reference this document in future conversations
4. Role: org_member — Client Organisation Member
4.1 Login + Redirect Target
- Login page:
/login - Post-login redirect:
/client/chat - JWT field:
orgMemberships[0].orgRole = "member"
4.2 Route Table
org_member has the same route access as org_admin with two exceptions — the admin-gated sub-sections of Settings are hidden in the nav but may be reachable by direct URL until the server-side guard fires.
| Route | Accessible to org_member? |
|---|---|
/client/chat | ✅ |
/client/approvals | ✅ |
/client/specialist | ✅ |
/client/settings/profile | ✅ |
/client/settings/team | ✅ (read-only view; no invite/remove/role-change) |
/client/settings/channels | ❌ hidden in nav (admin/owner only) |
/client/settings/billing | ❌ hidden in nav (admin/owner/billing only) |
/client/admin/knowledge-base | ❌ redirected away |
/client/admin/* (setup/team/billing) | ❌ redirected to /client/chat |
/client/specialists/* | ✅ |
/workspace/* | ❌ redirected to /client/chat |
/ops/* | ❌ redirected |
4.3 Per-Page Operations
/client/chat — same as org_admin
/client/settings/team (member view)
- Displays: Same member table but without the Actions column.
- No actions available: Cannot invite, remove, change roles, or transfer ownership.
- Pending invite count is shown but invites cannot be managed.
/client/settings/profile — identical to org_admin
/client/approvals — identical to org_admin
4.4 Navigation Structure
Settings layout sidebar (/client/settings/*):
- ← Back to Chat link
- Section 1 (always): Profile · Team
- Section 2 (channels/billing): Not shown — these nav items are hidden based on
orgRole - Footer: Sign Out + dark mode toggle
The admin sidebar (/client/admin/*) is not reachable — the admin/layout.tsx guard redirects non-admin roles back to /client/chat.
4.5 Permission Boundaries
org_member cannot:
- Invite or remove team members
- Change anyone's role (including their own)
- Transfer workspace ownership
- Access Channels settings (cannot connect/manage integrations)
- Access Billing (cannot view plan details or upgrade)
- Access the Knowledge Base admin page
- Access any Admin section (
/client/admin/*) - Access Expert workspace or Ops surfaces
4.6 Golden-Path Flow: Send a Message to the Specialist
- Log in → land on
/client/chat - If no active thread, type in the compose box and press Enter (or click Send)
- The AI agent drafts a reply — since the default threshold is 101, an Expert always reviews it before it appears
- The Expert sends the reply as the Specialist — the member sees it appear in the thread
- To approve a runtime request from the Specialist, navigate to
/client/approvalsvia the chat UI
5. Role: expert — Humanity Protocol Expert
5.1 Login + Redirect Target
- Login page:
/login - Post-login redirect:
/workspace/queue - JWT field:
platformRole = "expert"
5.2 Route Table
| Route | Description |
|---|---|
/workspace/queue | Main queue — all Expert-review-pending conversations |
/workspace/queue/[id] | Individual ticket detail (full-screen, direct URL or mobile deep-link) |
/workspace/tasks | Agentic task review — approve/reject plan steps |
/workspace/approvals | Runtime approval gates assigned to the Expert |
/workspace/analytics | Queue performance + AI confidence metrics for the Expert's scope |
/workspace/settings | Expert profile settings (name, avatar, title, bio, phone) |
/workspace/pools | Expert pools (legacy page — pools removed 2026-05-03; page may be a stub) |
5.3 Per-Page Operations
/workspace/queue (primary working surface)
- Displays: Two-panel layout — thread list (left) + ticket detail (right). On mobile: single-panel with tab toggle (List / Detail).
- Thread list features:
- Status tabs: All · Pending · Awaiting Client · Resolved · Snoozed
- Risk filter pills: All / Critical / High / Medium / Low
- Assignee filter: All / Mine / Unassigned
- Client filter dropdown (multi-client Experts only — "All Clients" or specific client)
- Each row shows: customer name, relative time, message preview (2-line clamp), risk badge, confidence bar, assignee pill (You / Expert name / Unassigned), channel badge (email only)
- Real-time updates via Socket.io; 8s polling fallback
- Pending count badge on the sidebar Queue icon (updates every 10s when not on queue page)
- Ticket detail panel (
TicketDetail):- Full conversation thread display
- AI-drafted reply with editable text area
- Send button — sends the reply as the Specialist and marks the queue item resolved
- Edit draft — modify the AI draft before sending
- Assign to me button (if unassigned)
- Snooze — snoozes the ticket
- Resolve without reply — closes the ticket without sending
- Escalate / flag options
- Risk level indicator, confidence score, channel badge
- Conversation history (all prior messages)
- Keyboard shortcuts:
?opens the shortcuts modal;j/knavigate items;Enteropens detail;ssends
/workspace/queue/[id] (direct ticket URL)
- Full-screen ticket detail with a ← Back to Queue header bar
- Same operations as the detail panel in
/workspace/queue - Used for mobile direct links and bookmark targets
/workspace/tasks (agentic task review)
- Displays: List of active agentic tasks (Hermes-runtime tasks). Each task card shows:
- Task ID (truncated), status pill, creation time, associated conversation ID
- Progress bar + step-dot timeline (N steps, each with status dot)
- Each step: step number, risk pill, action type, description, parameters JSON, result (expandable)
- Actions per task step (when
requires_approval+status = "pending_approval"):- Approve button — approves the step and allows execution to continue
- Reject button — rejects the step
- Optional feedback text area before rejecting
- View result toggle per completed step (expands JSON result)
- Refresh button to reload task list
/workspace/approvals
- Displays: Runtime approval and input requests assigned to the Expert (Expert-targeted, not client-targeted).
- Title: "Runtime approvals"
- Actions: Review and resolve pending Expert-targeted approval gates
- Note: Client approvals stay on the client surface (
/client/approvals) unless Ops resolves them
/workspace/analytics
- Displays: Analytics dashboard for the Expert's scoped queue.
- Period selector: 7d / 30d / 90d toggle
- Stat cards: Total conversations, resolved, pending, avg. resolution time
- Queue status bars: Pending vs. Resolved horizontal bar comparison
- Top request types: Horizontal bar list of most common request types
- AI confidence distribution: Low / Med / High column chart + percentage score
- Response latency: Avg ms and P95 ms
- Bar chart: Daily conversation volume over the selected period
/workspace/settings
- Displays: Expert profile form.
- Fields: Full name, Display name, Email (read-only), Title/Role, Bio (textarea), Phone
- Actions:
- Upload avatar (camera icon on avatar widget →
AvatarUpload) - Save changes button
- Appearance toggle: Light / Dark mode
- Sign out button (LogOut icon)
- Upload avatar (camera icon on avatar widget →
Productivity primitives inside /workspace/queue (shipped 2026-06-03)
A cluster of workspace-productivity features shipped together on 2026-06-03 to compress per-ticket Expert review time. They appear inside the /workspace/queue ticket detail panel rather than as separate routes.
- Customer history timeline — Side panel that surfaces the customer's prior conversations within the same Org × Specialist scope, rendered alongside the active ticket. Read-only — clicking a prior thread opens it in a new tab. PRs: #1530, #1533.
- KB search panel — Org-scoped Haystack search with citation insertion. The Expert searches the team's documented answers; clicking a result inserts a citation block into the editable draft. Backed by ADR-024 (Haystack/Hayhooks) + ADR-025 (pgvector) + ADR-026 (OpenRouter).
Removed 2026-06-05 — response templates. A third primitive (Org-scoped reusable reply snippets with
{{var}}interpolation, PRs #1532/#1535/#1536/#1618) was deprecated and removed end-to-end the day after it landed indev. The agent already generates a draft for every queue item and learns from Expert corrections over time; a parallel template system created two competing draft sources and a UX surface to keep in sync with model improvements. Issue #1518 closed as not-planned. Seedocs/features/expert-workspace.md→ Deprecated for the removal note.
See also docs/features/expert-workspace.md for the full feature treatment including future-state plans.
Notifications drawer (client portal, not Expert): A dedicated notifications drawer also shipped 2026-06-03 (#1474, #1549) but lives in
/client/*, not/workspace/*. The same notification primitive will plug into the Expert workspace in a follow-up; for now the Expert sees pending work only via the queue-list pending-count badge.
5.4 Navigation Structure
Workspace sidebar layout (collapsible icon-rail):
- Header: h.work logo (links to
/workspace/queue); collapse/expand trigger - Nav items:
- Queue (Inbox icon) — with live pending-count badge (red pill in expanded mode, red dot in collapsed)
- To review (ListChecks icon) →
/workspace/tasks - Approvals (ClipboardCheck icon) →
/workspace/approvals - Analytics (LineChart icon) →
/workspace/analytics
- Footer: Avatar + name + "Expert" role label →
/workspace/settings; Settings icon; Dark/light mode toggle; Keyboard shortcuts (?)
5.5 Permission Boundaries
expert cannot:
- Access
/client/*routes — no layout guard enforces this; any authenticated user can navigate directly to/client/*routes (redirect on login is viagetRoleRedirect()only, not a persistent layout guard) - Access
/ops/*routes — the Ops layout redirects non-AM/non-superadmin to/ - View conversations outside their
expert_accessgrants (ADR-007: dual-scope — per-Specialist or per-Org) - Create, edit, or delete Specialists (SuperAdmin only)
- Create or manage client organisations
- Access the Ops queue (
/ops/queue) — that is the SuperAdmin-only queue view - See other Experts' queue items (scoped by
expert_access) - Access
/workspace/poolsas a functional feature (pools removed 2026-05-03; stub page only)
ADR-007 Expert access scopes:
scope='specialist': Expert sees only conversations for a specific (Org × Specialist) pairscope='org': Expert sees all conversations for the entire Org- Both are managed by an AM or SuperAdmin via the client detail page's Experts tab (SuperAdmin only)
5.6 Golden-Path Flow: Review and Send a Draft Reply
- Log in → land on
/workspace/queue - Pending-count badge shows the number of items awaiting review
- Click the Pending tab to filter to items needing action
- Click a ticket row to open the detail panel (or use
j/k+Enterkeyboard shortcuts) - Read the client's message and the AI-drafted reply
- Edit the draft if needed (risk or accuracy issues)
- Click Send — the reply is sent as the Specialist, the queue item moves to Resolved
- Next item auto-focuses (or press
jto advance)
6. Role: account_manager — Account Manager (AM)
6.1 Login + Redirect Target
- Login page:
/login - Post-login redirect:
/ops/clients - JWT field:
platformRole = "account_manager"—getRoleRedirect()inAuthContext.tsxonly redirects this exact value to/ops/clients; a token with"am"will redirect to/client/chaton login. However,ops/layout.tsxtreats"am"as equivalent to"account_manager"for Ops portal access (isAm = platformRole === "account_manager" || platformRole === "am"), so an"am"token that manually navigates to/ops/*will function as a full AM.
6.2 Route Table
account_manager has access to a subset of the /ops/* routes. Routes marked saOnly in the sidebar are blocked — the Ops layout redirects AMs away from those paths to /ops/clients.
| Route | AM access? | Notes |
|---|---|---|
/ops/clients | ✅ | AM sees only their assigned clients |
/ops/clients/[id] | ✅ | Client detail (tabs: Overview, Conversations, Specialists, Team, Tools — no Experts/Integrations/Audit/Agreements tabs) |
/ops/clients/new | ✅ | Create a new client org (onboarding wizard) |
/ops/clients/[id]/setup/step-1 | ✅ | Setup step 1: basic org info |
/ops/clients/[id]/setup/step-2 | ✅ | Setup step 2: Specialist assignment |
/ops/clients/[id]/setup/step-3 | ✅ | Setup step 3: Expert assignment / review |
/ops/clients/[id]/setup/step-4 | ✅ | Setup step 4: send client invite |
/ops/clients/[id]/edit | ✅ | Edit client org details |
/ops/clients/[id]/specialists/[assignmentId]/edit | ✅ | Edit Specialist assignment config |
/ops/clients/[id]/specialists/[assignmentId]/kb | ✅ | Manage KB for a Specialist assignment |
/ops/inbox | ✅ | AM conversation inbox (cross-client thread view) |
/ops/agent-runs | ✅ | Runtime agent run monitor |
/ops/agent-runs/[id] | ✅ | Specific agent run detail |
/ops/approvals | ✅ | Platform-wide approval requests |
/ops/settings | ✅ | AM profile settings |
/ops/queue | ❌ SuperAdmin only | Redirected to /ops/clients |
/ops/experts | ✅ Accessible (AM + SuperAdmin since #1300, closes #1244) | Cross-client Expert↔org rollup, scoped to the AM's portfolio. See §6.7. |
/ops/sla | ✅ Accessible (AM + SuperAdmin since #1300) | Cross-client SLA-breach rollup. Role-gated page reached by direct URL (not currently in the sidebar). See §6.7. |
/ops/specialists | ❌ SuperAdmin only | Redirected to /ops/clients |
/ops/team | ❌ SuperAdmin only | Redirected to /ops/clients |
/ops/users | ❌ SuperAdmin only | Redirected to /ops/clients |
/ops/leads | ❌ SuperAdmin only | Redirected to /ops/clients |
/ops/expert-applications | ❌ SuperAdmin only | Redirected to /ops/clients |
/ops/analytics | ❌ SuperAdmin only | Redirected to /ops/clients (platform-wide analytics; distinct from the AM cross-client rollups in §6.7) |
/ops/billing | ✅ Accessible (AM + SuperAdmin since #1155 (#1165 was closed-unmerged and superseded by #1155)) | Lago billing overview |
/ops/health | ❌ SuperAdmin only | Redirected to /ops/clients |
/ops/personas/* | ❌ SuperAdmin only | Specialist persona / Tavus integration management (function-calls, replicas, templates). The planned rename to /ops/tavus/* via #1031 was closed without merge; the /ops/personas/* prefix was deliberately retained. AM users land on /ops/clients. |
/ops/pools | ❌ SuperAdmin only | Redirected to /ops/clients |
6.3 Per-Page Operations
/ops/clients (AM view)
- Displays: Data table of the AM's assigned clients. Columns: Client name + slug.domain, Admin Email, Status badge + CTA, Specialist name, Trial End Date, Actions dropdown.
- Status CTAs (inline buttons per row):
pending_am_setup→ Continue →/ops/clients/[id]/setup/step-1pending_specialist_assignment→ Assign →/ops/clients/[id]/setup/step-2pending_client_confirmation→ Resend invite (API call)
- Actions dropdown per row:
- Continue setup (if pending setup)
- Resend invite (if awaiting client)
- View conversations →
/ops/inbox?orgId=[id] - Edit client →
/ops/clients/[id]/edit - Deactivate (if active; irreversible — confirmation dialog)
- Header actions: Search input (client name filter) + Set up new client button →
/ops/clients/new - Row click: Navigates to
/ops/clients/[id]
/ops/clients/new (new client onboarding wizard)
- Step 1 (this page): Creates the org record and advances to setup flow.
- Required fields:
- Company name (min 2 chars)
- Slug (URL-safe, availability-checked in real-time via
SlugAvailabilityInput) - Industry (dropdown: E-Commerce, Financial Services, Legal, Healthcare, …)
- Primary domains (tag input: corporate domains only, no personal email providers)
- Admin email (must match a primary or secondary domain)
- Timezone (common + full IANA list)
- Optional fields (expandable section):
- Billing email
- Secondary domains
- Submit: Creates the org asynchronously (
createAmOrgAsync) with 2s-interval polling (max 30 attempts). On success →/ops/clients/[id]/setup/step-2. - Retry logic: On timeout shows "Retry" button (re-polls); on failure shows "Resubmit" button.
/ops/clients/[id] (client detail, AM view)
- Displays: Client name, status badge, subdomain. Tabs visible to AM: Overview · Conversations · Specialists · Team · Tools
- Overview tab:
- Editable org fields: display name, website, industry, timezone, notes
- Auto-reply config card (
AutoReplyConfigCard) — set confidence threshold (default 101 = always HITL) - Save button
- Conversations tab:
- Paginated conversation list with subject, status, channel, last activity
- Click conversation → opens in context (likely
/ops/inbox?convId=...)
- Specialists tab:
- List of assigned Specialists with assignment config
- Add Specialist button (select from existing Specialists)
- Per-assignment: Edit →
/ops/clients/[id]/specialists/[assignmentId]/edit - Per-assignment: KB →
/ops/clients/[id]/specialists/[assignmentId]/kb - Per-assignment: Remove (confirmation)
- Team tab:
- List of client org members with roles
- AM can view but cannot manage roles (role management is client-side or SuperAdmin)
- Tools tab:
- View enabled agent tools for this client
- AM can view but cannot edit tool permissions (SuperAdmin
canEditonly)
/ops/inbox (AM conversation inbox)
- Displays: Two-panel layout. Left: conversation list (all assigned orgs or filtered by org). Right: message thread.
- Filters: Org dropdown (All / specific client), Status filter (all / open / resolved / etc.)
- Actions:
- Select a conversation (click row)
- Draft message text area + Send button — sends a message as the AM (not as the Specialist)
- Update conversation status (resolve/reopen)
- Pagination within conversation list
- Auto-selects first conversation on load
/ops/clients/[id]/setup/step-1
- Displays: Step progress bar (step 1 of N). Org info form pre-populated from existing record.
- Fields: Company name, slug (with availability check), industry, primary/secondary domains, timezone, admin email
- Actions: Next → (saves and advances to step 2)
/ops/clients/[id]/edit
- Inline org edit form (same fields as setup step 1)
- Save / Cancel buttons
/ops/agent-runs
- Displays: DataTable of recent agent runtime runs. Columns: Run ID, Kind (conversation_draft / expert_side_chat / agentic_task / tool_action / validation / browser_automation / ops_manual), Status badge, Created, Organisation.
- Filters: Status dropdown (All / Active / Waiting approval / Waiting input / Failed / Completed / Cancelled), Kind dropdown
- Refresh button
- Row click →
/ops/agent-runs/[id]
/ops/agent-runs/[id]
- Detail view of a single agent run (steps, inputs, outputs, status timeline)
/ops/approvals
- Displays: DataTable of approval requests platform-wide (visible to AM for their orgs).
- Filters: Status (pending / all / approved / rejected / cancelled / expired), Kind (expert_send_approval / expert_tool_approval / client_approval / integration_write_approval / high_risk_response_approval / sandbox_capability_approval / missing_context), Risk level
- Actions per row:
- Approve button
- Reject button
- Cancel button
- Refresh button
/ops/settings
- Fields: Full name, Display name, Email (read-only), Title/Role, Bio (textarea), Phone
- Actions: Upload avatar, Save changes, Light/Dark mode toggle, Sign out button
6.4 Navigation Structure
Ops sidebar layout (collapsible icon-rail):
- Header: h.work logo + "Ops" sub-label (links to
/ops/clients); collapse/expand trigger - Nav items visible to AM (the flat
NAV_ITEMSlist inops/layout.tsx— distinct from the SuperAdmin groupedNAV_GROUPS):- Clients (Briefcase icon) —
/ops/clients - Inbox (Inbox icon) —
/ops/inboxwith conversation count badge - Experts (UserCheck icon) —
/ops/experts(cross-client rollup, §6.7) - Billing (CreditCard icon) —
/ops/billing(cross-client rollup, §6.7) - Approvals (ClipboardCheck icon) —
/ops/approvals - Runtime runs (Activity icon) —
/ops/agent-runs
- Clients (Briefcase icon) —
- Not in the AM sidebar: Queue, Specialists, Team, Users, Leads, Applications, Analytics, Health (SuperAdmin-only).
/ops/slais AM-accessible but is also not a sidebar item — it is reached by direct URL / SLA-breach escalation (§6.7). - Footer: Avatar + name + "account manager" role label →
/ops/settings; Settings icon; Dark/light mode toggle; Keyboard shortcuts (?)
6.5 Permission Boundaries
account_manager cannot:
- Access
/client/*routes (login redirect goes to/ops/clients; no persistent layout guard blocks navigation) - Access
saOnlyops routes — the Ops layout redirects AMs to/ops/clientsfor anysaOnlypage - View all clients platform-wide — only their assigned clients appear via
listAmOrgs() - Access the platform-wide queue (
/ops/queue) — SuperAdmin only - Create, edit, or delete Specialists (
/ops/specialists) — SuperAdmin only - Manage internal HP team members (
/ops/team) — SuperAdmin only - View or manage all platform users (
/ops/users) — SuperAdmin only - View leads (
/ops/leads) — SuperAdmin only - Review Expert applications (
/ops/expert-applications) — SuperAdmin only - View platform-wide analytics (
/ops/analytics) — SuperAdmin only (distinct from the AM-accessible cross-client rollups in §6.7) - Perform billing mutations (
sync-customer,retry-sync, customer detail, expert-workload, llm-cost, payment-failures) — SuperAdmin only; the AM/ops/billingview is read-only and portfolio-scoped (see §6.7) - View system health (
/ops/health) — SuperAdmin only - Manage Tavus function-calls/templates/replicas (
/ops/personas/*; the planned rename to/ops/tavus/*via #1031 was closed without merge) — SuperAdmin only - Impersonate client users (SuperAdmin-only action in client detail page)
- Edit tool permissions on client detail (read-only; SuperAdmin
canEdit) - View the Experts / Integrations / Audit / Agreements tabs on the client-detail page (
/ops/clients/[id]) — these per-client tabs are SuperAdmin-only and are separate from the AM-accessible cross-client Experts rollup at/ops/experts(§6.7)
6.6 Golden-Path Flow: Onboard a New Client
- Log in → land on
/ops/clients - Click Set up new client
- New client form: Enter company name, verify slug availability, select industry, add corporate domain(s), enter admin email, set timezone → click Create
- System creates the org asynchronously; on completion → redirected to Setup step 2
- Step 2: Assign a Specialist from the existing catalog. Set confidence threshold (default 101 = always HITL)
- Step 3: (if applicable) Review Expert access grants
- Step 4: Send the client invitation email to the admin
- Org status moves to
pending_client_confirmation— appear on the Clients list with "Resend invite" CTA - Once the client accepts → status becomes
active
6.7 Cross-Client Rollups (Experts / SLA / Billing)
Shipped in #1300 (closes #1244). These are portfolio-wide read surfaces: each aggregates across all the AM's assigned clients (organizations.assigned_am_id = me) in one table, with a per-client filter for drill-down. SuperAdmin sees the same surfaces unscoped (every active org). Full engineering reference: docs/features/am-rollups.md.
| Surface | Route | Rolls up | In sidebar? |
|---|---|---|---|
| Experts | /ops/experts | Every Expert↔org assignment in the portfolio (one row per org-scoped expert_access grant) | ✅ |
| SLA breaches | /ops/sla | Open expert-queue items past their SLA deadline, across the portfolio | ❌ — direct URL / post-escalation landing |
| Billing | /ops/billing | Per-Specialist Lago subscription state across the portfolio | ✅ |
Tenant scoping (the safety contract): every rollup goes through AmOrgScopeGuard + OrganizationAccessService. An AM sees only orgs assigned to them; supplying a ?orgIds= for a client outside the portfolio returns 403, and an AM with zero assigned orgs gets an empty table (fail-closed, never unscoped). Verified by api/test/am-cross-org-isolation.e2e-spec.ts.
/ops/experts (Experts rollup)
- Displays: One row per (Expert, client) — Expert name/email/status, the org, assignment id, assigned-at.
- Filter: Client dropdown writes
?org=<id>; the selected client is preserved when switching to/ops/billing(and back). - Data:
GET /am/experts→listAmExpertsRollup(org-scoped, non-revokedexpert_access, suspended Experts excluded).
/ops/sla (SLA-breach rollup)
- Displays: Breached queue items oldest-first — Client (links to
/ops/clients/{orgId}), Expert (or "Unassigned"), Breached timestamp, Age since breach, and an Open drill-down link. - Filters: Client dropdown (
?org=) plus From/To date filters (?from=/?to=, applied to the breach time). - Drill-down: Open →
/ops/clients/{orgId}?tab=experts&queueItemId={id}— lands on that client's Experts/queue tab pointed at the breached item, where the AM/Expert can act on it. - What counts as a breach: an open (non-
resolved) queue item whosesla_breach_atdeadline has passed. The deadline is set at item creation from the org's SLA config (metadata.sla_threshold_hours, default 4h;metadata.sla_timezone, default UTC;metadata.sla_business_hours_enabled, default on → counts only Mon–Fri 09:00–18:00 in the org tz). Asla-breach-monitorcron runs every 2 minutes and escalates each breach once to the org's assigned AM (Slack DM → email fallback). - Data:
GET /expert-queue?slaBreached=true→listSlaBreaches.
/ops/billing (Billing rollup)
- Displays: Per-Specialist subscription rows across the portfolio (org, Specialist, status, current rate, currency) plus totals (
active,sync_failed). - AM vs SuperAdmin: the AM gets a read of their portfolio. Billing mutations (sync-customer, retry-sync, customer detail, expert-workload, llm-cost, payment-failures) stay SuperAdmin-only.
- Data:
GET /ops/billing→OpsBillingOverviewQuery(Lago-mirrored state — see §Billing).
Refresh: the rollup pages fetch on load and re-fetch when the client filter changes; there is no background polling on these surfaces, so reload (or change the filter) to refresh.
7. Role: superadmin — SuperAdmin
7.1 Login + Redirect Target
- Login page:
/login - Post-login redirect:
/ops/clients - JWT field:
platformRole = "superadmin"
7.2 Route Table
SuperAdmin has access to all /ops/* routes — everything the AM sees plus all saOnly routes.
| Route | Description |
|---|---|
/ops/clients | All clients platform-wide (SuperAdmin view shows full OrgOverview table) |
/ops/clients/[id] | Full client detail with SA-only tabs: Experts, Integrations, Agreements, Audit + SA action bar |
/ops/clients/new | Create new client (same form as AM) |
/ops/clients/[id]/setup/step-1 through /step-4 | Setup wizard |
/ops/clients/[id]/edit | Edit client |
/ops/clients/[id]/specialists/[assignmentId]/edit | Edit Specialist assignment |
/ops/clients/[id]/specialists/[assignmentId]/kb | Manage Specialist KB |
/ops/inbox | Platform-wide conversation inbox |
/ops/queue | Platform-wide Expert review queue (read + triage) |
/ops/experts | Expert roster — assign/remove Experts from client orgs |
/ops/specialists | Specialist catalog — create, edit, delete Specialists |
/ops/team | Internal HP team — invite/remove AMs, Experts, AI operators; impersonate |
/ops/users | All platform users — full user table with role filter + impersonate |
/ops/leads | Company leads from sign-up form |
/ops/expert-applications | Expert application review |
/ops/analytics | Platform-wide analytics dashboard |
/ops/billing | Lago subscription management across all orgs (AM + SuperAdmin — #1155; #1165 was closed-unmerged, superseded by #1155) |
/ops/health | System health dashboard |
/ops/agent-runs | Runtime agent run monitor (all orgs) |
/ops/agent-runs/[id] | Agent run detail |
/ops/approvals | All approval requests (full platform) |
/ops/personas/templates | Specialist prompt templates management (the planned rename to /ops/tavus/* via #1031 was closed without merge; /ops/personas/* routes were deliberately retained) |
/ops/personas/replicas | Tavus video replica management |
/ops/personas/function-calls | Function call catalog management |
/ops/audit | Platform-wide SuperAdmin audit log — actor / action / target / timestamp / diff across all orgs (#1238 / #1298) |
/ops/feature-flags | Kill-switch / feature-flag admin — toggle platform capabilities at runtime (#1273, closes #1242) |
/ops/dlq | Dead-letter queue admin — inspect / requeue / discard failed background jobs (#1239 / #1251) |
/ops/sla | AM cross-client SLA rollup — Expert response-time breaches across all orgs (#1244 / #1300) |
/ops/impersonation | Impersonation audit trail — who shadowed whom, when, and what they did |
/ops/pools | Expert pools (legacy — pools removed 2026-05-03) |
/ops/settings | SuperAdmin profile settings |
7.3 Per-Page Operations
All AM operations apply. The following are SuperAdmin-exclusive additions:
/ops/clients (SuperAdmin view)
- SuperAdmin-specific columns: Plan badge (free/starter/pro/enterprise), Conversations count, Members count, Created date
- Row click →
/ops/clients/[id](full SA view with extra tabs) - Same search + filter as AM view
/ops/clients/[id] (SuperAdmin view)
- All AM tabs PLUS:
- SA action bar: Impersonate button → opens member picker dropdown → opens new tab logged in as selected client user (every action audited)
- Experts tab: Assign/remove Expert access grants for this org (ADR-007 dual-scope — per-Specialist or per-Org). Add Expert → select from Expert list → select scope
- Integrations tab: View all integration records for this org (Slack, Email, WhatsApp, Telegram, etc.)
- Agreements tab: View agreement acceptance records + missing agreement alerts
- Audit tab: Append-only audit trail for this org (entries with actor, action, timestamp, diff)
- Tools tab (editable): Toggle tool permissions on/off (SuperAdmin
canEdit=true)
/ops/queue (SuperAdmin queue)
- Displays: Two-panel queue view (reuses
TicketDetailfrom workspace). All expert-review items platform-wide. - Filters: Status (All / Pending / Resolved), Risk (All / Critical / High / Medium / Low)
- Auto-refresh: every 15 seconds
- Actions: Same ticket review actions as Expert workspace (view conversation, edit draft, resolve)
- Pending count badge in sidebar — updates every 10s
/ops/experts
- Displays: DataTable of all HP Experts. Columns: Name, Email, Status badge, Assigned Orgs (clickable tags).
- Actions per row:
- Assign to org — opens org picker popover → assigns Expert to a client org
- Remove from org — removes an Expert-Org assignment (per org tag in the cell)
- Impersonate → opens new tab as that Expert
- Actions dropdown with all of the above
- Superadmin-only:
listAllUsers()API call withexpertrole filter; not accessible to AM
/ops/specialists
- Displays: DataTable of all Specialists in the catalog. Columns: Avatar, First/Last name, Email (
{firstname}@{HWORK_DOMAIN}), Category, Skill tags, Confidence threshold. - Modes: list / create / edit / view
- List actions:
- New Specialist button → switches to create form
- Row click → opens view modal
- Edit (actions dropdown) → switches to edit form
- Delete (actions dropdown) → confirmation then deletes
- Create/Edit form fields: First name, Last name, Email (auto-composed as
{first}@{HWORK_DOMAIN}), Avatar upload, Category (dropdown), Skill tags (tag input), Bio (textarea), System prompt (textarea), Specialty domains (tag input), Catalog slug, Tavus persona ID, Confidence threshold (default 101) - Save / Cancel buttons
- SuperAdmin-only: No AM access to this page
/ops/team (internal HP team)
- Displays: DataTable of all internal HP team members (AMs, Experts, AI operators). Columns: Name, Email, Role badge, Status badge, Joined.
- Actions:
- Invite team member button → form with email + role selector (account_manager / expert / ai_operator)
- Impersonate (actions dropdown) → opens new tab as selected internal user
- Remove (actions dropdown) → removes platform member (confirmation)
- Search input (name/email filter)
/ops/users (all platform users)
- Displays: DataTable of every user across all orgs and roles. Columns: Name, Email, Role badge, Status badge, Org.
- Role filter dropdown (All roles / Org Members / Org Admins / Experts / Account Managers / AI Operators / Super Admins). The legacy
client_member/client_adminvalues are dead (never assigned, per #2847) and intentionally omitted from the filter. - Search by name or email
- Row → detail page (
/ops/users/[id]): Identity, Lifecycle (incl. audit trail), Memberships, Recent Activity, plus an Actions dropdown:- Edit — edit-user form (#1299, closes #1240). Editable fields: Name, Email, Platform role, Status. Email collisions return 409; promoting to SuperAdmin requires re-typing the target email; you cannot demote/disable yourself or the last active SuperAdmin. Changing email/role/status-to-suspended-or-deactivated revokes the user's sessions (confirmation modal interposed).
- Reset password (active/suspended rows) — emails a 6-digit OTP to the target; the actor never sees it. Active-only on the backend; rate-limited to 5/actor/hour.
- Impersonate (non-SuperAdmin rows) → opens new tab as that user; reason required, fully audited.
- Full reference:
docs/features/ops-users-admin.md.
/ops/leads
- Displays: DataTable of company sign-up leads. Columns: Company name, Industry, Contact name, Contact role, Work email, Company size, Headquarters, Selected roles, Created date.
- Read-only: No actions beyond viewing
/ops/analytics (platform-wide)
- Period selector: 7d / 30d / 90d
- Stat cards: Total conversations, resolved %, pending, avg response latency
- Charts: Daily conversation volume (bar chart), queue status, confidence distribution, top request types, response latency (avg + P95)
- Scope: All organisations on the platform
/ops/billing
- Displays: Lago-backed billing overview — stat cards (total / active / sync-failed subscriptions) and a DataTable of all Lago subscriptions across orgs. The legacy Stripe summary view was retired post-Phase-7 (#1016, 2026-05-28); the page was rebuilt on Lago in #1155 (#1165 was closed-unmerged and superseded by #1155) (2026-05-31).
- Columns: Client, Specialist, Subscription status, Monthly rate, Last sync.
- Actions per row:
- Retry sync — re-pushes the subscription to Lago when the previous sync failed.
- Access: AM + SuperAdmin (no longer
saOnly— nav opened in #1155 (#1165 was closed-unmerged and superseded by #1155)). Direct Stripe lives only inside Lago's PSP config.
/ops/health
- Displays: Service health status cards for: API, Agent, Database, Redis, WebSocket.
- Each card: service name, status dot (ok=green, degraded=yellow, down=red, checking=grey), status badge label, optional detail message.
- Refresh button — re-polls all services
- Auto-refresh interval (best-effort)
/ops/expert-applications (Expert application review — incl. Tavus video interviews)
- Displays: DataTable of all Expert applicants. Columns: Name, Email, Status badge (
pending/reviewing/qualified/invited/interview_completed/waitlisted/approved/rejected), AI score, Tavus interview link + duration, Created date. - Tabs: All applicants | Pending review | Interviews (post-interview review queue) | Waitlisted | Approved | Rejected. The Interviews tab is the post-2026-06-03 surface for the Tavus integration (PR #1524).
- Funnel summary (top of page): counts per status; live as applicants progress.
- Per-row actions (varies by current status):
- Send to interview — moves a
qualified(orwaitlisted) applicant into the Tavus video interview track; mints a personalized interview link via Tavus. PR #1565. - Retry interview invite — re-sends the invite email with the same link; useful if the original bounced or the applicant lost it.
- Approve — promotes the applicant to a platform Expert (creates the user, sends
application_approved+welcomeemails). The Approve transition is wired to the post-interview status (PR #1565). - Decline — sends
application_declinedand moves torejected. - Update threshold — adjusts the AI-screening threshold inline (no full edit form).
- 🗑️ Hard delete — SuperAdmin-only destructive action to scrub spam / duplicate submissions. Confirmation required. PR #1519.
- Send to interview — moves a
- Tavus interview detail — clicking an
interview_completedrow opens a side panel with: Tavus conversation ID, recording playback link + duration, transcript link (R2-mirrored per PR #1596 — 7-year retention with signed URLs), AI summary, and reviewer notes textarea. - Email side-effects: All status transitions fire templated emails via
EmailService(PR #1560):application_received,interview_scheduled,application_approved,application_declined,welcome. - Search by name / email / company.
- Access: SuperAdmin only. AM sees a redirect.
See docs/features/expert-application.md for the full feature treatment including the Tavus webhook lifecycle. The public front of this funnel — the /experts/join landing page and /experts/apply form that feed applications into this queue — is documented in docs/features/expert-acquisition.md.
/ops/personas/templates (rename to /ops/tavus/* via #1031 was closed without merge)
- Specialist prompt template management (list, create, edit, delete templates)
/ops/personas/replicas
- Tavus video replica management (list, create, delete replicas linked to Specialists)
/ops/personas/function-calls
- Function call / tool definition catalog management
/ops/approvals (SuperAdmin scope)
- Same UI as AM but sees all approval requests across all orgs.
- Full approve / reject / cancel actions on any request regardless of org.
/ops/feature-flags (kill-switch / feature-flag admin)
-
SuperAdmin-only runtime control plane for major Specialist capabilities. Flip a flag to turn a capability on/off without a deploy — the change propagates across the fleet within ~15 s (the resolve cache TTL). Shipped in #1273 (closes #1242). Full reference:
docs/features/feature-flags.md. -
Layout: three tables — Global flags, Per-org overrides, Per-org-specialist overrides. Each row shows name / scope / state (On/Off badge) / reason / last change (who + when).
-
Flags:
Flag (UI label) Default OFF behavior Specialist drafting ( agentic_mode_enabled)On Agentic task creation 403s; pipeline falls back to non-agentic drafting. KB retrieval ( kb_retrieval_enabled)On Retrieval returns no documents; Specialist drafts without KB context. Auto-reply ( auto_reply_enabled)Off (built-in) No AI draft auto-delivered — everything queues for Expert review. Tool calling ( tool_calling_enabled)On Tool calls blocked at the gateway ( status=blocked); drafting continues without tools.telegram_self_serve_enabledOff Client self-serve Telegram setup returns 403. The current UI does not give this flag a friendly label, so its global row shows with a blank name and it is not selectable in the Add override dropdown. -
Scope precedence: most-specific-wins —
org_specialistoverride beatsorgoverride beatsglobalbeats the built-in default. There is no merge; a narrower row fully overrides broader ones (so anorg = Onrow keeps one client live even whileglobal = Off). -
Actions:
- Toggle (power icon) → confirm dialog; a reason (≥ 5 chars) is mandatory before the state flips. Toggle is optimistic and rolls back on API error.
- Add override (org / org-specialist sections) → supply an Org ID or Org-specialist assignment (OSA) id + reason to create a scoped row.
- History (clock icon) → per-flag audit trail (last 50 changes for that key + scope:
previous → new, actor, timestamp, reason).
-
Auditing: every write is transactional and recorded in
feature_flag_auditand the platform audit log (feature_flag.toggle). -
Incident use: see
docs/runbooks/incident-response.md§ Feature Flags / Kill-Switches for "when to flip a flag during an incident."
/ops/audit (platform-wide audit log)
- SuperAdmin-only read-only view of the append-only platform audit log — every significant action across all orgs plus platform-level events. Shipped in #1298 (closes #1238). Full reference:
docs/features/audit-log.md. - What's recorded: auth/MFA, user admin, impersonation, conversations & messages, Expert queue, drafts, KB document changes, channel inbound, integrations/Haystack, org & OSA lifecycle, Expert-access grants, and feature-flag toggles. Each row captures actor, action, entity type/id, client (org), timestamp, IP, and a JSON payload diff.
- Columns: Event (human-readable summary + raw action) · Client (org name, or "Platform" for null-org events) · Actor (resolved
Name (email), or role for system events, plus a copyable user id) · Entity (type + copyable id) · When (relative, full timestamp on hover). - Filters: Client (dropdown), Actor ID, Action (e.g.
message.send), Entity (e.g.conversation), From/To datetime range, Rows (25/50/100). Pagination is cursor-based with a total count. - CSV export: exports the filtered set up to a 10,000-row cap (warns and truncates beyond that — narrow filters to get the rest). Values are escaped against spreadsheet formula injection.
- Scope note: actor identities are resolved only on this SA surface and the per-client Audit tab; the customer-facing feed never exposes internal Expert/AM identities.
- Consistency note: audit writes are eventual/fire-and-forget (ADR-019) — a strong operational record, not a guaranteed-complete ledger. There is no automated retention/TTL — rows persist until manually pruned.
- Incident use: the primary forensics surface — see
docs/runbooks/incident-response.md§ Forensics.
7.4 Navigation Structure
Ops sidebar layout — same collapsible structure as AM, but all nav items are visible:
| Nav item | Icon | Route |
|---|---|---|
| Clients | Briefcase | /ops/clients |
| Inbox | Inbox | /ops/inbox ← with conversation count badge |
| Queue | ListChecks | /ops/queue ← with pending-count badge (SA only) |
| Experts | UserCheck | /ops/experts |
| Specialists | IdCard | /ops/specialists |
| Team | Users | /ops/team |
| Users | UserSquare | /ops/users |
| Leads | Layers | /ops/leads |
| Applications | ShieldCheck | /ops/expert-applications |
| Analytics | LineChart | /ops/analytics |
| Billing | CreditCard | /ops/billing |
| Health | HeartPulse | /ops/health |
| Runtime runs | Activity | /ops/agent-runs |
| Approvals | ClipboardCheck | /ops/approvals |
Footer: Avatar + name + "superadmin" label → /ops/settings; Settings icon; Dark/light mode toggle; Keyboard shortcuts (?)
7.5 Permission Boundaries
SuperAdmin has no functional restrictions within the platform. However, by design:
- Hard-delete org is gated on
IS_PRODUCTION === false— returns 403 in production. Use deactivate instead. - Impersonation is audited — every action taken while impersonating is recorded in the org audit trail.
- Specialist create/update/delete — these endpoints are SuperAdmin-only at the API layer (
PlatformRolesGuard).
7.6 Golden-Path Flow: Promote an Expert and Assign to a Client
- Log in → land on
/ops/clients - Navigate to Team (
/ops/team) to confirm the Expert exists in the HP team; if not, Invite team member with roleexpert - Navigate to Clients → click the target client → open Experts tab
- Click Add Expert → select the Expert from the dropdown → choose scope:
scope='specialist'→ select which Specialist they cover (tightest, per ADR-007)scope='org'→ covers the entire client org
- Confirm — the Expert now sees this client's conversations in their
/workspace/queue - Optionally navigate to Specialists tab → click Edit on the assignment → adjust confidence threshold to allow auto-send for low-risk messages
8. Cross-Role Reference: Route Ownership
| Route prefix | org_admin | org_member | expert | account_manager | superadmin |
|---|---|---|---|---|---|
/client/chat | ✅ | ✅ | ❌ | ❌ | ❌ |
/client/approvals | ✅ | ✅ | ❌ | ❌ | ❌ |
/client/settings/profile | ✅ | ✅ | ❌ | ❌ | ❌ |
/client/settings/team | ✅ manage | ✅ read-only | ❌ | ❌ | ❌ |
/client/settings/channels | ✅ | ❌ | ❌ | ❌ | ❌ |
/client/settings/billing | ✅ | ❌ | ❌ | ❌ | ❌ |
/client/admin/knowledge-base | ✅ | ❌ | ❌ | ❌ | ❌ |
/workspace/queue | ❌ | ❌ | ✅ | ✅ | ✅ |
/workspace/tasks | ❌ | ❌ | ✅ | ✅ | ✅ |
/workspace/approvals | ❌ | ❌ | ✅ | ✅ | ✅ |
/workspace/analytics | ❌ | ❌ | ✅ | ✅ | ✅ |
/workspace/settings | ❌ | ❌ | ✅ | ✅ | ✅ |
/ops/clients | ❌ | ❌ | ❌ | ✅ (own) | ✅ (all) |
/ops/clients/new | ❌ | ❌ | ❌ | ✅ | ✅ |
/ops/inbox | ❌ | ❌ | ❌ | ✅ | ✅ |
/ops/queue | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/experts | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/specialists | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/team | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/users | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/leads | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/analytics | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/billing | ❌ | ❌ | ❌ | ✅ | ✅ |
/ops/health | ❌ | ❌ | ❌ | ❌ | ✅ |
/ops/agent-runs | ❌ | ❌ | ❌ | ✅ | ✅ |
/ops/approvals | ❌ | ❌ | ❌ | ✅ (own orgs) | ✅ (all) |
/ops/settings | ❌ | ❌ | ❌ | ✅ | ✅ |
9. ADR Cross-References
ADR-007: Expert Access Scope — Dual-Scope Grants
Date: 2026-05-22 | Status: Accepted
What it means for operators:
- Expert visibility is controlled by the
expert_accesstable — the canonical Expert ↔ data grant. - Two scopes are supported:
scope='specialist': Expert sees only one (Org × Specialist) pair — use for sensitive data separation (e.g., KYC Expert should not see Finance threads)scope='org': Expert sees everything for the whole Org — use for senior reviewers or account leads
- Deprecated:
org_expertstable (old direct Org assignment). Do not use in new code. - Where to manage: SuperAdmin →
/ops/clients/[id]→ Experts tab → Add Expert + select scope - Cascades into: Queue scoping (
/workspace/queuefilters by access grants), Specialist config visibility, KB access (future)
ADR-018: Multi-Pod Safety Contract (Active-Active)
Date: 2026-05-28 | Status: Accepted
What it means for operators:
- The platform runs as multi-instance active-active — N pods handle traffic simultaneously with no sticky sessions.
- There is no "primary" pod — any pod can serve any user request.
- All state is stored externally (PostgreSQL + Redis) — no in-process caches or counters that matter across requests.
- Scheduled jobs (e.g., DLQ retry, trial-ending notifications) run exactly once globally via BullMQ with stable
jobId— they do not fire N times per pod. - This means: if you see unexpected duplicate events or missing jobs, the cause is almost never "multi-pod" by design — it is a code violation of AA1–AA10. File a bug.
- Rolling deploys are safe — old and new pod versions coexist for minutes during deployment. Schema migrations follow expand-contract (additive first, then remove old columns).
ADR-024: Haystack 2.x + Hayhooks as the RAG runtime (supersedes RAGflow)
Date: 2026-06-02 | Status: Accepted
What it means for operators:
- KB search in the Expert workspace (and the agent's RAG retrieval path) runs against Haystack/Hayhooks, not the prior RAGflow service.
- No RAGflow operations remain — provisioning runbooks under
docs/_archive/ragflow-*.mdare historical. TheRAGFLOW_PROVISIONING_MODEenv var is no longer used. - Per-environment cost moved from ~$2k/env-month → $440/env. If you see unexpected KB-search latency or auth errors, the runbook is
docs/runbooks/haystack-deploy.md, not the archived RAGflow ones. - Supersedes the archived ADR-004 (per-org corrections dataset) and ADR-009 (RAGflow shared-instance vs per-tenant). Both archived under
docs/_archive/.
ADR-025: pgvector on the existing humanwork Postgres
Date: 2026-06-02 | Status: Accepted
What it means for operators:
- Document embeddings live in the existing humanwork Postgres via
pgvector, not RAGflow's bundled search. - No separate vector-store ops surface. Operations on the document store happen via standard Postgres tools.
- The CI postgres container already has
pgvector(sinceb7417b1d, 2026-05-03). New deployments inherit this; no extra setup.
ADR-026: OpenRouter for embed, chat, and rerank
Date: 2026-06-02 | Status: Accepted
What it means for operators:
- All embed / chat / rerank traffic routes through OpenRouter — one key, one billing line.
- If an LLM-related cost row appears under "OpenAI direct" or "Anthropic direct" in billing, that is drift and should be filed as a bug. The
correction_embeddingspath (PR #1604) is currently the one known drift exception; migration tracked in #1614. - Single-vendor failure mode: if OpenRouter is down, all LLM features degrade together. Health check on
/ops/healthsurfaces this.
ADR-027: TypeORM migrations only
Date: 2026-06-03 | Status: Accepted
What it means for operators:
- Schema changes go through TypeORM migrations in
api/migrations/. Raw SQL files underapi/src/database/migrations/are forbidden — CI blocks them. - Deployments must opt in to running migrations on boot via
RUN_MIGRATIONS_ON_BOOT=true. Without that flag, schema changes are silently inert. - If a deploy looks successful but a column / table is missing in prod, check the
RUN_MIGRATIONS_ON_BOOTenv var first — it's the most common cause.
ADR-028: Retire per-org Railway agent runtime — ECS-only
Date: 2026-06-03 | Status: Accepted
What it means for operators:
- The platform supports two agent runtimes:
shared_railway(default) andecs_per_org(premium). railway_per_orgno longer exists as anAgentRuntimeKind. Provisioner code removed in PR #1584.- If you see a Railway-per-org reference in an older doc, runbook, or PR description, treat it as historical. The current cutover playbook lives in
docs/runbooks/ecs-prod-deployment-spec.md. - ADR-003 (Railway as canonical deployment) is fully superseded for staging/prod by ADR-038 — prod cutover #701 closed 2026-06-15. Railway remains canonical for dev only (#1233). Tracked in #1634.
End of USER_OPERATIONS_MANUAL.md