# Feature coverage (OSS) One row per user journey. Every feature PR adds or updates its row and the spec that covers it. - **Priority:** P1 is the first waves, P2 comes later, N runs nightly only. - **Status:** โœ… covered ยท ๐Ÿšง in progress ยท โฌœ not yet | Feature | Journey | Spec | Pri | Status | |---|---|---|---|---| | Setup and auth | First-run setup creates the org and lands on the dashboard | `specs/setup/org.setup.ts` | P1 | โœ… | | Setup and auth | Admin signs in | `specs/auth/login.spec.ts` | P1 | โœ… | | Setup and auth | Wrong password shows an error | `specs/auth/login.spec.ts` | P1 | โœ… | | Setup and auth | Sign out | `specs/auth/login.spec.ts` | P1 | โœ… | | Setup and auth | Agent role is denied AI settings | `specs/auth/login.spec.ts` | P1 | โœ… | | Setup and auth | Sign-out, deactivation and a password change end sessions server-side; a refresh token is not an access token | `specs/auth/sessions.spec.ts` | P1 | โœ… | | Team | The Agent role is refused every admin API; sees channels without secrets; assigned-only sees just its group's handovers | `specs/team/permissions.spec.ts` | P1 | โœ… | | Widget chat | Customer gets the AI answer | `specs/widget/widget-chat.spec.ts` | P1 | โœ… | | Widget chat | History survives a reload | `specs/widget/widget-chat.spec.ts` | P1 | โœ… | | Widget chat | The dashboard's iframe snippet chats (its socket comes from the API's own origin) | `specs/widget/iframe-snippet.spec.ts` | P1 | โœ… | | Widget chat | First authorization answer lost (socket gets the anonymous token) โ†’ widget authorizes again and chats | `specs/widget/widget-chat.spec.ts` | P1 | โœ… | | Widget chat | Email-first agent (gate โ†’ chat, person recorded), Ask anything panel, lead capture with no email asked โ€” each also with the first authorization lost | `specs/widget/chat-styles.spec.ts` | P1 | โœ… | | Widget chat | Agent wraps up โ†’ customer rates the chat โ†’ rating stored against the agent | `specs/widget/rating.spec.ts` | P1 | โœ… | | Widget chat | A second browser that types a customer's email gets its own empty conversation (the owner keeps theirs), can't rename them or make them a lead, and an address claimed before its owner signs in yields none of their chats | `specs/widget/conversation-ownership.spec.ts` | P1 | โœ… | | Widget chat | Scoping keeps a visitor's own conversation: a second tab joins it; a visitor the site signed in finds it in another browser, and after `ReplyPier.identify()` | `specs/widget/conversation-ownership.spec.ts` | P1 | โœ… | | Widget chat | Provider error, provider timeout and malformed reply each end in an apology; the next message works | `specs/widget/ai-failures.spec.ts` | P1 | โœ… | | Human handover | AI hands over โ†’ contact form โ†’ agent takes over โ†’ two-way messages โ†’ the AI stays silent | `specs/handover/handover.spec.ts` | P1 | โœ… | | Human handover | After hours, or nobody online: the chat waits in the team's queue with a reply that says so | `specs/handover/after-hours.org.spec.ts`, `nobody-online.spec.ts` | P1 | โœ… | | Human handover | A visitor's attachment reaches the teammate through a signed link | `specs/handover/attachments.spec.ts` | P2 | โœ… | | Agents | Create in the dashboard โ†’ edit instructions โ†’ they reach the model | `specs/agents/agent-editor.spec.ts` | P1 | โœ… | | Agents | Toggles (handover, rating, reply buttons) | โ€” | P1 | โฌœ | | Knowledge | Add text โ†’ answer is grounded in it (real search) | `specs/knowledge/knowledge-answer.spec.ts` | P1 | โœ… | | Knowledge | Deleted knowledge stops reaching the model; one agent's never reaches another's | `specs/knowledge/knowledge-lifecycle.spec.ts` | P1 | โœ… | | Knowledge | An uploaded PDF is indexed by the knowledge worker and answered from | `specs/knowledge/knowledge-pdf.spec.ts` | P2 | โœ… | | AI config | Rejected key is reported (exact message) and agents keep working; the saved key is the one used | `specs/settings/ai-config.org.spec.ts` | P1 | โœ… | | Tickets | AI opens a ticket โ†’ listed โ†’ agent changes status | `specs/tickets/ai-ticket.spec.ts` | P1 | โœ… | | Tickets | Resolving tells the customer in their chat | `specs/tickets/ai-ticket.spec.ts` | P1 | โœ… | | Tickets | Confirmation window runs out โ†’ closed โ†’ customer rates โ†’ CSAT kept, and the ask is in the thread (worker, `@redis`) | `specs/tickets/ai-ticket.spec.ts` | P2 | โœ… | | Lead capture | Visitor shares details โ†’ appears as a Lead in People with their name and company | `specs/leads/lead-capture.spec.ts` | P1 | โœ… | | People | Rename, phone, mark customer; international and unique phones; a WhatsApp contact keeps their number | `specs/leads/people.spec.ts` | P2 | โœ… | | Team | Admin adds an agent who signs in to the inbox; Agent role sees only Inbox/People/Settings | `specs/team/team.spec.ts` | P1 | โœ… | | Team | Groups management UI | โ€” | P1 | โฌœ | | Widget JS API | open/close/isOpen; hidden launcher + page's own trigger button | `specs/widget/js-api.spec.ts` | P1 | โœ… | | Widget placement | Left side; sidebar mode; dashboard display settings with no code, site config wins; welcome message and colour | `specs/widget/placement.spec.ts` | P1 | โœ… | | Widget placement | `open({message})`, events | โ€” | P1 | โฌœ | | Token-auth widget | Server-issued token โ†’ chat works; no, tampered, other-widget or expired token is refused | `specs/widget/token-auth.spec.ts` | P1 | โœ… | | Reply buttons | Telegram, WhatsApp, Messenger, Instagram: AI offers buttons, a tap gets the next answer | `specs/channels/reply-buttons.spec.ts` | P2 | โœ… | | Reply buttons | Widget quick replies; typed-number matching | โ€” | P2 | โฌœ | | Help center | Only published articles are public; unpublishing takes one down | `specs/help-center/publishing.org.spec.ts` | P2 | โœ… | | Help center | Search | โ€” | P2 | โฌœ | | Workflows | One-message flow greets once and answers once with no AI call; a question branches on the answer; AND across two answers (true, false, an answer that looks like code, a non-number); a missing branch stops instead of taking the other | `specs/workflows/workflows.spec.ts` | P2 | โœ… | | MCP connectors | An agent answers from a real MCP server's tool; header secrets masked on read, kept on save; a server that is down costs only its own tools, and Test says it could not connect | `specs/mcp/connectors.spec.ts` | P2 | โœ… | | Channels | Telegram, WhatsApp, Messenger, Instagram, Slack, LINE, SMS (Twilio, Plivo), email: a signed inbound message gets the AI reply on the same channel | `specs/channels/replies.spec.ts` | P2 | โœ… | | Channels | WhatsApp customer asks for a person โ†’ agent takes over in the inbox โ†’ reply goes out on WhatsApp | `specs/channels/handover.spec.ts` | P2 | โœ… | | Channels | Email reply is threaded (Re: subject, In-Reply-To) | `specs/channels/email.spec.ts` | P2 | โœ… | | Channels | Forged webhooks refused on every channel; echoes, receipts and bot messages never reach the model | `specs/channels/forged-webhooks.spec.ts` | P2 | โœ… | | Channels | A refused send is marked Not delivered; list and long-title buttons stay within WhatsApp's limits | `specs/channels/delivery.spec.ts` | P2 | โœ… | | Channels | A provider's retry gets one answer (`@redis`) | `specs/channels/retries.spec.ts` | P2 | โœ… | | Channels | A WhatsApp number or Messenger Page from the customer's own Meta app (manual credentials + app secret) receives messages at its own webhook address; a wrong secret is refused; the address never takes another app's number | `specs/channels/own-meta-app.spec.ts` | P2 | โœ… | | Channels | A WhatsApp number whose token Meta refuses is flagged, the Integrations card names it, and reconnecting or the next delivered reply clears it; a message-level refusal does not flag it | `specs/channels/needs-reconnect.spec.ts` | P2 | โœ… | | Channels | Media messages; disconnect | โ€” | P2 | โฌœ | | Analytics | A conversation counts for its agent; the dashboard renders | `specs/analytics/analytics.spec.ts` | P2 | โœ… | | CRM | HubSpot install, manual sync and automatic push (worker) with the lead's details | `specs/crm/hubspot.org.spec.ts` | P2 | โœ… | | CRM | Pipedrive install (Basic-auth token exchange) and a captured lead pushed as organisation, person, lead and note | `specs/crm/pipedrive.org.spec.ts` | P2 | โœ… | | Integrations | Jira connect from Settings (real browser OAuth round trip) and the AI filing an issue in the agent's project | `specs/integrations/jira.org.spec.ts` | P2 | โœ… | | Integrations | Shopify install and link, order status answered from the shop, lookup refused without the customer's email | `specs/integrations/shopify.org.spec.ts` | P2 | โœ… | | Visual and cross-browser widget | Widget on Firefox, WebKit, Android, iPhone; screenshots light/dark | `--project=widget-*`, `specs/visual` | P2 | โœ… (nightly) | | Accessibility | axe on key screens (dark and light themes) and the widget: no serious findings anywhere; a per-screen baseline catches regressions | `specs/a11y` | P2 | โœ… | | Performance | Loader/widget size budgets; reply-time budget | `specs/perf` | P2 | โœ… | | Security basics | HttpOnly/Secure sign-in cookies; no CORS for other origins | `specs/security` | P2 | โœ… | | Org website and API access | Changing the org's website allows the new site and revokes the old one; it never gets the sign-in cookies | `specs/security/org-domain-cors.org.spec.ts` | P2 | โœ… | | Live-chat socket origin | The dashboard's socket signs in with its cookies; an org's website, or a `