Files
gochat/docs/comparison/2026-06-11-gochat-chatwoot-woochat-alignment-plan.md
T

52 KiB

GoChat ↔ Chatwoot/Woochat Frontend Alignment Review And Plan

Date: 2026-06-11
Scope: review implementation differences between GoChat and reference/chatwoot, with Woochat/current Chatwoot frontend direct-connect compatibility as the acceptance target.
Output: gap list, priority order, and executable alignment plan for the refactored GoChat business service.
Status: Live enterprise browser smoke, route parity, Meilisearch search smoke, and full Go regression passed against the reused Chatwoot frontend; notification list/profile-preference browser-store smoke, provider callback/setup fixtures, Captain provider-mode fixtures, widget pubsub-token realtime fixtures, account actions contact-merge fixtures, agent-bot account route fixtures, assignable-agent query fixtures, assignment-policy fixtures, agent-capacity nested route fixtures, agent create fixtures, custom-attribute definition fixtures, audit-log fixtures, automation-rule fixtures, campaign fixtures, canned-response fixtures, bulk-action fixtures, Captain/Copilot API fixtures, core channel provider frontend fixtures, voice/WhatsApp setup fixtures, CRM company/contact/note fixtures, CSAT report fixtures, custom-role/custom-filter fixtures, dashboard-app fixtures, dashboard/api/endPoints.js auth/profile literal fixtures, help-center dashboard fixtures, inbox conversation/message fixtures, inbox health/member/inbox fixtures, SAML settings fixtures, summary reports fixtures, generic integrations fixtures, Dyte/Linear/Slack literal integration runtime fixtures, labels/macros/notifications/reports/search/SLA literal runtime fixtures, teams/summary-reports/user-notification-settings/webhooks/year-in-review/CSAT public fixtures, widget literal runtime fixtures, account literal fixtures, agent-capacity literal fixtures, agent bulk-create literal triage, article literal triage, automation literal triage, company literal runtime paths, contacts literal runtime paths, conversations literal label/unread-count paths, endPoints.spec.js legacy constants, CSAT reports literal runtime paths, and inbox conversation literal runtime paths and inbox message literal runtime path and inbox literal runtime paths are now covered. docs/parity/frontend_contract_inventory.md now has 0 rows marked Mapped; needs fixture/smoke evidence; final release gates were rerun on 2026-06-13 and passed: route parity, full Go regression, and live enterprise Woochat/browser smoke.

Executive Summary

  • The reused Woochat frontend contract is represented by reference/chatwoot/app/javascript/dashboard/api, reference/chatwoot/app/javascript/widget/api, reference/chatwoot/app/javascript/survey/api, and their dependent stores/composables.
  • Current GoChat has strong route coverage for the tracked frontend-critical surface: refreshed route parity reports 435 exact, 0 method-compatible, 9 parameter-compatible, and 0 missing out of 444 tracked critical routes.
  • The direct-connect blockers found in this pass were fresh-schema omissions, Chatwoot token-header/CSRF/CORS assumptions, Redis pool starvation under smoke load, trailing-slash collection-route redirects, Vite browser-smoke shell routing, dashboard boot feature gates, and missing fresh-schema team/campaign tables. These have been aligned for the covered dashboard/widget/public/enterprise API and browser paths.
  • No independent /home/rogee/Projects/*woochat* checkout was found during this review, so this plan treats reference/chatwoot as the current Woochat frontend source of truth.
  • This document now records the landed alignment work and the current completion evidence. Keep realtime and provider fixtures as drift guards, but the direct-connect release gates have current evidence.

Evidence Refresh

Evidence Current Result Notes
Route dump docs/parity/gochat_routes.txt refreshed from go run ./cmd/dump_routes Current dump contains 1010 lines including TOTAL: 1009.
Route parity docs/parity/route_parity.md refreshed from go run ./cmd/route_parity 435 exact, 0 method-compatible, 9 parameter-compatible, 0 missing out of 444 tracked critical routes.
Frontend contract scan reference/chatwoot/app/javascript/dashboard/api, widget/api, survey/api Dashboard, widget, public survey, Captain, enterprise, channel, report, and integration clients define the direct-connect API contract.
Frontend contract inventory docs/parity/frontend_contract_inventory.md Phase 0 inventory created with 224 frontend API contract entries grouped by owner area.
Live enterprise browser smoke docs/parity/frontend_smoke_report.md; .tmp/frontend-smoke-live/browser-smoke-report.json Passed on 2026-06-13T12:24:17Z with 37 checks, 0 failures, reused reference/chatwoot dashboard/widget/enterprise screens against GoChat on port 13000.
Full Go regression git diff --check && GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./... Passed on 2026-06-13 after smoke-script stabilization and route parity refresh.
Parameter-compatible route tests internal/handler/api/v1/agent_capacity_handler_test.go and internal/handler/api/v1/article_handler_test.go Agent-capacity nested user/inbox-limit methods and help-center .md/.png suffix dispatch are covered by focused handler tests.
Auth/profile/account fixtures internal/handler/api/v1/auth_handler_test.go, internal/handler/api/v1/profile_handler_test.go, internal/handler/api/v1/mfa_handler_test.go, internal/handler/api/v1/account_handler_test.go, internal/repository/account_repo_test.go Sign-in, validate-token, profile bootstrap, availability, auto-offline, active-account side effects, MFA raw payloads, and account cache keys now assert Chatwoot-style frontend-visible keys and persisted side effects.
Inbox fixtures internal/handler/api/v1/inbox_handler_parity_test.go, internal/handler/api/v1/inbox_member_handler_test.go, internal/handler/api/v1/agent_capacity_handler_test.go, internal/handler/api/v1/agent_bot_handler_test.go Inbox list/detail envelopes, channel settings, admin-only sensitive fields, inbox member payload/diff updates, raw WhatsApp Cloud health payloads, agent create payloads, assignable-agent inbox_ids queries, assignment-policy list/inbox override flows, agent-capacity policy/nested user/inbox-limit success/error flows, agent-bot account CRUD/avatar/reset routes, Facebook/Google/Instagram/Microsoft/TikTok/Twilio/Twitter/Web/WhatsApp-call provider frontend routes, and provider callback/webhook drift guards now have frontend-contract fixtures.
Conversation/message fixtures internal/handler/api/v1/conversation_handler_crud_test.go, internal/handler/api/v1/message_handler_test.go, internal/handler/api/v1/conversation_serializer_test.go Conversation list envelope/meta/label/attribute/last-message fields and message create/list/attachment fields now assert the Chatwoot dashboard store contract.
CRM/contact/company fixtures internal/handler/api/v1/crm_frontend_smoke_test.go, contact_handler_crud_test.go, company_handler_test.go Contact/company dashboard smoke plus account actions contact merge, contact merge/import/export, contact notes, company nested contacts/conversations/notes, contact timeline attachments, contact/company update realtime events, contact delete realtime events, and merge update/delete realtime events now assert frontend-visible response and mutation contracts.
Voice/WhatsApp/CSAT/customization fixtures internal/router/router_test.go, internal/service/whatsapp_authorization_service_test.go, internal/handler/api/v1/csat_survey_handler_test.go, custom_role_handler_test.go, custom_filter_handler_test.go, dashboard_app_handler_test.go Woochat voice conference callbacks/contact call initiation, WhatsApp embedded signup/reauthorization, CSAT dashboard list/metrics/download, custom roles, custom filters, and dashboard apps now have direct frontend-contract evidence in the inventory and focused command list.
Contract fixture coverage docs/parity/contract_fixture_coverage.md P0/P1 owner areas now have a coverage matrix mapping frontend contract source, current GoChat evidence, and remaining evidence needed; auth/profile/account has focused fixture coverage for sign-in/profile/MFA/cache slices, while remaining avatar/accounts/conversations literals stay in the inventory backlog.
Regression test git diff --check and GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./... passed again on 2026-06-13 after the Captain/provider/widget evidence updates and route regeneration. Covers the expanded direct-connect fixture suite, route boot, webhook receipt updates, service jobs, widget/API handlers, middleware, repository, router, and websocket packages.
Placeholder audit docs/parity/placeholder_audit.md No chatwootParityStub remains on reused critical dashboard/widget/public paths; provider nil-fallbacks return explicit 503.
Frontend smoke harness docs/parity/frontend_smoke_report.md, scripts/parity_frontend_smoke.sh, and scripts/parity_frontend_browser_smoke.mjs Fresh PostgreSQL/Redis/Meilisearch migration, seed, API smoke, enterprise API smoke, and live scripts/parity_frontend_smoke.sh --enterprise-browser-smoke passed on 2026-06-13 against GoChat on 127.0.0.1:13000 and reused Chatwoot Vite on localhost:3036; browser report is .tmp/frontend-smoke-live/browser-smoke-report.json with 37 checks and 0 API failures, including notification/profile preference store requests.

Landed Alignment Work In This Pass

  • Added fresh-schema migrations for dashboard apps, extended contacts/conversations/accounts/channel fields, companies, SLA, installation configs, CSAT responses, bot rules, automation rules, macros, macro executions, and audits so a clean PostgreSQL database can migrate and seed without hidden legacy state.
  • Made smoke seed idempotent for the admin user and kept seed output parseable for the smoke harness even when bootstrap logs are emitted.
  • Aligned Chatwoot direct-auth behavior by allowing DeviseTokenAuth-style access-token headers in AuthMiddleware and skipping CSRF for token-auth API/public/widget paths that the reused frontend calls.
  • Increased Redis pool configurability/default capacity to avoid login/token storage failures under worker plus smoke concurrency.
  • Registered both no-slash and trailing-slash collection routes for frontend-critical dashboard and enterprise paths to prevent Gin 301 HTML redirects from breaking JSON clients.
  • Exposed and allowed DeviseTokenAuth headers through CORS so the browser can read access-token, client, uid, token-type, and expiry, persist cw_d_session_info, and validate dashboard sessions without frontend changes.
  • Hardened browser smoke to serve Chatwoot/Vite shell pages from a same-origin test server, proxy Vite assets, use CDP-captured requests for navigation assertions, send Chatwoot auth headers for browser-context Copilot requests, and fail on frontend-visible API 4xx/5xx responses.
  • Added fresh-schema teams, team_members, and campaigns migrations and made the dashboard portal list readable without a knowledge-base feature flag so boot-time unconditional frontend requests do not fail.
  • Extended smoke coverage through dashboard auth/profile/inbox/conversation/message/contact/company, widget config/message, public CSAT, SLA, CSAT reports/download, automation, macros, audit logs, custom roles, agent capacity, Captain, and Copilot.
  • Added auth/profile/account contract fixtures for DeviseTokenAuth sign-in and validate-token payloads, profile bootstrap user/account keys, availability and auto-offline mutations, set_active_account membership active_at persistence, MFA raw payloads, and account cache keys.
  • Added inbox/provider contract fixtures for Chatwoot-style list/detail envelopes, channel settings, admin-sensitive fields, inbox member payload/diff updates, raw WhatsApp Cloud health responses, provider delivery/read/failure callbacks, and duplicate status-callback idempotency.
  • Added conversation/message contract fixtures for Chatwoot-style conversation list envelopes, meta sender fields, labels, additional/custom attributes, last-message payloads, outgoing message create defaults, sender payloads, content attributes, attachments, and display conversation IDs.
  • Fixed profile serialization to always expose custom_attributes as an empty object when unset, matching the reused frontend's object-access assumptions, and made account-user active_at updates database-portable instead of relying on PostgreSQL-only NOW().

Alignment Target

Woochat/current Chatwoot frontend must be able to point at GoChat by changing only backend host/runtime configuration, without patching frontend API clients or store logic.

That requires parity across five layers:

  1. Route shape: every frontend-called path/method exists with Chatwoot-compatible path, query, multipart, and auth handling.
  2. Wire contract: JSON envelopes, pagination metadata, object keys, enum values, null/empty behavior, error status, and validation messages match frontend expectations.
  3. State transitions: mutations update all dependent models and counters that frontend stores read after success or realtime replay.
  4. Realtime contract: websocket/SSE/Redis event names and payloads match Chatwoot event consumers for conversation, message, notification, presence, typing, cache, inbox, and contact updates.
  5. Operational side effects: async jobs, search indexing, delivery status, webhook dispatch, CSAT, reports, and provider integrations are durable enough that the frontend does not observe stale or fake success states.

Current Functional Difference Map

Priority Area Current GoChat State Chatwoot/Woochat Expectation Required Alignment
P0 Full reused frontend smoke API, browser, enterprise API, and enterprise browser smoke now pass for the covered route-request paths. Dashboard, widget, public CSAT/help-center, and enterprise screens run unchanged against GoChat. Keep the smoke gate in CI/release and convert any future failures into named implementation slices.
P0 Auth/session bootstrap DeviseTokenAuth-style access-token API auth, CSRF skip paths, browser CORS header exposure, sign-in/validate-token/profile user-account fixtures, availability, auto-offline, active-account persistence, MFA raw payloads, and cache keys are now aligned for direct API and browser calls. Login, validate-token, profile, account cache bootstrap, MFA-visible fields, active account, and token refresh behave like Chatwoot without frontend client changes. Keep auth/profile/account fixtures as drift guards while moving to inbox and conversation fixture slices.
P0 Serializer/envelope drift Auth/profile/account, inbox list/detail/member/health, and core conversation/message fixtures now guard key frontend-visible payloads, but CRM, widget/public, reports, enterprise, and deeper mutation rows still need frozen fixtures. Frontend stores consume exact Chatwoot object shapes, pagination, meta, and error envelopes. Freeze representative fixture responses from Chatwoot and compare GoChat for contacts, reports, widget, public, enterprise screens, and remaining conversation mutations.
P0 Route parameter compatibility No tracked route is missing, but 9 are parameter-compatible rather than exact. Frontend-visible literal paths must work; server-side parameter names are not visible, but suffix dispatchers must preserve .md/.png behavior. Agent-capacity nested users/inbox-limits and help-center article .md/.png routes now have focused proof; keep future parameter-compatible routes covered by external-path tests.
P0 Realtime payload fidelity Event constants, publisher, WS/SSE delivery, message/conversation mutation fixtures, typing/presence heartbeat and expiry fixtures, notification/cache fixtures, widget pubsub_token room message delivery fixtures, browser subscription create/destroy, user notification preference update fixtures, and live browser requests for the notification list/profile notification-preference screens exist for Chatwoot-style frontend behavior. Frontend stores expect message.created, conversation.updated, notification.created, typing/presence/cache events with Chatwoot payload fields; PushHelper and notification-preference screens expect raw Chatwoot payloads and account-scoped routes; widget ActionCable expects message.created on the contact pubsub_token room. Keep notification/preference and widget browser smoke as drift guards.
P0 Fresh database bootstrap Fresh-schema migrations and smoke seed were extended for dashboard apps, CRM, teams, campaigns, SLA, CSAT, automation, macros, audits, Captain, and account/inbox fields. A new deployment can migrate, seed, sign in, and load Woochat frontend screens without relying on hidden legacy rows or manual SQL backfills. Keep migration smoke as a release gate and add rollback/idempotency checks for the new Chatwoot-compatible schema slices.
P1 Conversation/message behavior Core services, serializers, labels, participants, drafts, attachments, status/assignment paths exist. Finder filters, display IDs, unread counts, assignee/team/status transitions, private notes, reply-to, delete/retry/update, attachment payloads, and mentions match Chatwoot. Add contract tests around conversation list/detail/search/message create-update-delete and verify frontend store refresh/realtime paths.
P1 Inbox/channel/assignment setup Inbox, member, assignable-agent, assignment-policy, agent-capacity, channel settings, health raw payload, provider-failure envelope, and assignment-policy inbox override routes are represented. Inboxes and channels expose Chatwoot-compatible settings, members, availability, provider health/failure, assignment-policy override, and capacity payloads. Add signed provider setup/callback fixtures beyond WhatsApp health and keep role-sensitive channel settings as drift guards.
P1 CRM/contact/company Contact/company handlers, custom attributes, notes, labels, search, and frozen dashboard payload-shape fixtures are represented for common contact/company flows; contact merge/import/export contracts, attachment timeline depth, contact/company realtime update payloads, and contact delete/merge source-side events now have focused fixture coverage. Contact list/detail, contact inboxes, merge, import/export, company contacts, notes, custom attributes, labels, realtime updates, and timeline fields match dashboard stores. Keep CRM fixtures as drift guards; contact update/delete/merge realtime source paths are now covered.
P1 Widget/public inbox APIs Widget routes, messages, campaigns, direct uploads, contact update, public inbox paths, focused widget config/pre-chat/message/ActiveStorage direct-upload/campaign/public contact/status/read/labels/events/realtime payload fixtures, cw_conversation query/cookie reuse fixtures, and expanded browser-smoke harness coverage for widget boot now exist. Widget API accepts Chatwoot query params (website_token, locale, cw_conversation, cw_d_session_info), persisted cw_conversation cookies, multipart attachments, ActiveStorage direct uploads, campaigns, labels/events, update/read semantics, widget message.created pubsub-token realtime delivery, and reused widget entrypoint boot requests. Keep live browser smoke and widget realtime fixtures as drift guards.
P1 Search and indexing Meilisearch-first engine, DB fallback, indexers, search handlers, seed-created help-center article data, live search API-smoke assertions for seeded conversation/message/contact/company/article payloads, valid Meilisearch document UIDs, explicit uid primary-key writes, and company/article mutation hook fresh-object tests exist. Search results for conversations, messages, contacts, companies, and articles are account-scoped, fresh after mutations, and shaped for frontend global/search modules. Keep live Meilisearch smoke, reindex job, and fallback rejection in release mode as release gates.
P1 Help-center/public portal Portal/category/article/search/sitemap routes exist, including dashboard article CRUD, JSON, markdown, and tracking-pixel compatibility paths; dashboard create/list/show/edit/update/delete payloads, locale redirect/fallback, JSON list/filter, sitemap, .md, and .png fixtures now assert Chatwoot-compatible behavior. Public help center and dashboard article management support locale redirects, article/category listing, search, sitemap, .json, .md, .png tracking behavior, and Chatwoot dashboard article CRUD payloads. Keep as drift guard; add browser smoke only if Woochat portal UI changes.
P1 Direct uploads and attachments Account/widget direct upload handlers and attachment serializers exist; ActiveStorage create/complete response fields, storage bytes, signed IDs/upload UUIDs, widget attachment payloads, and unsupported MIME validation now have focused fixtures. Chatwoot frontend can upload files through ActiveStorage-style direct-upload flow and send attachments in dashboard/widget messages. Add provider send-payload and REST-vs-push attachment drift guards where channel delivery paths serialize attachments.
P1 Automation/macros/campaigns Automation rules, macros, macro executions, bot rules, campaigns, and canned responses are represented; automation-rule CRUD/clone/toggle validation and campaign lifecycle/trigger side effects, scheduled trigger job dispatch/realtime events, and bulk-action progress now have focused Chatwoot frontend contract fixtures, with service alignment for campaign display-id start/stop plus frontend audience-array trigger tolerance. Dashboard automation-rule create/list/update/clone/toggle/delete, campaign create/update/start/stop, macro execute, and canned response CRUD/search flows return Chatwoot-compatible payloads or explicit action envelopes and mutate conversations/messages where applicable, including campaign-triggered conversation/message creation, scheduled campaign trigger job dispatch/completion, campaign trigger conversation/message realtime events, macro empty-200 execute response/validation behavior, and durable bulk-action completion/search-index side effects. Keep this slice as a drift guard; re-open only if Woochat starts consuming a non-empty macro execute response body.
P1 Notifications/preferences Notification, notification-subscription, user notification settings, presence, and account cache routes exist; notification CRUD/read-state, PushHelper browser subscription create/destroy, user preference show/update persistence, source-side mutation publication, notification/cache realtime payload fixtures, and live browser route requests for /notifications?page=1 plus /notification_settings are covered. Notification lists, read/unread transitions, browser subscription state, user notification preferences, and online status stay in sync with frontend stores. Keep as drift guard; broaden only if Woochat changes subscription/preference UI behavior or adds new notification-store calls.
P1 Enterprise screens SLA, audit logs, custom roles, agent capacity, assignment policies, Captain/Copilot, CSAT, limits and account enterprise routes pass API and browser route-request smoke; TestChatwootPermissionSetCreateUpdateListShowParity freezes Chatwoot's six custom-role permission keys; TestEnterpriseAccountLiteralFrontendPathsUseCurrentAccountContext covers literal enterprise account API paths; TestCaptainAssistantHandler_PlaygroundV2ProviderErrorReturnsChatwootFallback freezes Chatwoot's Captain V2 provider-error fallback shape; TestCopilotResponseJobForFollowupMessageUsesStoredThreadHistoryAndIdempotency covers background Copilot follow-up jobs. Enterprise frontend screens load and mutate without frontend patches or fake success states, including custom-role permission management, enterprise account limits/billing actions, Captain limit availability clamping, subscription existing-customer no-op behavior, Captain V2 provider-error conversation_handoff fallback, and Copilot follow-up response jobs through stored thread history. Keep live provider smoke and fixture drift guards as release gates.
P1 Reports/live reports API v2 reports and summary report routes exist; TestAPIV2Reports_ChatwootPayloadShapes, TestAPIV2Reports_AllFrontendEndpointShapes, TestAPIV2Reports_TimeseriesTimezoneValueParity, and TestAPIV2Reports_CSVDownloadEntrypointsMatchChatwootFrontend freeze summary, timeseries, timezone-offset day grouping values, CSV download, matrix, bot, distribution, conversation, and outgoing-count endpoint shapes; TestAPIV2LiveReports_ChatwootFrontendPayloadShapes freezes v2 live-report conversation/grouped payloads; TestAPIV2LiveReports_StoreRefreshSequenceMatchesChatwootFrontend covers the three Chatwoot liveReports store refresh actions; TestAPIV2LiveReportsRouterAuthAndAccountScope covers live-report auth/account-scope enforcement; audit list serializer filters, fixed page size, pagination meta, and descending page order have fixture coverage. Dashboard reports have focused frontend-direct-connect fixtures for API v2 report shape, value, CSV, live payload, auth, and store-refresh paths. Keep reports fixtures as drift guards; broaden only if Woochat adds new report API calls.
P1 CSAT/survey Public CSAT and dashboard CSAT list/metrics/download paths are represented and included in API smoke; TestMetrics_DashboardValueDriftFiltersMatchChatwootFrontend freezes Chatwoot's response-filtered total_count/ratings_count and account/date-only total_sent_messages_count; review-note audit/serializer and public PUT/locked-update fixtures now cover the frontend-visible mutation edges. Public survey show/update plus dashboard metrics/download match Chatwoot status codes, validation errors, CSV/export payloads, date filters, dashboard metric filters, sent-count semantics, review-note audit effects, and public PUT/locked non-mutation behavior. Keep status-transition/job-send fixtures as follow-up drift guards.
P2 Provider integrations Webhook/channel handlers now have fixtures for WhatsApp delivered/read/failed, Twilio delivered/read/failed plus duplicate status idempotency, Facebook/Instagram delivered/read receipts plus retry idempotency, TikTok read receipts plus retry idempotency, LINE valid/missing/invalid signature handling, Telegram webhook setup success/failure reauthorization flags, setup payloads, OAuth callback fallback/upsert edges, email OAuth token payload errors, and Linear/Shopify/Notion provider-error redirects without phantom hooks. Frontend-visible channel setup and health states reflect real provider ack/failure/retry behavior. Run live provider smoke where credentials are available; keep fixtures as drift guards for future provider payload changes.
P2 Background jobs and durability Worker/dispatch services exist for indexing, delivery, CSAT, import/export, reports, webhooks, Captain, and maintenance. Chatwoot side effects are asynchronous, retryable, idempotent, and observable when the frontend refreshes or receives events. Add job idempotency/retry tests and expose frontend-visible failure states instead of silent success.
P2 SSO and identity edge SSO/SAML/LDAP/OIDC are currently treated as excluded/partially wired in prior tracker text. Woochat auth screens may still contain MFA/profile/session/token flows even if enterprise SSO is feature-gated. Document deployment gates for SSO-family features; keep profile, session, MFA, token validation, and active-account behavior fully frontend-compatible.

Required Alignment Function Points

The remaining alignment work should be tracked as frontend-owner slices, not only as backend packages, because the acceptance target is unchanged Woochat frontend code against GoChat.

Owner Slice Must Align For Direct Frontend Connect Primary Evidence To Add
Auth/profile/account bootstrap auth.js, account.js, enterprise/account.js, CacheEnabledApiClient.js, MFA, validate-token, active-account, auto-offline, account cache keys, installation config. Browser login smoke plus fixture assertions for /auth/sign_in, /auth/validate_token, /profile, /accounts, /accounts/:id, and enterprise account endpoints.
Inbox/channel/assignment inboxes.js, inboxMembers.js, assignableAgents.js, assignmentPolicies.js, agentCapacityPolicies.js, channel clients, inbox health. Fixtures for inbox list/detail/settings/members, provider channel create/update, assignment-policy inbox overrides, assignable-agent availability, capacity users/inbox-limits, and health states.
Conversations/messages conversations.js, inbox/conversation.js, inbox/message.js, conversation/message stores. Fixtures for list/detail/search/filter/meta, message create/update/delete/retry, private notes, attachments, labels, participants, drafts, assignment/status/team changes, and matching realtime events; update/delete/retry now include Chatwoot frontend route/body assertions plus message-mutation dispatch evidence for external-error, tombstone cleanup, and retry status reset; message.created/message.updated/conversation.updated/conversation.typing_on realtime wire shapes, Chatwoot presence users/contacts payloads, and conversation status/priority/labels/assignment change-data events are fixture-covered; draft collection and participants now resolve Chatwoot display conversation IDs end-to-end; unread/update-last-seen display-ID routes now cover last-seen rollback and notification read side effects.
CRM contacts.js, companies.js, contactNotes.js, attributes.js, labels/custom attributes. Fixtures for contact/company list/detail, merge, notes, contact inboxes, import/export, labels, custom attribute CRUD, contact/company search, attachment timeline, and contact/company realtime updates.
Widget/public inbox widget/api/*, public inbox/contact/conversation/message endpoints, direct uploads, campaigns. Browser widget smoke plus fixtures for config/pre-chat frontend mixin shape, cw_conversation cookie/query-session reuse during config boot and message history fetch, message pagination, contact update, labels, events, campaigns, multipart/direct upload, and public conversation status/read flows.
Help center/public portal helpCenter/*, portal/api/article.js, /hc JSON/markdown/tracking/sitemap paths. Fixtures for locale fallback, portal/category/article listing, article JSON/markdown, search, sitemap, and tracking pixel side effect/content type.
Reports/CSAT/live reports reports.js, summaryReports.js, liveReports.js, csatReports.js, survey/api/*. API v2 report endpoint shape fixtures are covered across reports.js index/summary/conversations/agents/inboxes/labels/teams/conversations_summary/conversation_traffic/bot_metrics/bot_summary, timeseries/CSV/matrix/distribution/outgoing-count, and live-report conversation/grouped paths; v2 timezone-offset day grouping value parity covers frontend timezone_offset semantics; v2 CSV download entrypoints now cover agents/inboxes/labels/teams/conversations_summary response headers and raw CSV bodies; live-report auth/account-scope enforcement now rejects unauthenticated and cross-account access while accepting Chatwoot access-token; live-report store-refresh sequence now covers account/agent/team actions and raw commit-ready payloads; outgoing message count value parity now covers agent/team/inbox/label grouping, invalid group_by, date-range exclusion, incoming-message exclusion, and bot sender exclusion for agent grouping; CSAT dashboard list/metrics/download, metric value-drift filters, review-note audit/serializer behavior, and public show/update/locked PUT edges are fixture-covered; keep status-transition/job-send fixtures as drift guards.
Automation/macros/campaigns automation.js, macros.js, campaigns.js, cannedResponse.js, bulk actions. Automation-rule CRUD/clone/toggle validation fixture, campaign nested body/display-id lifecycle, trigger side-effect, scheduled job-dispatch, and realtime event fixtures, macro display-conversation execute side-effect fixture, canned response CRUD/search fixtures, bulk-action enqueue/progress/search-index fixtures, macro empty-200 execute response behavior, and broad bot-rule suites are covered; keep as drift guard unless Woochat changes the macro execute response contract.
Notifications/realtime/cache notifications.js, notificationSubscription.js, user notification settings, websocket consumers, cache invalidation. Notification list/read/unread/delete fixtures plus notification.created/notification.updated/notification.deleted payload fixtures using { notification, unread_count, count }; account.cache_invalidated.cache_keys label/inbox/team fixture; PubSub subscriber now forwards updated/deleted/cache topics; read/unread/snooze/delete handlers now publish Chatwoot notification store payloads; browser PushHelper subscription create/destroy and user notification settings show/update persistence are fixture-covered.
Enterprise/Captain/Copilot sla.js, customRole.js, auditLogs.js, captain/*, enterprise account APIs, limits. Enterprise browser smoke plus enterprise account literal-path limits/billing actions, Captain limit availability clamping, subscription existing-customer no-op behavior, and billing error no-mutation boundaries, custom-role Chatwoot permission key parity, Captain documents/responses payload and frontend filter fixtures, Captain document response-builder queue/idempotency/FAQ/embedding job fixtures, Captain playground legacy disabled fallback, Captain V2 enabled response and provider-error conversation_handoff fallback, Copilot thread provider-disabled/provider-enabled fixtures, background Copilot follow-up job history/idempotency, and SLA inbox association response/DB side effects are covered; keep as drift guard for new Captain/Copilot provider modes.
Provider integrations channel/*, integrations/*, webhooks.js, provider callback routes. Signed provider callback fixtures, setup/health/delivery-state tests, retry/idempotency checks, and stable unsupported responses for unconfigured providers; WhatsApp signed delivery-status callback now persists delivered/read/failed message statuses, delivery status timestamps, status events, frontend-visible external_error for failures, and duplicate same-status callbacks as idempotent no-ops; Twilio delivery-status callbacks now normalize callback phone numbers, persist delivered/read/failed message statuses, delivery status rows, status events, frontend-visible external_error for failures, and suppress duplicate same-status callbacks as idempotent no-ops; TikTok read receipts now persist read message status, delivery status, status event, and duplicate read-receipt retries as idempotent no-ops; contact-level read receipts now also backfill per-contact delivery status rows for messages already at the target read status (TestIncomingPersisterQueuesContactMessagesStatusUpdateWithWorker); Facebook/Instagram delivery/read receipts now persist delivered/read message statuses, delivery status rows, status events from Chatwoot-compatible webhook endpoints, and duplicate receipt retries as idempotent no-ops; Facebook page setup now covers facebook_pages.json provider failure as 422, raw register_facebook_page inbox payload/config, and reauthorize_page config updates; root Instagram/TikTok/Twitter OAuth callbacks now persist serializer-readable inbox channel config before redirecting Woochat to inbox setup; repeated Google/Instagram/TikTok/Twitter callbacks refresh existing channel/inbox config and redirect to settings instead of the new-inbox agent step, while Google/Microsoft token payload errors redirect to the frontend fallback without creating phantom inboxes; Linear/Shopify/Notion token payload errors redirect to stable Chatwoot frontend destinations without creating phantom hooks; TikTok setup now returns stable {channel,inbox} payloads and persists channel config even when provider setup is disabled; Telegram webhook setup success stores webhook_url, and setup failure marks reauthorization_required instead of silently exposing a working channel; LINE/Twilio setup fixtures assert raw inbox payloads plus persisted channel linkage/config; LINE webhooks now cover valid, missing-signature, and invalid-signature behavior without creating phantom messages.

Parameter-Compatible Route Follow-Up

These are not missing frontend paths, but they require explicit coverage because route parity is currently shape-compatible instead of exact-name-compatible:

Priority Route Family Chatwoot Path Shape GoChat Match Alignment Action
P0 Agent capacity users /api/v1/accounts/:account_id/agent_capacity_policies/:agent_capacity_policy_id/users /api/v1/accounts/:account_id/agent_capacity_policies/:id/users Covered by TestChatwootPolicyInboxLimitAndUserFlow plus TestChatwootPolicyInboxLimitAndUserValidationErrors: create/list/delete response shape and validation/not-found envelopes use the Chatwoot literal frontend path.
P0 Agent capacity inbox limits /api/v1/accounts/:account_id/agent_capacity_policies/:agent_capacity_policy_id/inbox_limits/:id /api/v1/accounts/:account_id/agent_capacity_policies/:id/inbox_limits/:limit_id Covered by TestChatwootPolicyInboxLimitAndUserFlow plus TestChatwootPolicyInboxLimitAndUserValidationErrors: create/duplicate validation/PUT/PATCH/delete, negative-limit validation, and missing-limit not-found envelopes use the Chatwoot literal frontend path.
P0 Help-center markdown /hc/:slug/articles/:article_slug.md suffix-compatible article route Covered by TestPublicMarkdown_ReturnsOnlyPublishedMarkdown: verifies text/markdown; charset=utf-8, raw body, locale-specific content, and draft 404 behavior.
P0 Help-center tracking pixel /hc/:slug/articles/:article_slug.png suffix-compatible article route Covered by TestPublicTrackingPixel_IncrementsPublishedArticleViews: verifies image/png, 1x1 PNG body, private 24h cache header, published view increment, and draft non-increment behavior.

Current evidence: TestChatwootPolicyInboxLimitAndUserFlow now covers agent-capacity inbox-limit POST/duplicate validation/PUT/PATCH/DELETE and user POST/GET/DELETE flows. TestChatwootPolicyInboxLimitAndUserValidationErrors covers negative-limit validation, missing-limit not-found, missing user validation, and missing account-user not-found envelopes on the same Chatwoot literal nested paths. TestInboxAssignmentPolicy_ChatwootRoutes covers assignment-policy inbox override attach/show/list/delete. TestInboxHandler_HealthReturnsWhatsAppCloudRawPayload and TestInboxHandler_HealthReturnsProviderFailureState cover frontend-visible WhatsApp Cloud health success/failure behavior. TestPublicMarkdown_ReturnsOnlyPublishedMarkdown and TestPublicTrackingPixel_IncrementsPublishedArticleViews cover help-center suffix dispatch behavior.

Prioritized Execution Plan

Phase 0 — Freeze Frontend Contract

  • Generate an inventory of Woochat frontend API calls from dashboard/api, widget/api, survey/api, relevant stores, and composables. docs/parity/frontend_contract_inventory.md now records the first owner-mapped API-client inventory.
  • Group each call by owner slice: auth/profile/account, inbox/channel, conversation/message, CRM, automation/macros, help center, widget/public, reports, enterprise, integrations, Captain.
  • For each group, record method, path, query/body shape, expected success envelope, expected error envelope, and realtime/cache side effect.
  • Deliverable: docs/parity/frontend_contract_inventory.md with owner mapping and smoke coverage status.

Phase 1 — Close P0 Direct-Connect Gates

  • Run scripts/parity_frontend_smoke.sh --api-smoke against PostgreSQL, Redis, Meilisearch, and GoChat.
  • Run scripts/parity_frontend_smoke.sh --browser-smoke against the reused Chatwoot/Vite frontend.
  • Run enterprise smoke modes when enterprise screens are enabled.
  • Fix or ticket every failure with a reproducible endpoint, frontend component/store, expected Chatwoot behavior, and GoChat hotspot.
  • Acceptance: smoke report records pass/fail by matrix row, no untriaged P0 failure remains.

Phase 2 — Contract Fixture Tests

  • Capture or reconstruct Chatwoot-compatible fixtures for key dashboard pages: profile, account cache keys, inbox list/detail, conversation list/detail, message create/update/delete, contact/company, labels/teams, custom filters, reports.
  • Add GoChat handler/serializer tests that assert exact keys, enum strings, nullable fields, pagination/meta, timestamps, and errors.
  • Include widget/public fixtures for pre-chat, message pagination, direct upload, CSAT submit/update, help-center JSON/markdown/tracking routes.
  • Acceptance: fixture tests fail on contract drift and cover all P0/P1 frontend entrypoints.

Phase 3 — Realtime And Store Consistency

  • Compare Chatwoot ActionCable event payloads against GoChat WebSocket/SSE/Redis events.
  • Verify that every mutation used by the frontend emits the events needed to update unread counts, conversation previews, active timelines, labels, assignments, contact details, notifications, and cache keys.
  • Keep browser subscription and user notification settings fixtures as drift guards; the live enterprise browser smoke now also covers the current Chatwoot notification list and profile notification-preference route requests.
  • Acceptance: frontend can rely on realtime updates without stale persisted state or manual refresh workarounds.

Phase 4 — Side Effects And Async Durability

  • Validate search indexing after every searchable mutation and prove release-mode Meilisearch behavior.
  • Validate background jobs for message delivery, delivery status, CSAT sends, contact import/export, webhook dispatch, report rollups, Captain/Copilot jobs, and maintenance cleanup.
  • Add idempotency and retry tests where Chatwoot queues jobs; expose frontend-visible failures where provider execution cannot be completed.
  • Acceptance: successful API responses correspond to durable side effects or explicit frontend-visible pending/failed states.

Phase 5 — Enterprise And Provider Hardening

  • Run enterprise smoke across SLA, custom roles, audit logs, agent capacity, assignment policies, Captain/Copilot, limits, CSAT, automation/macros, and reports.
  • Validate channel/provider setup and webhook callbacks with signed fixture requests.
  • Document feature gates for intentionally disabled provider/LLM/SSO behavior so the frontend receives stable disabled/unsupported states instead of broken screens.
  • Acceptance: enterprise/provider screens either work unchanged or render intentional disabled states from Chatwoot-compatible API responses.

Acceptance Matrix

Gate Command Or Evidence Required Result
Route parity go run ./cmd/dump_routes then go run ./cmd/route_parity 0 missing; parameter-compatible route families have focused tests or documented Gin constraints.
Static contract docs/parity/frontend_contract_inventory.md and docs/parity/contract_fixture_coverage.md Every frontend API client call is mapped to a GoChat handler/service and smoke/test owner; current inventory has 224 entries and the coverage matrix tracks remaining fixture/smoke evidence.
API smoke scripts/parity_frontend_smoke.sh --api-smoke Auth/profile, inbox, conversation/message, CRM, seeded conversation/message/contact/company/article search, widget, CSAT, and dashboard API checks pass on a fresh PostgreSQL/Redis/Meilisearch stack; latest enterprise-browser run refreshed the company/article search additions. Search captures are written to search_conversations.json, search_messages.json, search_contacts.json, search_companies.json, and search_articles.json.
Browser smoke scripts/parity_frontend_smoke.sh --browser-smoke Reused Chatwoot/Woochat frontend boots, logs in, validates token, requests conversations, and has no frontend-visible API 4xx/5xx failures in the covered dashboard boot path; latest enterprise-browser report also boots the reused widget entrypoint and passes widget mount/messages/inbox-members/campaigns checks (.tmp/frontend-smoke-live/browser-smoke-report.json, 37 passed checks).
Enterprise smoke scripts/parity_frontend_smoke.sh --enterprise-smoke --no-seed and --enterprise-browser-smoke --no-seed Enterprise API and enterprise browser route-request smoke pass for SLA, CSAT, automation, macros, audit, custom roles, capacity, Captain, and Copilot.
Go tests GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./... Passed on 2026-06-13 after current code/documentation changes.
Diff hygiene git diff --check Passed on 2026-06-13 after current code/documentation changes.

Tracker Update Recommendations

Update docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md only after this review is accepted, using these rows:

Tracker Row Suggested Status Rationale
Reused Chatwoot frontend verification Keep Review; attach passed browser evidence API, browser, enterprise API, and enterprise browser smoke now pass, but fixture/realtime/provider live gates remain before claiming full direct-connect parity.
Serializer/envelope parity Keep Review; split into fixture-tested subrows Route parity is strong, but frontend direct-connect depends on exact payloads.
Route parity Mark generated evidence refreshed; do not mark exact 0 missing, but 9 parameter-compatible routes need tests/documented constraints.
Realtime parity Keep Review; attach payload fixture evidence Message/conversation mutation, typing/presence, notification, account-cache, browser subscription, and user notification preference fixtures are covered; live browser smoke also verifies the current notification list and profile notification-preference store requests; remaining risk is provider live-smoke coverage without configured external credentials.
Search/indexing Keep Review; retain live Meilisearch gate Live enterprise-browser smoke reran the full Meilisearch reindex/search path and captured seeded conversation/message/contact/company/article payloads; company/article hooks assert updated objects reach indexing.
Widget/public/help-center Keep Review; retain browser smoke evidence Public/widget flows are highly frontend-visible and include multipart/session/locale edge cases; pre-chat config shape, cw_conversation query and cookie session reuse across config boot, message history, labels, and events, locale redirect/fallback, portal/category/article JSON, dashboard article CRUD payloads, category filters, sitemap URLs, suffix-route markdown/tracking-pixel dispatch, raw markdown content, 1x1 pixel cache/body, view side effects, and widget browser-smoke harness navigation are covered; the latest enterprise browser report passed widget mount, messages, inbox-members, and campaigns checks.
Enterprise features Keep Review; split provider-enabled vs feature-gated behavior Frontend should see either working behavior or stable disabled states, never fake success.

Immediate Next Work Items

  1. Keep the expanded live enterprise browser smoke as a release gate now that reports/live API v2 shape, value, CSV, auth, store-refresh, CSAT dashboard/public/review-note, custom-role permission, enterprise account literal-path and billing error boundaries, SLA inbox association side effects, Captain document/response frontend filters and response-builder jobs, WhatsApp signed delivery/read/failure status callback, Twilio delivered/read/failed delivery-status callback, TikTok read-receipt callback retry fixture, Facebook page setup/reauthorize callback fixtures, root Instagram/TikTok/Twitter OAuth callback config fixtures, TikTok/LINE/Twilio setup payload/config fixtures, LINE valid/missing/invalid signature webhook fixtures, Telegram setup reauthorization fallback, Facebook/Instagram delivery/read receipt webhook fixtures, background Copilot follow-up job, widget cw_conversation query/cookie config/message/labels/events drift, ActiveStorage direct-upload create/complete, and help-center locale/JSON/sitemap/markdown/pixel slices are fixture-covered.
  2. Keep the added notification list/profile preference browser-store smoke as a drift guard; core conversation/message, typing/presence, notification/cache, browser subscription, and user preference contracts are now fixture-covered.
  3. Keep account actions/contact merge, agent create, agent-bot account, assignable-agent, assignment-policy, agent-capacity, custom-attribute definition, audit-log, automation-rule, campaign, canned-response, bulk-action, Captain/Copilot, and core channel-provider fixtures as drift guards for Woochat CRM/settings/enterprise/channel route changes.
  4. Keep provider fixtures as drift guards for future payload changes: inbox assignment override, WhatsApp health/status/failure, Twilio delivered/read/failed delivery-status, TikTok read-receipt, Facebook/Instagram delivery/read receipt, Facebook page setup, root OAuth callback config/upsert/error fallback, email OAuth token payload fallback, Linear/Shopify/Notion integration callback error fallback, Dyte meeting/add-participant, Linear runtime operations, Slack create/delete/list-channel routes, generic integration hooks, Telegram setup reauthorization fallback, TikTok setup, LINE setup, and Twilio setup fixtures are now covered.
  5. Keep live Meilisearch search smoke as a release gate and retain search_reindex.log, search_conversations.json, search_messages.json, search_contacts.json, search_companies.json, and search_articles.json evidence under .tmp/frontend-smoke-live/ when rerun.
  6. Attach fixture/smoke evidence to docs/parity/frontend_contract_inventory.md and docs/parity/contract_fixture_coverage.md rows as slices are proven.
    • Current inventory backlog is 0 rows after closing changelog external-Hub triage, voice, WhatsApp authorization, companies, contact notes, contacts, conversations top-level labels/unread-counts, CSAT reports, custom roles, custom filters, dashboard apps, auth/profile literals from dashboard/api/endPoints.js, help-center dashboard APIs, inbox conversation/message APIs, and inbox health/member/inbox APIs, Dyte/Linear/Shopify integrations, labels, live reports, macros, MFA, notification subscriptions, notifications, Notion authorization, onboarding, search, SLA policies, applied-SLA reports, SAML settings, summary reports, generic integrations, account literal paths, agent-capacity literal paths, agent bulk-create literal triage, article literal triage, automation literal triage, company literal runtime paths, contacts literal runtime paths, conversations literal label/unread-count paths, endPoints.spec.js legacy constants, and CSAT reports literal runtime paths, and inbox conversation literal runtime paths, and inbox message literal runtime path, and inbox literal runtime paths, and Dyte/Linear/Slack/generic integrations literal runtime paths, and labels/macros/notifications/reports/search/SLA literal runtime paths, teams/summary-reports/user-notification-settings/webhooks/year-in-review/CSAT public runtime paths, and widget literal runtime paths.
    • Evidence closure moved from inventory backlog to release gates on 2026-06-13: route dump/parity regeneration, git diff --check, full go test ./..., and live enterprise Woochat/browser smoke all passed.
  7. Add new provider-disabled/provider-enabled fixture tests only when Woochat introduces new channel setup, callback, or delivery-status payloads.
  8. Re-run full go test ./..., go run ./cmd/dump_routes, go run ./cmd/route_parity, and git diff --check after code changes, not just documentation updates.

Non-Goals And Assumptions

  • This review does not require changing Woochat/current Chatwoot frontend code.
  • This review now covers the Chatwoot/Woochat SAML settings API contract, but does not mark end-to-end SSO login, LDAP, or OIDC fully complete; those remain deployment/feature-gated unless scope changes.
  • This review does not claim live provider behavior is complete without configured provider smoke evidence.
  • This review treats reference/chatwoot as the frontend contract because no separate local Woochat checkout was found.