Implementation Status โ historical feature inventory
Not an architectural or build source of truth. This inventory was last comprehensively reviewed on 2026-06-24 and contains point-in-time feature notes. Executable code, migrations, tests, and the exact deployed commit are authoritative for what exists. Accepted ADRs are authoritative for intended architecture. For the managed Hermes path use ADR-046, its remediation ledger, and the machine contract.
A row below is useful navigation, not proof. Before relying on it, verify the linked controller/entity/component and the relevant test or live acceptance path. Do not implement a legacy runtime, prompt, review, polling, projection, R2/base64, or host-workspace shape merely because an older row describes it.
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.
| PR | Section | What |
|---|---|---|
| #1604 | ยง15 / Learning loop | New 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 briefs | environment_profiles โ client_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 / Resilience | OpenRouter 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, ยง16 | Decommission 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 / CI | dev โ 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 / domains | Domain canonicalization: h852.work = dev, h853.work = staging, h.work = prod. Sweep any older docs using stale subdomain names. |
| #1583 / #1506 / #1493 | ยง1 / auth | Cross-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 gateway | HERMES_TOOLSETS is now wired from the toolsManifest + tool-gateway client โ Specialist-scoped tool surfaces no longer rely on env-var allowlists. |
| #1432 | ยง6 / channels | Gmail Pub/Sub webhook for inbound email (closes #686). |
| #1526 + #1528 | ยง13 / KB | KB search endpoint for Expert workspace (backend) + KB search panel UI. |
| #1551 / #1433 | ยง10 / billing | Grace-period gating + /ops/billing surfacing for payment-failure states. |
| #1475 | ยง10 / billing | In-app notifications on payment failure. |
| #1508 | ยง11 / SLA | Per-org SLA config + Slack breach alerting. |
| #1530 / #1533 | ยง8 / Expert workspace | Customer history timeline (backend + FE). |
| #1549 / #1474 | ยง3 / client portal | Dedicated client notifications drawer. |
| #1083 | ยง14 / Tavus | Tavus expert-application interview integration fixes. |
| #1442 | ยง6 / channels | Email cutover rollback runbook. |
| #1498 | ยง6 / Slack | Slack OAuth install runbook. |
| #1577 | ยง17 / infra | terraform-apply is now workflow_dispatch-only โ no infra change applies on push. |
| #1510 | ยง1 / DEMO_MODE | Audit + CI guard preventing DEMO_MODE=true from leaking into a production deploy. |
| #1522 | ยง15 / RuntimeToolExecutor | Added order_lookup tool to the RuntimeToolExecutor surface. |
#1604 / ADR-026 caveat: The
correction_embeddingstable 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โ
| Feature | Status | Notes |
|---|---|---|
| Email + password login | โ Complete | POST /auth/login โ JWT; auth.service.ts |
| Email OTP (passwordless) | โ Complete | POST /auth/request-otp + POST /auth/verify-otp |
| Onboarding OTP (invite flow) | โ Complete | POST /auth/send-invite-otp + POST /auth/verify-invite-otp; single-use OTP per invite token |
| Demo login (DEMO_MODE) | โ Complete | POST /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 | โ Complete | RS256 JWT with sub, email, name, platformRole, orgMemberships[]; 7-day expiry |
| 2FA (TOTP) | โ Complete | TOTP via otplib; POST /auth/2fa/setup + POST /auth/2fa/verify; qrcode generation |
| Role-based routing (frontend) | โ Complete | getRoleRedirect() 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 | โ Complete | superadmin, account_manager, expert, ai_operator, org_admin, org_member, client_admin, client_member |
| Org memberships (owner/admin/member/billing) | โ Complete | OrgMembership entity; encoded in JWT |
| Row-level security (RLS) | โ Complete | PostgreSQL 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/*).
| Feature | Status | Notes |
|---|---|---|
| Phase 0 โ validation gate (AM-side) | โ Complete | GET /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) | โ Complete | Name, slug, industry, domains, email, website, country, timezone; real-time slug validation |
| Phase 1.2 โ assign specialists | โ Complete | Multi-specialist assignment with primary designation; no confidence/review delivery field; OrgSpecialistAssignment entity |
| Phase 1.3 โ AM profile | โ Complete | Global AM profile (shared across orgs) |
| Phase 1.4 โ send client invite | โ Complete | ClientInvite token (7-day expiry); resend extends window; stale org auto-archives after 90 days |
| Step 1.4 wizard โ send button | โ Complete | PR #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 | โ Complete | PR #243: "Copy Onboarding Link" button now available before invitation is sent |
| Step 1.4 wizard โ Complete Setup CTA | โ Complete | PR #243: "Complete Setup" CTA added for orgs already in pending_client_confirmation status |
| Client onboarding SPA โ 3 steps | โ Complete | PRs #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 | โ Complete | Email 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 | โ Complete | Read-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 | โ Complete | Full-bleed, equal-width segments, correct active/inactive colors |
| Idempotent re-visits | โ Complete | Invitation accepted status still allows org/specialist/slug/profile fetches; validateInvitationToken no longer 410s when org is active |
| Phase 2.1 โ OTP + password + profile | โ Complete | Email OTP verification; password set; name/title/phone fields (entry point preserved at /accept-invite) |
| Phase 2.2 โ confirm company info + slug | โ Complete | Slug reserved atomically; immutable after confirmation; slug alias system for rebrands |
| Phase 2.3 โ meet your specialist | โ Complete | Read-only specialist preview; team composition hidden from client |
| Phase 2.4 โ channels setup (in onboarding) | โ Removed | Channels 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) | โ Removed | Both moved out of onboarding to /client/settings/team and /client/settings/billing post-onboard. |
| Phase 2.6 โ completion | โ Complete | Status โ active; trial starts; welcome emails sent (no longer references "Invite your team" or "Set up billing"); invite token invalidated |
| Slug validation rules | โ Complete | Format ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$; reserved words blocked; personal domains blocked; never recycled |
| Stale org auto-archive | โ Complete | StaleOrgService; 90-day window |
| Business context import (onboarding wizard) | โ Not built | USER_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.
| Feature | Status | Notes |
|---|---|---|
Client settings route (/client/settings) | โ Complete | Redirects to /client/settings/profile; replaces /portal/admin/* |
Profile settings (/client/settings/profile) | โ Complete | Name, avatar, phone, title, bio; all roles |
Team view (/client/settings/team) | โ Complete | All roles can view member list; GET /admin/members |
| Self-service team invites | โ Complete | POST /admin/members/invite; accessible to org_admin (admin/owner orgRole) |
| Remove team member | โ Complete | DELETE /orgs/:orgId/members/:userId; Admin/Owner only via OrgRolesGuard("admin") |
| Role management (change member roles) | โ Complete | PATCH /admin/members/:id/role; Admin/Owner can change roles up to Admin level |
| Workspace roles (Owner/Admin/Billing/Member) | โ Complete | OrgMembership.orgRole; encoded in JWT; 4-tier model fully wired in UI and API |
| Transfer ownership | โ Complete | POST /orgs/:orgId/transfer-ownership; Owner-only; guard enforced server-side |
| Leave workspace (self-service) | โ ๏ธ Partial | UI stub exists in /client/settings/team; self-removal API pending โ issue #148 |
Channel settings (/client/settings/channels) | โ Complete | Admin/Owner only; channel connect/manage UI |
Billing settings (/client/settings/billing) | โ Complete | Admin, Owner, Billing roles; plan, usage, payment method |
3. Client Portal Chatโ
| Feature | Status | Notes |
|---|---|---|
| Portal chat UI | โ Complete | PortalChat.tsx (1,473 lines); conversation list sidebar + message thread |
| Create conversation | โ Complete | POST /conversations; agent name auto-assigned from curated name pool |
| Send message | โ Complete | POST /conversations/:id/messages; validated at org boundary |
| Receive Specialist response | โ Complete | Managed Hermes ACP returns the canonical reply for the existing SessionDB session; Socket.io delivers updates and clients perform one bounded refresh after reconnect. No fixed polling fallback or Expert release gate. |
| Conversation history | โ Complete | GET /conversations (list) + GET /conversations/:id (thread with paginated messages) |
| Keyword search | โ Complete | GET /conversations/search?q=&orgId=; full-text via pg_trgm |
| Channel badge | โ Complete | ChannelBadge.tsx; shows web / email / WhatsApp / Slack / Telegram with icon + color |
| Specialist persona display | โ Complete | Client 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 | โ Complete | TrialBanner shown to client users; GET /client/trial-info |
| Internal notes hidden from client | โ Complete | isInternal filter on message list; client role excluded via EXPERT_ROLES check |
| Read-only status badge (client) | โ Complete | Client 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. |
| Canonical sender identity | ๐ง ADR-046 remediation | Client-visible canonical replies retain the Specialist identity. Synthetic AI/Expert-review labels and Expert-edited projections are being removed; genuine later human corrections/follow-ups remain separately auditable. |
4. Expert Workspaceโ
| Feature | Status | Notes |
|---|---|---|
| Expert attention list | โ Complete | /workspace/queue; explicit human requests and genuine failures scoped by expert_access; ordinary successful deliveries create no item |
| Filter by status | โ Complete | Pending / in_progress / resolved filter; listPending() service method |
| Filter by org | โ Complete | Org filter in queue service |
| Full conversation thread view | โ Complete | TicketDetail.tsx; CustomerThread component; all messages shown |
| Canonical reply and failure evidence | ๐ง ADR-046 remediation | Exact Hermes locators identify canonical SessionDB rows. Confidence/risk/review response fields are being removed rather than retained as compatibility metadata; see the remediation ledger. |
| Correct delivered reply | โ Complete | Human correction rewrites the exact canonical locator and is audited |
| Write genuine follow-up | โ Complete | Expert can author an additional message without replacing the already-delivered Hermes reply |
| Send as Specialist persona | โ Complete | Genuine follow-up is attributed to the Specialist; Expert identity is not exposed to the client |
| Resolve ticket | โ Complete | resolve() endpoint; status โ resolved |
| Internal notes | โ Complete | Note toggle in PortalChat (expert-only); is_internal + sender_id on messages; addInternalNote() API call |
| Conversation status dropdown | โ Complete | Status <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 | โ ๏ธ Disabled | reassign() backend exists; pool model removed 2026-05-03; frontend reassign UI disabled pending new direct-assignment model |
| Queue refresh | ๐ง ADR-046 remediation | Target: scoped Socket.io mutation events plus one bounded reconnect/navigation refresh and zero idle full-list polling. Residual loops are tracked in the remediation ledger. |
| Explicit human-owned task decisions | โ Complete | Task approval endpoints remain for genuine human-owned product operations, not for normal Hermes turns or tools |
| Tool execution | โ ๏ธ Partial | Hermes prefers progressively disclosed normal/native tools. Humanwork MCP supplies only missing capabilities; the narrow configured write-action compatibility carrier may gate one concrete server-owned side effect. |
| Expert profile + assignment UI | โ Not built | USER_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 |