Skip to main content

Implementation Status

Single source of truth for what is and isn't built. Last reviewed: 2026-06-24 (ops cost/leverage analytics refresh: SA-E4 Expert leverage shipped via #3199; SA-B5 per-org cost now partial — LLM cost + Expert workload in PRs #3195/#3200, dollarized margin pending #3196). Prior audit pass 2026-06-04: refreshed §15/§16 for the agent-runtime decommission per ADR-028 / #1584; aligned dogfood Specialist name with scripts/seed-dev.sh (Eleanora Voss, not Bob); added "Past Week" stanza below. Previous review 2026-05-25.). Cross-referenced against: api/src/ controllers + entities, frontend/src/ components + pages.


Past Week — Shipped 2026-05-27 → 2026-06-04

Major merges since the 2026-05-25 review that are NOT yet expanded into the per-section tables below. Each is filed against the section it touches so future re-syncs can promote the row in-place.

PRSectionWhat
#1604§15 / Learning loopNew correction_embeddings table — Phase 1 of #1360 learning-loop closure. Uses OpenAI directly for embedding generation, not OpenRouter — flagged as a possible exception to ADR-026; pending Eusden confirmation whether deliberate or drift.
#1602 / #1613 / #1199§5 Onboarding briefsenvironment_profilesclient_briefs rename fully shipped (all merged 2026-06-04 under #632). DB-table rename + client_brief_revisions audit table via #1602 (migration 1785500000001-RenameEnvironmentProfilesToClientBriefs.ts, closes #1172); API module / entity / controller / route + permission guards via #1613 (closes #1173) — module is now api/src/client-briefs/, entity ClientBrief, route /client-briefs/*, old /environment-profiles/* paths kept as 308 redirects (slated for removal ~30 days after the FE path swap); frontend copy + API client via #1199 (closes #1174).
#1599§15 / ResilienceOpenRouter CircuitBreaker moved to Redis (last in-process CB caller removed) so the multi-pod active-active deployment converges on a single shared circuit state.
#1584 / #1450§15, §16Decommission RailwayPerOrgProvisioner — only shared_railway and ecs_per_org agent runtimes remain. Implements ADR-028. Supersedes the 2026-05-22 "soak ongoing" claim from #589.
#1559§17 / CIdev → staging → main promotion flow is now CI-enforced — guard workflow is a required status check that rejects PRs to main not originating from staging (and to staging not from dev). Companion doc: docs/promotion-flow.md.
#1537§1 / domainsDomain canonicalization: h852.work = dev, h853.work = staging, h.work = prod. Sweep any older docs using stale subdomain names.
#1583 / #1506 / #1493§1 / authCross-org IDOR fix on conversations + fail-closed auth + restore @Public() on routes broken by the global guard (webhook ingress, bootstrap). Public-auth surface audit landed simultaneously.
#1502 / #1598§15 / tool gatewayHERMES_TOOLSETS is now wired from the toolsManifest + tool-gateway client — Specialist-scoped tool surfaces no longer rely on env-var allowlists.
#1432§6 / channelsGmail Pub/Sub webhook for inbound email (closes #686).
#1526 + #1528§13 / KBKB search endpoint for Expert workspace (backend) + KB search panel UI.
#1551 / #1433§10 / billingGrace-period gating + /ops/billing surfacing for payment-failure states.
#1475§10 / billingIn-app notifications on payment failure.
#1508§11 / SLAPer-org SLA config + Slack breach alerting.
#1530 / #1533§8 / Expert workspaceCustomer history timeline (backend + FE).
#1549 / #1474§3 / client portalDedicated client notifications drawer.
#1083§14 / TavusTavus expert-application interview integration fixes.
#1442§6 / channelsEmail cutover rollback runbook.
#1498§6 / SlackSlack OAuth install runbook.
#1577§17 / infraterraform-apply is now workflow_dispatch-only — no infra change applies on push.
#1510§1 / DEMO_MODEAudit + CI guard preventing DEMO_MODE=true from leaking into a production deploy.
#1567 / #1570§15 / /agentic/tasksProper 401/403 + role-aware scoping for /agentic/tasks/* endpoints.
#1522§15 / RuntimeToolExecutorAdded order_lookup tool to the RuntimeToolExecutor surface.

#1604 / ADR-026 caveat: The correction_embeddings table generates embeddings via the OpenAI SDK directly, not OpenRouter. ADR-026 says "embed, chat, rerank" should route through OpenRouter. Until Eusden confirms this is a deliberate per-pipeline exception (vs. a drift), do not promote ADR-026 to "live for all embedding paths".


1. Authentication & Roles

FeatureStatusNotes
Email + password login✅ CompletePOST /auth/login → JWT; auth.service.ts
Email OTP (passwordless)✅ CompletePOST /auth/request-otp + POST /auth/verify-otp
Onboarding OTP (invite flow)✅ CompletePOST /auth/send-invite-otp + POST /auth/verify-invite-otp; single-use OTP per invite token
Demo login (DEMO_MODE)✅ CompletePOST /auth/demo-login; supports superadmin, account_manager, expert, client; non-prod only. Maps to canonical seed users: amy@acmefinancial.com (client), expert1@humanwork.dev (expert), am1@humanwork.dev (AM), e@humanity.org (superadmin). CORS auto-allows Vercel dev/staging when DEMO_MODE=true.
JWT generation + validation✅ CompleteRS256 JWT with sub, email, name, platformRole, orgMemberships[]; 7-day expiry
2FA (TOTP)✅ CompleteTOTP via otplib; POST /auth/2fa/setup + POST /auth/2fa/verify; qrcode generation
Role-based routing (frontend)✅ CompletegetRoleRedirect() in AuthContext; superadmin → /ops/clients, expert → /workspace/queue, account_manager → /ops/clients, client → /client/chat. Legacy /am/* and /superadmin/* redirect to matching /ops/* routes.
Platform roles✅ Completesuperadmin, account_manager, expert, ai_operator, org_admin, org_member, client_admin, client_member
Org memberships (owner/admin/member/billing)✅ CompleteOrgMembership entity; encoded in JWT
Row-level security (RLS)✅ CompletePostgreSQL RLS policies in 6 migrations (009, 013, 017, 027, 033, + WhatsApp whitelist); two-tier internal/client domain policy; SQLite test environments skip via guard

2. Client Onboarding

2026-05-10 rebuild (PRs #267–271): Client onboarding rebuilt as a 3-step SPA at single URL /onboarding/start?token=… — no page reloads between steps. Channel Setup, Teammates, and Billing steps removed from the wizard (Channels and Billing are still reachable post-onboard from /client/settings/*).

FeatureStatusNotes
Phase 0 — validation gate (AM-side)✅ CompleteGET /am/orgs/:orgId/phase0-status; hard-blocks until company info, specialist, AM profile, trial date all pass
Phase 1.1 — company info (AM creates org)✅ CompleteName, slug, industry, domains, email, website, country, timezone; real-time slug validation
Phase 1.2 — assign specialists✅ CompleteMulti-specialist assignment; confidence threshold per specialist; primary designation; OrgSpecialistAssignment entity
Phase 1.3 — AM profile✅ CompleteGlobal AM profile (shared across orgs)
Phase 1.4 — send client invite✅ CompleteClientInvite token (7-day expiry); resend extends window; stale org auto-archives after 90 days
Step 1.4 wizard — send button✅ CompletePR #243: was permanently disabled due to trialEndDateSet pre-check; fixed with client-side override so button enables when other gates pass
Step 1.4 wizard — Copy Onboarding Link✅ CompletePR #243: "Copy Onboarding Link" button now available before invitation is sent
Step 1.4 wizard — Complete Setup CTA✅ CompletePR #243: "Complete Setup" CTA added for orgs already in pending_client_confirmation status
Client onboarding SPA — 3 steps✅ CompletePRs #267–271 (2026-05-10): Workspace Setup → Your h.work Team → Done; single URL /onboarding/start?token=…; no page reloads between steps
Step 1: Workspace Setup✅ CompleteEmail field as disabled input (not plain text); inline [input].h852.work slug picker; flat sorted timezone list with (GMT +X:00) City format; submit button surfaces specific validation errors on click
Step 2: Your h.work Team✅ CompleteRead-only specialist preview + AM email + AM name surfaced; Specialist monthly rate displayed with override/catalog source caption (PR #518 / #498 closed)
Step 3: Done✅ Complete"Continue to your Workspace" → /client/chat (auto-authenticated); welcome email sent
Onboarding progress bar✅ CompleteFull-bleed, equal-width segments, correct active/inactive colors
Idempotent re-visits✅ CompleteInvitation accepted status still allows org/specialist/slug/profile fetches; validateInvitationToken no longer 410s when org is active
Phase 2.1 — OTP + password + profile✅ CompleteEmail OTP verification; password set; name/title/phone fields (entry point preserved at /accept-invite)
Phase 2.2 — confirm company info + slug✅ CompleteSlug reserved atomically; immutable after confirmation; slug alias system for rebrands
Phase 2.3 — meet your specialist✅ CompleteRead-only specialist preview; team composition hidden from client
Phase 2.4 — channels setup (in onboarding)❌ RemovedChannels setup moved out of onboarding to post-onboard /client/settings/channels. Email + corporate-domain whitelist seeded automatically at org creation.
Phase 2.5 — invite teammates / billing (in onboarding)❌ RemovedBoth moved out of onboarding to /client/settings/team and /client/settings/billing post-onboard.
Phase 2.6 — completion✅ CompleteStatus → active; trial starts; welcome emails sent (no longer references "Invite your team" or "Set up billing"); invite token invalidated
Slug validation rules✅ CompleteFormat ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$; reserved words blocked; personal domains blocked; never recycled
Stale org auto-archive✅ CompleteStaleOrgService; 90-day window
Business context import (onboarding wizard)❌ Not builtUSER_STORIES C-O6 (P1 gap) — no upload or config UI for initial knowledge base

2a. Client Settings & Team Management

Routes: /client/settings/*. Old /portal/admin/* and /client/admin/* routes redirect here.

FeatureStatusNotes
Client settings route (/client/settings)✅ CompleteRedirects to /client/settings/profile; replaces /portal/admin/*
Profile settings (/client/settings/profile)✅ CompleteName, avatar, phone, title, bio; all roles
Team view (/client/settings/team)✅ CompleteAll roles can view member list; GET /admin/members
Self-service team invites✅ CompletePOST /admin/members/invite; accessible to org_admin (admin/owner orgRole)
Remove team member✅ CompleteDELETE /orgs/:orgId/members/:userId; Admin/Owner only via OrgRolesGuard("admin")
Role management (change member roles)✅ CompletePATCH /admin/members/:id/role; Admin/Owner can change roles up to Admin level
Workspace roles (Owner/Admin/Billing/Member)✅ CompleteOrgMembership.orgRole; encoded in JWT; 4-tier model fully wired in UI and API
Transfer ownership✅ CompletePOST /orgs/:orgId/transfer-ownership; Owner-only; guard enforced server-side
Leave workspace (self-service)⚠️ PartialUI stub exists in /client/settings/team; self-removal API pending — issue #148
Channel settings (/client/settings/channels)✅ CompleteAdmin/Owner only; channel connect/manage UI
Billing settings (/client/settings/billing)✅ CompleteAdmin, Owner, Billing roles; plan, usage, payment method

3. Client Portal Chat

FeatureStatusNotes
Portal chat UI✅ CompletePortalChat.tsx (1,473 lines); conversation list sidebar + message thread
Create conversation✅ CompletePOST /conversations; agent name auto-assigned from curated name pool
Send message✅ CompletePOST /conversations/:id/messages; validated at org boundary
Receive agent response✅ CompleteReal Hermes runtime wired behind /v1/chat (PR #194); SSE endpoint exists; single-event response acceptable for MVP. Token-by-token streaming is P2 (issue #248). Socket.io gateway wired; client-side polling fallback implemented.
Conversation history✅ CompleteGET /conversations (list) + GET /conversations/:id (thread with paginated messages)
Keyword search✅ CompleteGET /conversations/search?q=&orgId=; full-text via pg_trgm
Channel badge✅ CompleteChannelBadge.tsx; shows web / email / WhatsApp / Slack / Telegram with icon + color
Specialist persona display✅ CompleteClient sees Specialist name, avatar, and full profile in the /client/chat dashboard right-panel carousel; expert identity never exposed. GET /client/specialists returns assigned Specialist personas.
Trial banner✅ CompleteTrialBanner shown to client users; GET /client/trial-info
Internal notes hidden from client✅ CompleteisInternal filter on message list; client role excluded via EXPERT_ROLES check
Read-only status badge (client)✅ CompleteClient sees status as read-only badge; cannot change status
Client-facing approval UI (high-stakes actions)❌ Not built (P2 — deferred)USER_STORIES C-W8. Demoted from P0 → P2 on 2026-05-23: MVP handles approval manually via the conversation channel since most work is done through communication.
AI vs Expert handling label✅ CompleteInline badge in client message view: "AI" (blue) for agent messages, "Human review" (purple) for expert-reviewed messages; experts retain their existing "Expert" label
Agentic task status tracking⚠️ PartialAgenticTask entity + API exist; client-facing task progress view not confirmed

4. Expert Workspace

FeatureStatusNotes
Expert queue list✅ Complete/workspace/queue; ExpertQueueService; sorted by risk; QueueItem component
Filter by status✅ CompletePending / in_progress / resolved filter; listPending() service method
Filter by org✅ CompleteOrg filter in queue service
Full conversation thread view✅ CompleteTicketDetail.tsx; CustomerThread component; all messages shown
AI suggestion + confidence score✅ CompletegetSuggestion() in expert-queue.service; ConfidenceBar.tsx renders 0–100 bar with color coding
Risk badges✅ CompleteColor-coded risk level: low (green), medium (yellow), high (orange), critical (red)
Accept draft (approve & send)✅ Completerespond() in expert-queue.service; marks resolved
Edit draft before sending✅ CompleteEditable textarea in TicketDetail; edit + send action
Write from scratch✅ CompleteExpert can clear draft and write manually
Send as specialist persona✅ CompleteResponse attributed to specialist; expert identity not exposed to client
Resolve ticket✅ Completeresolve() endpoint; status → resolved
Internal notes✅ CompleteNote toggle in PortalChat (expert-only); is_internal + sender_id on messages; addInternalNote() API call
Conversation status dropdown✅ CompleteStatus <select> (pending/awaiting_client/resolved/snoozed) in PortalChat for expert role; PATCH /conversations/:id/status. No archived state — it was collapsed into resolved (#2002). See conversation-status-lifecycle.
Assign to self✅ Complete"Assign to me" button in PortalChat; PATCH /conversations/:id/assign; assigned_expert_id on Conversation
Defer ticket✅ Complete (backend)defer() sets deferred_until; frontend defer UI not yet confirmed
Reassign queue item⚠️ Disabledreassign() backend exists; pool model removed 2026-05-03; frontend reassign UI disabled pending new direct-assignment model
Queue auto-refresh✅ CompletePolling implemented in workspace queue page
Agentic task plan review✅ CompleteAgenticTask entity; GET /agentic/tasks; approve/reject per step
Agentic task step approve✅ CompletePOST /agentic/tasks/:id/steps/:stepId/approve
Agentic task step reject✅ CompletePOST /agentic/tasks/:id/steps/:stepId/reject with feedback
Tool execution (agentic)⚠️ PartialPlan/checkpoint/approval loop landed via #696 (closed #172). Tool dispatch flows through api/src/agent-api/tool-registry.ts (PR #399); some tools (Shopify, Amazon) execute live, Nango-backed tools (QuickBooks, Xero) are registered but stubs; Jumio is skeleton-only (#230).
Expert profile + assignment UI❌ Not builtUSER_STORIES E-O2, E-O3 (P1 gap) — skill tags in User entity but no profile UI. Pool-based assignment is gone (ADR-007); assignment now via expert_access.
Correction categorization UI⚠️ PartialCorrection entity + POST /learning/corrections exist; UI for selecting error type not confirmed
Push notifications (critical escalations)❌ Not builtUSER_STORIES E-P3 (P0 gap)
Native mobile app❌ Not builtUSER_STORIES E-P4 (P1 gap)

5. Conversation Management

FeatureStatusNotes
Conversation status✅ CompletePATCH /conversations/:id/status; pending / awaiting_client / resolved / snoozed (no archived — collapsed into resolved, #2002). See conversation-status-lifecycle.
Snooze with resurface time✅ Completesnooze_until column on Conversation (migration 034); snoozeUntil in entity and frontend interface
Specialist assignment✅ CompletePATCH /conversations/:id/assign; assigned_expert_id on Conversation
Internal notes✅ Completeis_internal + sender_id on Message (migration 034); note toggle; filtered server-side in conversations.service.tscanSeeInternal role check in query builder excludes is_internal=true rows for client roles
Full-text search✅ Completepg_trgm index; GET /conversations/search
Multi-tenant scoping✅ CompleteAll queries org-scoped; RLS enforced at DB layer
Audit trail✅ CompleteAuditLog entity; AuditService records every significant action
SLA deadline tracking✅ Completesla_deadline on ExpertQueueItem (migration 012-SlaDeadline)
SLA performance dashboard (client)❌ Not builtUSER_STORIES C-V5 (P1 gap)

6. Channel Adapters

ChannelStatusNotes
Web / portal✅ CompleteDirect portal chat; POST /conversations/:id/messages
CORS fix (Vercel preview)✅ CompletePR #244: Vercel preview deployments (dynamic *-humanityprotocol.vercel.app URLs) now allowed in non-production environments via regex pattern
Email (Gmail API inbound polling)✅ Complete 2026-06-05Primary inbound path. Gmail API polling via cron (*/30 * * * * * on Railway dev) shipped via PR #1722 (closes #1060). Uses ONE Google Workspace service account with domain-wide delegation to read each Specialist's mailbox (bob@h.work); no per-Specialist OAuth tokens.
Email (Gmail API outbound via DWD)✅ Complete 2026-06-05Primary outbound path. Replies sent from the Specialist's gsuite mailbox via DWD impersonation (PR #1722). Specialist mailboxes are provisioned by organizations.service.ts enqueuing WORKSPACE_JOB_CREATE on Specialist↔Org assignment; the processor calls Admin SDK users.insert.
Email (Cloudflare inbound)⚠️ Fallback during 2-week soakCloudflare email worker (deployed 2026-05-10) is fallback while we soak the Gmail polling path. Routes @dev.h852.work → dev API and @h852.work → staging API. Worker sends base64 RFC822; API parses with mailparser at POST /channels/email/inbound; HMAC-SHA256 verify via CLOUDFLARE_EMAIL_WEBHOOK_SECRET. Decommission tracked in #1440/#1441 (still open).
Email (Resend outbound)✅ Transactional onlyNo longer the Specialist conversation channel. Resend is reserved for invites/onboarding/transactional email via email/email.service.ts. Auto-replies use verified email domain (not dev.* subdomain). Templates redesigned 2026-05-10.
WhatsApp (Twilio)✅ CompleteHMAC-SHA1 signature verification; number pool (≈20 numbers); whitelist enforcement; POST /channels/whatsapp/inbound. 2026-05-10: heldForReview respected (no auto-reply when expert review pending); media/attachments passed through to sendMessage (media-only inbound gets [Media message] placeholder); reply truncated to 4096 chars before Twilio send; boot guard logs warning when TWILIO_AUTH_TOKEN is missing; deactivated-org check before creating any conversation.
Slack⚠️ PartialAdapter implemented (HMAC-SHA256 verify; app_mention + message events); Slack org resolution wired (resolveSlackOrgId maps team_id/enterprise_id/app_id/channel_id → org via stored Slack integration credentials); still blocked on live Slack credentials (BLK-004)
Telegram✅ CompletePer-org tokens in integration_credentials; TelegramModule (fix/issue7)
Microsoft Teams❌ StubBot Framework webhook; JWT validation stub (BLK-032 — needs credentials)
WeChat❌ StubOfficial Account webhook XML parsing not done (BLK-042, P3)
Channel health API✅ CompleteGET /orgs/:orgId/channels/status; GET /orgs/:orgId/channels/webhook-urls
Integration credentials (encrypted)✅ CompleteAES-256-GCM encryption; integration_credentials table; CRUD at /orgs/:orgId/integrations
Circuit breaker✅ CompleteImplemented for Slack, Email, Teams error handling
Outbound org webhooks🔮 FutureSigned payloads; per-org subscriptions — in FUTURE_REQUIREMENTS.md

6a. Third-Party Integrations (Nango + bespoke)

2026-05-22 model: Nango is the integration infrastructure platform — covers the 700+ provider catalog (QuickBooks, Xero, HubSpot, Salesforce, etc.) via per-Org OAuth Connect Sessions. Bespoke services (Jumio, Shopify, Amazon SP-API) remain for vendors not in Nango or where deeper integration is required. Agent tool dispatch routes both via a single static registry. See PR #399.

FeatureStatusNotes
Self-hosted Nango server (dev)✅ CompletePR #403 / #228. Railway-deployed; /health and /connection both 200 with dev secret. Public URL + API env wiring documented.
Self-hosted Nango server (staging/prod)❌ Not builtTracked under #228 follow-on; needs staging + prod Railway projects + secret rotation procedure.
NangoModule (NestJS)✅ CompletePR #399 / #229. api/src/integrations/nango/{nango.module,nango.service,nango.client}.ts.
Nango Connect Session (OAuth handoff)✅ Completecfd05d76 / #421. createConnectSession issues per-Org session tokens; getConnection / listConnections / deleteConnection wired. buildNangoConnectionId(orgSlug, provider) is the connection-ID convention.
Nango connection revoke✅ Completebf0c78b0. Deleted Nango connections treated as revoked; legacy local credential rows cleaned via e67ea995.
Static agent tool registry✅ CompletePR #399. api/src/agent-api/tool-registry.ts; GET /v1/agent-api/tools/:toolName; AgentToolKind = "bespoke" | "nango".
SA Nango catalog autocomplete + link-out✅ Complete#423. /ops/clients/:id integrations panel surfaces tool kind badge and links to Nango catalog.
QuickBooks (Nango)⚠️ Registered, not wiredquickbooks_query tool descriptor in registry with kind: "nango"; backend action handler + agent prompt wiring deferred. Supersedes the stub row in #176.
Xero (Nango)⚠️ Registered, not wiredxero_query tool descriptor in registry with kind: "nango"; same status as QuickBooks.
HKEX (Nango)❌ Not built#176. Not in Nango catalog; needs bespoke or alt provider.
Shopify✅ Complete (bespoke)Pre-existing bespoke proxy; remains bespoke per #399 — deeper integration than Nango exposes.
Amazon SP-API✅ Complete (bespoke)Pre-existing bespoke proxy; remains bespoke per #399.
Jumio (bespoke KYC)⚠️ Skeleton only#230 — assignee Dankovk. api/src/integrations/jumio/{jumio.module,jumio.service,jumio.client}.ts exist (122 LOC); jumio_lookup tool descriptor registered; JumioService.lookup() throws NotFoundException until per-Org IntegrationCredential row exists. Blocker: no Jumio sandbox account / API key on file — procurement-side, not engineering. OQ-202 (per-Org vs HP-shared key) still open.
Per-Org integration credentials encryption✅ Complete#551 / PR #570. integration_credentials.encrypted_config now AES-256-GCM at rest via decryptConfig() helper; boot guard refuses prod without CREDENTIALS_ENCRYPTION_KEY.
Tool execution audit (per call)✅ CompletePR #399. Audit row emitted on every tool dispatch with model, provider, masked params; Jumio path uses buildJumioAuditPayload (PII-safe).
Tool execution metrics (success/failure per tool per org)❌ Not built#176 work item; deferred until P0s clear.
Integration health monitoring + credential rotation❌ Not built#176 work item; rotation procedure documented in Jumio PRD (#230).

7. Specialist Management

FeatureStatusNotes
AM creates specialist✅ Completeadmin-specialists.controller.ts; Specialist entity with name, avatar, routing email, skill tags
AM assigns specialist to org✅ CompleteOrgSpecialistAssignment entity; confidence_threshold per specialist per org; isPrimary flag
Multiple specialists per org✅ CompleteMigration 024; multiple assignments supported
Specialist change request✅ CompleteSpecialistChangeRequest entity (pending/fulfilled/declined)
Specialist routing email✅ Completebob@h.work style dedicated routing address
Email outbound via Gmail Send (DWD service-account impersonation)✅ CompletePhase 2 ADR-0002 originally shipped per-OSA oauth_refresh_token_encrypted (#1065 / #1079); inbound dual-read (#1093); outbound dispatch (#1095), all 2026-05-29. 2026-06-05 update (PR #1722): architecture moved to ONE Google Workspace service account with domain-wide delegation impersonating each Specialist's mailbox — no per-Specialist OAuth tokens. Cloudflare worker retained as inbound fallback during 2-week soak (#1440/#1441).
Named account lead assignment per org❌ Not builtUSER_STORIES SA-C9 (P1 gap) — no UI to set named AM per org

8. Notifications & Real-Time

FeatureStatusNotes
WebSocket gateway (Socket.io)✅ CompleteNotificationsModule; rooms: experts, org:<id>, pool:<id>; events: expert_queue_item_added, queue_item_resolved, agent_message_sent
SSE streaming (agent responses)✅ CompletePOST /conversations/:id/messages/stream; server-sent events
In-app notifications (AppNotification)✅ CompleteAppNotification REST + Socket.io delivery rail shipped via #915 (2026-05-27); item 1 of #170's 5-item scope. Push delivery / email delivery / prefs UI still pending under #170.
Client-side polling✅ CompleteFrontend polls for new messages as fallback
Push notifications (mobile / browser)❌ Not builtUSER_STORIES E-P3 (P0 gap) — pending under #170 follow-ups

9. Analytics & Reporting

FeatureStatusNotes
Analytics page (superadmin)✅ CompleteAnalyticsModule + controller; live data from DB: queue status, top request types, pool resolution times, auto-resolve rate, active experts. SA-B4 P0 gap resolved.
Client dashboard (summary)⚠️ PartialDashboard page exists; quota data live via GET /orgs/:orgId/quota; conversation counts from live API; volume chart mock
Conversation search✅ CompleteFull-text via pg_trgm
Correction stats⚠️ PartialLearningService stores corrections; no stats aggregation endpoint or UI confirmed
Expert leverage ratio✅ CompleteSA-E4 — /ops/analytics Expert leverage section + GET /ops/analytics/expert-leverage (SuperAdmin); from expert_access (ADR-007). PR #3199
Per-org cost tracking⚠️ PartialSA-B5 — per-org LLM cost + Expert workload on /ops/billing?org=<id> (PRs #3195/#3200). Dollarized labour + infra cost → gross margin still pending (#3196)
Autonomous handling rate✅ Completeauto_responded flag on Conversation; autoResolveRate surfaced in analytics API and superadmin analytics page
SLA performance dashboard❌ Not builtUSER_STORIES C-V5 (P1 gap)

10. Billing & Subscriptions

2026-05-29 rail flip: Lago — self-hosted Lago (Railway for dev; AWS for staging + prod — AWS bring-up tracked in #1287) — is the canonical billing rail — Orb was abandoned. Invoicing is per-Specialist monthly rate (sum of assigned Specialists' resolved rates × period), not plan-tier subscription. LagoProvider shipped via #1069; dual pricing strategy (plan_per_rate default, plan_overrides premium) via #1105; client invoice surface via #1155; ops billing UI via #1155 (note: #1165 was the originally-cited Phase-8 PR but was closed-unmerged and superseded by #1155); Phase-7 legacy fixed-plan teardown via #1016. Direct Stripe lives only inside Lago's PSP config. See docs/features/billing.md and docs/decisions/2026-05-29-lago-pricing-strategy.md.

FeatureStatusNotes
Per-Specialist rate schema✅ Completespecialists.monthly_rate_config (catalog default; 364 roles populated in dev) + org_specialist_assignments.monthly_rate_config (AM override with optional rate_effective_from / rate_effective_until window)
AM rate override (per-org)✅ CompletePR #518 / #498 closed; override wins when its window is active, falls back to catalog default, then null
Onboarding rate display (client side)✅ CompletePR #518: GET /onboarding/:token/specialist returns monthlyRate: { amount, currency, source: 'override' | 'specialist' } | null; rendered via Intl.NumberFormat in Step 2 of 3-step SPA
Lago provider (canonical invoice rail)✅ Complete#1069 LagoProvider (2026-05-29); #1105 dual-strategy (LAGO_PRICING_STRATEGY=plan_per_rate default; plan_overrides requires Lago premium license). Self-hosted Lago — Railway for dev; AWS for staging + prod (AWS bring-up tracked in #1287). See docs/superpowers/specs/2026-05-26-billing-provider-leveraged-design.md §Operational note.
Lago client invoice surface✅ Complete#1155 wired /client/settings/billing to Lago Manage Billing portal + per-Specialist subscriptions list (2026-05-31).
Lago ops billing UI (Phase 8)✅ Complete#1155 (#1165 was closed-unmerged, superseded by #1155): /ops/billing rebuilt on Lago — subscription DataTable, sync-failure alert, Retry sync; nav opened from saOnly → AM + SuperAdmin (2026-05-31).
Phase 7 legacy teardown✅ Complete#1016 removed legacy fixed-plan Stripe path from BillingController (2026-05-28).
Mid-month proration / assignment-event ledger✅ Delegated to LagoLago handles calendar-day proration natively on its subscription engine; no separate ledger needed. Earlier #514 obsoleted by rail flip.
Direct Stripe integration🗑️ RemovedLago wraps Stripe as its PSP. Legacy STRIPE_SECRET_KEY env retained only because Lago needs it; standalone Stripe code removed via #1016.
Request Finance disabled✅ CompletePR #219: ENABLE_REQUEST_FINANCE flag defaults to false; crypto payment path disabled unless explicitly re-enabled; RF code preserved but inactive
Message quota tracking🔁 Re-scoped — partial cleanupGET /orgs/:orgId/quota; OrgThrottlerGuard. No longer a billing construct — abuse protection only. Partial cleanup landed via PR #531 2026-05-23 (global APP_GUARD registration + /auth rate-limit decorator removed). Note: throttler was re-registered in shadow mode via #812 + webhook throttle #839; see ADR-021.
Client invoice view UI rewrite✅ Wired/client/settings/billing shows consolidated invoices + per-Specialist line items (Lago), shipped via #1155; JSON-safe serialization #1180. (#528)
Client payment collection (add card)✅ WiredAdd payment method button → GET /client/billing/checkout-url → Lago Stripe Checkout URL (setup-mode); ensureCustomer eagerly links the customer to the org's Stripe provider (LAGO_STRIPE_PAYMENT_PROVIDER_CODE); Lago auto-charges finalized invoices off-session. (#1268)
Trial period✅ Complete30-day default; trialStartedAt on Organization; TrialBanner in client portal
Trial state on billing page✅ Complete2026-05-10 (commit 8f83779, issue #187): orgs without an active subscription now show "Trial — N days remaining" / "Trial expired" instead of "Free plan"
Plan + usage page (client)✅ CompleteLago-backed (#1155). Per-Specialist line itemization shipped.
Invoice history / download✅ CompleteLago Manage Billing portal handles invoice history + PDF download (#1155).
VAT / tax ID⚠️ PartialVAT field collected; Lago tax handling wiring still pending.
All-org subscriptions table (superadmin)✅ Complete/ops/billing rebuilt on Lago in #1155 (#1165 was closed-unmerged and superseded by #1155): stat cards (total/active/sync_failed), subscription DataTable, Retry sync.

11. API Webhooks (Outbound)

FeatureStatusNotes
Inbound webhooks (channels)✅ CompleteSlack, Email, WhatsApp, Telegram all receive inbound webhooks
Outbound org-level webhooks🔮 FutureSigned payloads; per-org subscriptions — spec in FUTURE_REQUIREMENTS.md; not started
Webhook URL helper✅ CompleteGET /orgs/:orgId/channels/webhook-urls returns per-channel webhook URLs for client to configure

12. Mobile

FeatureStatusNotes
Responsive web (PWA)✅ CompleteServiceWorkerRegistrar in root layout; responsive Tailwind styles; manifest.json present with correct start_url (/workspace/queue) and shortcut URLs
Native mobile app (expert)❌ Not builtUSER_STORIES E-P4 (P1 gap)
Push notifications❌ Not builtUSER_STORIES E-P3 (P0 gap)

13. Knowledge Base & AI Training

FeatureStatusNotes
Correction capture✅ CompleteCorrection entity (factual_error, tone, missing_step, wrong_action); POST /learning/corrections; LearningService
Correction categorization UI⚠️ PartialError-type enum in entity; UI for selecting category not confirmed in workspace
Vector memory (agent)⚠️ DeprecatedRetrieval now lives via Haystack (api/src/haystack/*); agent_memories table is retained but unused. Issue #172 (agentic mode tool execution / checkpointing) was closed via PR #696 — no longer the reactivation rationale.
KB ingestion from corrections🔮 FutureRF-0015 — corrections refine the org KB through a downstream LearningService consumer
KB upload (business context)✅ CompleteAPI and onboarding upload endpoint added via Haystack; client KB management UI delivered by humanwork#297
Agent memory visibility (client)✅ CompleteUSER_STORIES C-T4 delivered by humanwork#297: /client/admin/knowledge-base supports list, upload, search, delete, detail chunks, and parse-status live updates

14. Platform Ops & Admin

FeatureStatusNotes
Health dashboard✅ Complete/ops/health (SA only); HealthController; API + DB + Redis + channel adapter status
Prometheus metrics✅ CompleteMetricsService + MetricsController; /metrics endpoint
Audit log viewer✅ CompleteAuditLog entity; AuditLogController; /ops/audit (SA only — #1238/#1298). Docs: docs/features/audit-log.md
Expert pool management (create/add member)❌ RemovedExpert pools removed 2026-05-03. Expert ↔ data access is now via expert_access (ADR-007). The legacy org_experts table is deprecated 2026-05-22 and dropped in #540 after soak.
Impersonation (superadmin)✅ CompleteImpersonationService; audit-logged; superadmin only
Stale org auto-archive✅ CompleteStaleOrgService; 90-day threshold
Tool permission management (API)✅ CompleteToolPermission entity; PUT /orgs/:orgId/tool-permissions/:toolName
Tool permission management (UI)❌ Not builtUSER_STORIES SA-P5 (P1 gap) — API exists; no frontend
Per-org channel adapter health (superadmin UI)❌ Not builtUSER_STORIES SA-P4 (P1 gap) — API exists; not surfaced in superadmin UI
Named account lead per org (UI)❌ Not builtUSER_STORIES SA-C9 (P1 gap)
Expert leverage ratio analytics✅ CompleteSA-E4 — /ops/analytics Expert leverage (clients & Specialist instances per Expert); from expert_access. PR #3199
Humanity Protocol credential verification⚠️ Stub/users/:id/hp-verify endpoint is a stub; integration not functional

15. AI Agent Runtime

FeatureStatusNotes
Hermes CLI runtime (chat)✅ Completeagent/hermes_client.py; shells out to hermes chat CLI; session mapping: Humanwork conv IDs → Hermes session IDs via cached mapping (first turn creates; subsequent turns resume)
Agent API contract v1✅ Complete/v1/chat, /v1/chat/stream wired to real Hermes runtime; agent/routers/chat.py
Agent-service shared secret auth✅ CompleteX-Agent-Secret header; middleware/auth.py uses hmac.compare_digest; permissive in dev when env var unset
Agent JWT guard (NestJS)✅ CompleteAgentTokenGuard validates agent-scoped JWT tokens on agent-api routes
Corrections pipeline✅ Complete/v1/corrections on agent forwards to NestJS LearningService via corrections_client.py
Chat streaming (true SSE)⚠️ Partial/v1/chat/stream endpoint exists and returns SSE-framed response; currently single-event. Current Hermes docs/source expose stable token streaming through config/TUI gateway message.delta, not a simple hermes chat --stream flag for the quiet subprocess path.
Agentic task runtime✅ Migrated to RIG (2026-05-25, #696)The legacy /v1/tasks/* endpoints on the agent service were removed in #696 (RIG hard-cut) and now return HTTP 410 (LEGACY_TASK_AUTHORITY_REMOVED). The Platform /agentic/tasks/* HTTP surface remains but is now backed by the RIG runtime control plane (docs/architecture/RIG_HARD_CUT_RUNTIME_PORT_PLAN.md). LangGraph rollback and /graph/invoke remain removed.
RAG / memory retrieval⚠️ PartialPlatform-owned Haystack retrieval wired for /v1/agent-api/context and conversation history injection; dev=Railway, staging+prod=AWS ECS Fargate (humanwork-rag Cloud Map service) per ADR-024. pgvector storage is the active vector store.
POST-MVP agent surfaces (config/knowledge)🔮 Future/v1/configure and /v1/knowledge return 501 deferred; explicit post-MVP boundary
HMAC signature crash fix✅ CompletePR #206: verifyHmac now returns HTTP 401 instead of throwing RangeError on wrong-length signature
Pagination fix (has_more)✅ CompletePR #206: has_more in getConversationMessages now correctly compares filtered count
Timing-safe learning token check✅ CompletePR #206: assertPlatformToken in learning.controller.ts now uses timing-safe comparison
Prompt injection false-positive fix✅ CompletePR #244: SECURITY_PREFIX rule 3 rewritten — addressing agent by assigned persona name is now correctly treated as normal usage, not injection
Specialist persona header injection fix✅ CompletePR #244: NestJS no longer passes bare specialistSystemPrompt as full role template; agent now correctly merges persona into role template
Expert respond() real-time emit✅ CompletePR #244: ExpertQueueService.respond() now emits agent_message_sent WebSocket event so client sees expert reply in real-time without waiting for 8s poll

16. Per-Org Dogfood (acmefinancial)

2026-06-04 framing: Acme Financial is the first dogfood org. Eleanora Voss is the assigned KYC Specialist (per scripts/seed-dev.sh:429; eleanora@h852.work on dev). The prior "Bob" label was retired when the canonical seed was updated; references in older PR descriptions and ADRs may still say Bob — these are historical and have been re-aligned in docs/example-flow.md, docs/USER_OPERATIONS_MANUAL.md, and the MVP_P0_RUNBOOK. This section tracks runtime state for the Acme/Eleanora/KYC stack so contributors don't continue work against the stale generic-ecommerce or Bob-era frame. Sourced from #239 work items.

ComponentStatusNotes
Acme org seed (acmefinancial)✅ CompleteSeeded in dev; amy@acmefinancial.com (client), Eleanora Voss assigned as primary Specialist.
Eleanora Voss Specialist persona✅ CompleteCatalog entry + routing email (eleanora@h852.work); persona prompt merged via PR #244 (no more bare-prompt regression).
KYC role template (kyc_ops.txt)✅ Completeagent/prompts/kyc_ops.txt declares jumio_lookup tool with customer_id + lookup_type (basic|enhanced|sanctions). Verified by agent/evals/test_kyc_role.py.
SOUL + skills for Acme✅ Completeorgs/acmefinancial/skills/kyc-ops/{jumio-lookup,sanctions-check,escalation-draft}/SKILL.md present.
jumio_lookup tool descriptor✅ CompleteRegistered in api/src/agent-api/tool-registry.ts; dispatch wired via PR #399.
jumio_lookup end-to-end❌ Not shippedBespoke Jumio backend (#230) skeleton-only; blocked on Jumio sandbox account. Eval test_kyc_role.py currently asserts the graceful "Jumio not_implemented → escalate" branch only.
Per-Org sandboxed agent runtime✅ Complete via ECS provisioner#362 Phase A (per-org Hermes session isolation) shipped earlier; Phase B Railway-per-org provisioner landed 2026-05-22 via PR #589 and was subsequently decommissioned via PR #1584 / #1450 / ADR-028. Only supported agent runtimes are now shared_railway and ecs_per_org.
HP credential verification (Eleanora's KYC turn)⚠️ Stub/users/:id/hp-verify endpoint still a stub (see §14); separate from Jumio path.
Acme channel adapters⚠️ PartialEmail (Cloudflare inbound + Resend outbound) and WhatsApp (Twilio) confirmed live; Slack landed 2026-05-26 via #816 (Connect OAuth) + #1219 (per-org signing_secret) — see MVP_P0_RUNBOOK v2.0.
End-to-end smoke (F1 in #239)❌ Not builtLive smoke covering Amy → Eleanora → Expert review → outbound reply is the M1.5 closing-out gate.

Gap Summary

PriorityGap countExamples
P0 gaps1Push notifications (E-P3). Notes: per-Org sandboxed agent runtime (#362) shipped 2026-05-22 via PR #589; the Railway-per-org code path was subsequently decommissioned in PR #1584 / #1450 per ADR-028 (only shared_railway and ecs_per_org remain). Client approval UI (C-W8) demoted from P0 → P2 on 2026-05-23 — manual approval via chat for MVP.
P1 gaps9Jumio bespoke (#230 — blocked on sandbox account), business context import, SLA dashboard, expert profile UI, named account lead, tool permission UI, per-org channel health UI, HP credential verification, correction categorization UI, defer/reassign frontend. (Expert leverage ratio shipped 2026-06-24 via #3199.)
P2 gaps5Nango QuickBooks/Xero wiring (#176), invoice history, per-org gross-margin (partial: LLM cost + Expert workload shipped via PRs #3195/#3200; dollarized labour+infra cost pending #3196), inline ticket discussion, tool execution metrics
Future2Outbound webhooks, KB ingestion from corrections

Status key: ✅ Complete | ⚠️ Partial | ❌ Not built | 🔮 Future (in FUTURE_REQUIREMENTS.md)


Workstream Notes & Cleanup Targets

Absorbed from the retired docs/technical-scopes.md on 2026-05-25. Only items still accurate against current code are kept; stale claims (LangGraph 4-node pipeline, R2 zero-impl, AgentMemory as live, Stripe as canonical billing, api/src/collab|tickets|seed|integrations/shopee, api/src/scheduler/ as unregistered, agent/placeholder/ as deletable) have been dropped.

Directory ownership (for parallel work)

Each scope below has roughly exclusive directory ownership; shared files require PR coordination.

AreaPrimary directoriesCross-ref §§
Platform Coreapi/src/{auth,common,admin,audit,users,health,config,database}§1, §14
Conversation & HITLapi/src/{conversations,expert-queue,notifications,learning,customers,specialists}§3, §4, §5, §8
Channelsapi/src/{channels,email} (incl. channels/whatsapp/, channels/telegram/, channels/teams/)§6
Billing & Onboardingapi/src/{billing,onboarding,organizations}§2, §10
Integrationsapi/src/integrations/ (shopify, amazon, jumio, nango, credentials), api/src/tools/§6a
AI Agentagent/ (entire dir), api/src/{agentic,agents,agent-api}, api/src/haystack/, api/src/kb/§15, §16
Client Portal FEfrontend/src/app/client/, frontend/src/app/onboarding/, frontend/src/components/client/§3
Internal Surfaces FEfrontend/src/app/{workspace,ops}/, frontend/src/components/{internal,analytics}/§4, §9, §14
Frontend Platformfrontend/src/{components/ui,components/shared,contexts,hooks,lib,__tests__}, frontend/src/app/login/
Analyticsapi/src/analytics/, frontend/src/components/analytics/§9
Infra & DevOpsk8s/, .github/workflows/, e2e/, scripts/, docker-compose.yml

Coordination-required shared files:

  • api/src/common/entities.ts — all TypeORM entities. Touch via PR review.
  • frontend/src/lib/api.ts — comprehensive API client (~3.2K lines). Imported by every FE scope.
  • frontend/src/contexts/AuthContext.tsx — JWT parsing + role-based redirect; FE-wide.
  • api/migrations/ — append-only, sequentially numbered. Coordinate the next number in Slack before opening a PR.

Cleanup targets (verified 2026-05-25)

Real dead-code targets that still exist on disk:

TargetPathActionNotes
Legacy /am/* sub-pagesfrontend/src/app/am/DeleteRoot-level redirect to /ops/* already in place.
Legacy /superadmin/* sub-pagesfrontend/src/app/superadmin/DeleteRedirects to /ops/* already in place.
Orphan top-level routesfrontend/src/app/{dashboard,analytics,integrations,queue}/DeleteNot linked from current nav; no role redirect lands here.
Duplicate setup routefrontend/src/app/ops/clients/[id]/setup/step2/DeleteKeep step-2/.
Demo backdoorfrontend/src/lib/api.ts (demo login bypass branch)Remove before launchConfirmed P0 blocker in mvp-launch-checklist.md.
Refactor channels.controller.tsapi/src/channels/channels.controller.ts (~2.1K LOC monolith)Split per channel adapterTracked as part of channels follow-up.

Previously listed but already deleted (do not re-add to cleanup lists): api/src/collab/, api/src/tickets/, api/src/seed/, api/src/integrations/shopee/. api/src/scheduler/ is NOT dead — it is wired into health.module.ts and expert-queue.module.ts. agent/placeholder/ is retained as a deliberate local-dev fallback (see agent/placeholder/README.md); do not delete without coordinating with the agent team.

Suggested team groupings

TeamPrimary scopesPrimary skills
Platform Core§1, §5, §14NestJS, TypeORM, PostgreSQL, WebSocket
Channels§6Twilio, Slack/Teams APIs, Cloudflare workers
Commercial§10, §9 analyticsLago billing (per-Specialist monthly), onboarding UX, dashboards
Integrations§6aOAuth, Nango, Shopify/Amazon, credential mgmt
Intelligence§15, §13Python, Hermes CLI, GPT-4o, pgvector, Haystack
Frontend§3, §4, FE platformNext.js 16, React 19, CSS, testing
Infrastructureinfra & DevOpsK8s, GitHub Actions, R2, Railway, Playwright

Collision-avoidance rules

  1. Each scope has effective exclusive directory ownership. If your change crosses into another scope's directory, tag that scope's owner on the PR.
  2. The two shared FE files (lib/api.ts, AuthContext.tsx) and the shared entities file (common/entities.ts) require PR review from affected scope owners.
  3. Migrations are append-only and sequentially numbered — coordinate the next number before authoring it.
  4. The agent/ service is wholly owned by the Intelligence team. Other scopes that need agent changes provide the NestJS-side API surface (api/src/agent-api/); the Intelligence team wires the agent side.

Schema Changes (2026-05-03 audit)

  • expert_pools and pool_memberships tables removed — Expert ↔ data access is now via expert_access (ADR-007). The earlier intermediate org_experts table (2026-05-03 → 2026-05-22) is deprecated and removed in #540 after soak.
  • Organization.status consolidated to: pending_am_setup, pending_specialist_assignment, pending_client_confirmation, active, trial_ending, suspended, deactivated.
  • Organization.metadata JSONB column added for arbitrary fields without migrations.
  • email_audit_log table added for inbound/outbound email audit trail.
  • HWORK_DOMAIN env var replaces SPECIALIST_EMAIL_DOMAIN and NEXT_PUBLIC_APP_DOMAIN.