Files
gochat/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md
T

38 KiB

Chatwoot Parity Development Plan

Updated: 2026-06-04

Goal

Build GoChat as a Go backend that can directly reuse the frontend from reference/chatwoot. The backend API, data contracts, side effects, permissions, and runtime behavior must match the local reference/chatwoot repository first. Existing docs are secondary when they conflict with the reference implementation.

Confirmed Decisions

  • Frontend: reuse Chatwoot frontend directly. Backend compatibility is mandatory.
  • Baseline: reference/chatwoot is the source of truth for routes, controllers, models, serializers, jobs, and service behavior.
  • Immediate order: keep go test ./... green first, then deepen Chatwoot behavior parity.
  • Search: final implementation must use Meilisearch. DB/LIKE search is not acceptable as the final engine.
  • Enterprise scope: exclude SSO/SAML/LDAP/OIDC. Include the remaining paid features already present in planning and code: SLA, Audit, CustomRole, AgentCapacity, Captain/Copilot, CSAT, InboxLimit, automation, macros, assignment policies, and related limits/workflows.

Current Baseline

  • go test ./... passes.
  • Route dump succeeds with TOTAL: 791.
  • Route parity artifacts now exist under docs/parity/ and are generated by cmd/route_parity.
  • Tracked frontend-critical route audit covers 251 Chatwoot routes: 251 exact, 0 method-compatible, 0 parameter-compatible, 0 missing.
  • Handler test stability fixes are committed into the baseline before feature parity work continues.
  • .codegraph/ is generated indexing output and is not part of tracked product code.

Execution Snapshot

Phase Name Status Blocking gaps
Phase 0 Test and route baseline Done none
Phase 1 Meilisearch search engine Review live Meilisearch integration and document-shape parity still need reference verification
Phase 2 Route and controller parity audit Doing Ruby/Bundler unavailable, so Chatwoot route extraction currently uses static routes.rb fallback
Phase 3 Data and serializer parity Planned needs route-gap priorities from Phase 2
Phase 4 Enterprise feature completion Planned excluded SSO family must stay out of scope; all other enterprise features remain included
Phase 5 Background jobs and integrations Planned durable worker choice and job parity are open
Phase 6 Core placeholder burn-down Planned placeholders must be converted into real Chatwoot-compatible behavior
Phase 7 Verification harness Planned route/JSON/frontend smoke harness not complete

Tracking Artifacts

Artifact Purpose Update rule
docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md Master execution plan and status ledger. Update in every parity commit.
docs/parity/gochat_routes.txt Generated Go route inventory. Regenerate after every route change.
docs/parity/route_parity.md Generated tracked route comparison against reference/chatwoot/config/routes.rb. Regenerate after every route-tracking or route-registration change.
cmd/route_parity Static route parity generator. Extend whenever a new Chatwoot route group enters the tracked critical set.
.hermes/plans/2025-05-24-global-search-meilisearch.md Original Meilisearch implementation plan. Mine for context only; this document is now the active tracker.
.hermes/plans/2026-05-24-automation-macro-csat.md Original automation, macro, and CSAT implementation plan. Mine for context only; this document is now the active tracker.
docs/requirements/*.md Reference notes extracted from Chatwoot modules. Use as helper material after checking reference/chatwoot directly.

Immediate Execution Queue

This is the ordered queue for the next implementation slices. Do not skip the route and test gates even when working on deeper business behavior.

Order Work item Primary phase Done when Status
Q1 Expand tracked route parity to Captain/Copilot, assignment policies, widget, public inbox/contact/conversation, public CSAT, v2 reports, summary reports, and live reports. Phase 2 cmd/route_parity tracks these groups and docs/parity/route_parity.md lists every missing/mismatched route. Done
Q2 Patch route aliases discovered by Q1, especially Chatwoot widget/public paths such as /api/v1/widget/... versus existing /widget/.... Phase 2 Missing tracked routes return to zero or are explicitly documented with implementation tasks. Done
Q3 Add route boot regression coverage for wildcard conflict groups before expanding more Rails-style resources. Phase 2 Router tests cover nested dynamic resources that previously risked Gin conflicts. Done
Q4 Start serializer parity fixtures for auth/session, conversations/messages, contacts/companies, inboxes, notifications, and search. Phase 3 Each area has at least one reference fixture and Go response test. Doing
Q5 Review Meilisearch document shape and endpoint payloads against Chatwoot frontend consumers. Phase 1 and Phase 3 Search remains Meilisearch-first and payload mismatches are fixed or tracked. Todo
Q6 Burn down enterprise gaps in this order: SLA, assignment policy and capacity, CSAT, automation/macros, Audit, CustomRole, InboxLimit, Captain/Copilot. Phase 4 and Phase 5 Each feature passes route, persistence, auth, side-effect, response, and test checks. Todo
Q7 Add frontend smoke harness using the reused Chatwoot frontend once core API flows boot end-to-end. Phase 7 Login, inbox list, conversation list/detail, message send, contact view, and widget init run without frontend adapters. Todo

Phase 0: Test And Route Baseline

Status: done.

Checklist:

  • Fix internal/handler/api/v1 route param mismatches around :account_id, :id, and resource IDs.
  • Fix malformed test routes that conflict with Gin wildcard rules.
  • Add defensive handling for zero-value services in handler edge tests.
  • Align handler error responses where tests encode the expected Chatwoot-compatible status category.
  • Keep platform routes bootable and dumpable.
  • Verify go test ./....
  • Verify go run ./cmd/dump_routes.

Verification commands:

env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./...
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go run ./cmd/dump_routes

Phase 1: Meilisearch Search Engine

Status: review.

Source material:

  • .hermes/plans/2025-05-24-global-search-meilisearch.md
  • reference/chatwoot search controllers, models, and indexing behavior
  • Current local packages under internal/search, internal/handler/api/v1/search_handler.go, and entity repositories

Checklist:

  • Define a stable SearchEngine interface for Meilisearch-backed search and indexing.
  • Add search config for engine, host, API key, and index prefix.
  • Implement Meilisearch client wrapper with index bootstrapping and settings.
  • Define per-entity documents for conversations, messages, contacts, companies, articles, and help-center content as required by Chatwoot frontend behavior.
  • Wire create/update/delete hooks from services into indexing.
  • Add batch reindex command for existing data.
  • Keep DB search only as explicit development fallback, not as final production mode.
  • Add tests with a mocked search engine and integration hooks that can run without a live Meilisearch instance.
  • Document required Meilisearch environment variables and local startup flow.

Acceptance:

  • Global search endpoint and entity search endpoints return Chatwoot-compatible payloads.
  • Search results are account-scoped.
  • Search indexing survives entity updates and deletes.
  • go test ./... stays green.

Tracking table:

ID Task Target files Reference source Status
P1.1 Add SearchConfig with engine, host, API key, index prefix, env binding, and defaults. internal/config/config.go, configs/config.yaml, config tests .hermes/plans/2025-05-24-global-search-meilisearch.md Done
P1.2 Add stable engine contract for search, indexing, deletes, batch indexing, and close. internal/search/engine.go Chatwoot global/entity search behavior Done
P1.3 Implement Meilisearch engine wrapper, index naming, bootstrap, sortable/filterable/searchable settings. internal/search/engine_meili.go Chatwoot search models/services Review
P1.4 Keep existing DB search as explicit dev fallback only. Production config must prefer Meilisearch. internal/search/engine_db.go, internal/search/search_service.go User decision on Meilisearch Done
P1.5 Define documents and serializers for conversations, messages, contacts, companies, articles, and help-center content. internal/search/engine.go reference/chatwoot models/serializers Review
P1.6 Wire create/update/delete hooks from entity services into async or synchronous indexing boundary. internal/service/*, internal/search/search_service.go, internal/app/bootstrap.go Chatwoot callbacks/jobs Done
P1.7 Add batch reindex command and account/entity filters. cmd/reindex_search Chatwoot reindex/search tasks Done
P1.8 Add mocked engine tests and service integration tests without requiring live Meilisearch. internal/search/engine_test.go, internal/config/config_test.go Existing test style Done
P1.9 Document Meilisearch env vars and local startup flow. this doc, ops docs if needed Hermes plan Done

Meilisearch local flow:

docker run --rm -p 7700:7700 -e MEILI_MASTER_KEY=gochat_dev getmeili/meilisearch:latest
GOCHAT_SEARCH_ENGINE=meilisearch GOCHAT_SEARCH_HOST=http://localhost:7700 GOCHAT_SEARCH_API_KEY=gochat_dev go run ./cmd/reindex_search -types all

Search environment variables:

Variable Default Notes
GOCHAT_SEARCH_ENGINE meilisearch Use db only for explicit local fallback.
GOCHAT_SEARCH_HOST http://localhost:7700 Meilisearch endpoint.
GOCHAT_SEARCH_API_KEY empty Set to Meilisearch master/search key when enabled.
GOCHAT_SEARCH_INDEX_PREFIX gochat_ Prefixes indexes such as gochat_conversations.
GOCHAT_SEARCH_TIMEOUT_SECONDS 5 HTTP timeout for search/index requests.

Phase 2: Route And Controller Parity Audit

Status: doing.

Checklist:

  • Dump Chatwoot route source declarations from reference/chatwoot/config/routes.rb.
  • Dump GoChat routes with cmd/dump_routes.
  • Build a first tracked route parity table covering method, path, controller, source, and route status.
  • Prioritize first frontend-critical API v1 account routes used by the Chatwoot web app.
  • Extend parity table with auth scope, request params, response serializer, and handler implementation status.
  • Patch first-batch route names and wildcard params where Gin constraints require different internal names, while preserving external URLs.
  • Add regression tests for the contact conversations relation route added in this slice.
  • Expand route boot regression coverage for tracked Gin wildcard/param conflict groups.

Acceptance:

  • Route gap report is generated and checked in.
  • All currently implemented routes boot without panic.
  • Missing frontend-critical routes have tickets or implementation tasks.

Tracking table:

ID Task Artifact Status
P2.1 Generate Chatwoot route dump from reference/chatwoot. docs/parity/chatwoot_routes_static.md Review
P2.2 Generate GoChat route dump with cmd/dump_routes. docs/parity/gochat_routes.txt Done
P2.3 Produce route parity table: method, path, controller/handler, auth, request params, serializer, status. docs/parity/route_parity.md Review
P2.4 Mark frontend-critical gaps from Chatwoot web app route usage. docs/parity/route_parity.md Done
P2.5 Convert existing placeholders/stubs into tracked feature tasks instead of hidden debt. this doc and gap report Doing
P2.6 Add route boot regression tests for Gin wildcard/param conflicts. internal/router/router_test.go Done
P2.7 Track Captain/Copilot route group from routes.rb:62-89. cmd/route_parity, docs/parity/route_parity.md Done
P2.8 Track assignment policies and inbox assignment policy routes from routes.rb:306-313. cmd/route_parity, router Done
P2.9 Track widget API routes from routes.rb:442-472; keep /api/v1/widget as the Chatwoot-compatible surface. cmd/route_parity, router widget mount Done
P2.10 Track public API routes from routes.rb:569-585, including public inbox contacts, conversations, messages, and CSAT survey. cmd/route_parity, public handlers Done
P2.11 Track v2 reports, summary reports, and live reports from routes.rb:479-513. cmd/route_parity, reports handlers Done

Current Phase 2 route findings:

Type Count Required action
Exact tracked critical routes 251 Keep covered while expanding audit scope.
Method-compatible update routes 0 First tracked batch now has exact Rails-compatible method coverage.
Missing tracked critical routes 0 Current tracked frontend-critical route set has no route-level gaps.

Expanded tracked groups now covered by route parity:

Area Coverage
Agents and assignable agents CRUD/bulk-create route coverage for agents, plus assignable_agents#index.
Canned responses index/create/update/destroy account routes.
Custom attributes and custom filters index/show/create/update/destroy account routes.
Labels and team membership labels CRUD plus teams and team_members collection actions.
Notifications account-scoped notifications, notification_settings, unread_count, read_all, destroy_all, snooze, unread.
Inbox members Chatwoot account-scoped inbox_members create/show/update/destroy routes.
Inbox member actions agent_bot, set_agent_bot, sync_templates, health, register_webhook, reset_secret, avatar.
Captain/Copilot Assistants, assistant inboxes/scenarios, assistant responses, bulk actions, copilot threads/messages, custom tools, documents, preferences, and tasks.
Assignment policies Account assignment policies, nested inbox bindings, and inbox assignment policy routes.
Widget API Chatwoot /api/v1/widget/* route surface plus legacy /widget/* compatibility.
Public API Public inbox contact/conversation/message routes and public CSAT survey route.
Reports v2 /api/v2/accounts/:account_id summary reports, reports, and live reports.

New route groups tracked in this slice:

Area Chatwoot source Current Go surface observed Expected action
Captain/Copilot reference/chatwoot/config/routes.rb:62-89 Many /api/v1/accounts/:account_id/captain/... routes already existed. Added tracked critical set; route parity is exact.
Assignment policies reference/chatwoot/config/routes.rb:306-313 /assignment_policies and local /assignment_policies_v2 routes exist. Added tracked route set and aligned singular inbox assignment delete route.
Widget API reference/chatwoot/config/routes.rb:442-472 GoChat exposed many routes only under /widget. Added /api/v1/widget aliases; behavior parity remains tracked under Phase 3/6.
Public API reference/chatwoot/config/routes.rb:569-585 GoChat had public CSAT conversation routes. Added public inbox/contact/conversation/message route surface and Chatwoot public CSAT path.
Reports v2 reference/chatwoot/config/routes.rb:479-513 GoChat had report-style routes under /api/v1/accounts. Added exact v2 /api/v2/accounts/:account_id/... report paths.

Closed tracked critical route gaps in this slice:

Method Path Chatwoot controller Implementation note
GET /api/v1/accounts/:account_id/contacts/:contact_id/conversations api/v1/accounts/contacts/conversations#index Added contact conversation relation endpoint returning Chatwoot payload shape, optional inbox_id, and latest-20 ordering.
POST /api/v1/accounts/:account_id/contacts/export api/v1/accounts/contacts#export Added Chatwoot async request path returning 200 OK; existing CSV download route remains for local compatibility.
POST /api/v1/accounts/:account_id/conversations/:conversation_id/toggle_priority api/v1/accounts/conversations#toggle_priority Added Chatwoot action path returning 200 OK.

Closed Rails update method gaps:

Expected Existing GoChat route Implementation note
PUT /api/v1/accounts/:account_id/conversations/:conversation_id PATCH /api/v1/accounts/:account_id/conversations/:conversation_id Added PUT alias to the same update handler.
PUT /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id PATCH /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id Added PUT alias to the same update handler.

Phase 2 commands:

env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go run ./cmd/dump_routes > docs/parity/gochat_routes.txt
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go run ./cmd/route_parity

Phase 3: Data And Serializer Parity

Status: planned.

Checklist:

  • Compare key Chatwoot serializers/entities with Go response payloads.
  • Align account, user, inbox, conversation, message, contact, company, team, label, canned response, campaign, help center, and notification payload shapes.
  • Verify timestamps, IDs, enum strings, nested objects, pagination metadata, and error envelopes.
  • Add fixture-driven tests for payload compatibility.

Acceptance:

  • Chatwoot frontend can consume the payloads without adapter code.
  • Serializer deviations are documented only where GoChat intentionally differs.

Frontend-critical API groups to audit first:

ID Area Scope Status
P3.1 Auth/session/profile Login, logout, current user, profile, availability, notification settings. Todo
P3.2 Accounts/users/teams Account settings, users, agents, teams, invitations, roles, permissions. Todo
P3.3 Inboxes/channels Inbox CRUD, assignable agents, avatars, channel config, business hours, widget config. Todo
P3.4 Conversations/messages List filters, status changes, assignment, labels, private notes, attachments, drafts, typing/read events. Todo
P3.5 Contacts/companies CRUD, merge, labels, notes, custom attributes, import/export, conversations relation. Todo
P3.6 Labels/custom attributes/custom filters Create/update/list behavior and exact response shapes. Todo
P3.7 Notifications/reports/help center/campaigns Frontend-visible payloads and pagination/error envelopes. Todo
P3.8 Widget/public APIs Widget init, campaigns, config, contact, conversations, messages, direct uploads, public inbox flow, public CSAT. Doing
P3.9 Search payloads Global search and entity search documents backed by Meilisearch. Review

Serializer parity work plan:

Order Endpoint family Reference sources Verification artifact Status
S1 Auth and profile reference/chatwoot/app/controllers/api/v1/profile*, frontend auth API usage fixture tests for current user/profile payloads Todo
S2 Conversations and messages reference/chatwoot/app/controllers/api/v1/accounts/conversations*, serializers/entities fixture tests for index/show/message create/update Todo
S3 Contacts and companies reference/chatwoot/app/controllers/api/v1/accounts/contacts*, companies* fixture tests for list/show/search/merge/relation payloads Todo
S4 Inboxes and channels reference/chatwoot/app/controllers/api/v1/accounts/inboxes*, channel controllers fixture tests for inbox CRUD, channel settings, widget config Todo
S5 Notifications and settings reference/chatwoot/app/controllers/api/v1/accounts/notifications* fixture tests for notification list/actions/settings Todo
S6 Reports and CSAT reference/chatwoot/app/controllers/api/v1/accounts/reports*, csat_survey_responses* fixture tests for report filters and CSAT metrics/list Todo
S7 Widget/public reference/chatwoot/app/controllers/api/v1/widget*, public/api/v1* widget smoke fixtures and public flow tests Doing
S8 Search reference/chatwoot search controllers plus frontend search client Meilisearch-backed search response fixtures Todo

Serializer comparison rules:

  • Compare against reference/chatwoot serializers/entities before changing Go responses.
  • Prefer fixture-driven tests for exact JSON shape, enum strings, pagination metadata, and error envelopes.
  • Preserve Chatwoot field names even if Go internal naming differs.

Phase 4: Enterprise Feature Completion

Status: doing.

Excluded:

  • SSO
  • SAML
  • LDAP
  • OIDC

Included checklist:

  • SLA policies and SLA event tracking.
  • Audit logs and admin-readable audit endpoints.
  • Custom roles and permission checks.
  • Agent capacity and assignment limits.
  • Assignment policies and auto-assignment compatibility.
  • Captain/Copilot assistant, custom tools, scenarios, documents, responses, and inbox bindings.
  • CSAT survey response flow, metrics, filters, and review notes.
  • Inbox limits and account/inbox usage enforcement.
  • Automation rules, macros, execution logs, and action side effects.

Acceptance:

  • Each included feature has routes, persistence, authorization, tests, and Chatwoot-compatible response behavior.
  • Unsupported SSO family features are explicitly disabled or omitted without breaking frontend navigation for enabled features.

Enterprise tracking table:

ID Feature Existing Go surface Required next work Status
P4.1 SLA policies/events internal/model/sla_policy.go, internal/model/sla_event.go, internal/service/sla_policy_service.go, internal/service/sla_event_service.go, internal/handler/api/v1/sla_policy_handler.go Compare with Chatwoot SLA behavior; wire lifecycle events and breach tracking; add frontend payload tests. Todo
P4.2 Audit logs internal/model/audit.go, internal/service/audit_service.go, internal/repository/audit_repo.go, internal/handler/api/v1/audit_handler.go Ensure every mutating enterprise/core action emits audit events and filters match Chatwoot. Todo
P4.3 Custom roles/permissions internal/model/custom_role.go, internal/service/custom_role_service.go, internal/middleware/role_check.go, internal/handler/api/v1/custom_role_handler.go Align permission keys, inherited roles, authorization failures, and admin UX payloads. Todo
P4.4 Agent capacity internal/model/agent_capacity_policy.go, internal/service/agent_capacity_policy_service.go, internal/handler/api/v1/agent_capacity_handler.go, internal/autoassignment/* Enforce capacity in assignment path and auto-assignment; add limit tests. Todo
P4.5 Inbox limits internal/model/inbox_limit.go, internal/service/inbox_limit_service.go, internal/repository/inbox_limit_repo.go, internal/handler/api/v1/inbox_limit_handler.go Enforce account/inbox usage limits and frontend-compatible responses. Todo
P4.6 Captain/Copilot internal/model/captain_models.go, internal/model/copilot_models.go, internal/service/captain_*, internal/service/copilot_*, internal/handler/api/v1/captain_*, internal/handler/api/v1/copilot_handler.go Complete assistant, tools, scenarios, documents, responses, inbox bindings, suggestions, and streaming compatibility. Todo
P4.7 CSAT internal/csat/*, internal/automation/csat_survey_*, internal/handler/api/v1/csat_*, internal/service/csat_metrics_service.go Wire resolve-triggered survey send, public update flow, metrics, review notes, filters. Todo
P4.8 Automation and macros internal/automation/*, internal/handler/api/v1/automation_rule_handler.go, internal/handler/api/v1/macro_handler.go Finish action side effects, execution logs, webhook/email transcript delivery, and rule trigger coverage. Todo
P4.9 Assignment policies internal/autoassignment/*, internal/automation/agent_bot_rule_listener.go Match Chatwoot assignment policy behavior and availability/capacity rules. Todo

Enterprise acceptance gates:

Feature Required gates before Done Reference notes
SLA Field names and units match Chatwoot; only_during_business_hours exists; applied SLA state machine is wired; breach events create notifications; delete/update statuses match Rails behavior. docs/verification/SLA_ASSIGNMENT_POLICY_V2_COMPATIBILITY_REPORT.md, docs/requirements/M11-enterprise-features.md
Audit Mutating account resources emit audit records with actor, IP, request UUID, auditable type/id, associated account, and changes; admin list pagination matches Chatwoot. docs/requirements/M11-enterprise-features.md
CustomRole Permission keys match Chatwoot; AccountUser permission resolution honors custom roles; deleting a role nullifies users; admin-only policy is enforced. docs/requirements/M1-accounts-and-users.md, docs/requirements/M11-enterprise-features.md
AgentCapacity and InboxLimit Assignment and auto-assignment respect per-inbox conversation limits; account/inbox limits are enforced in create paths and surfaced to frontend. docs/requirements/M1-accounts-and-users.md, docs/requirements/M5-team-and-assignment.md
Assignment policies V2 route and payload shape match Chatwoot; policy selection is applied during manual and automatic assignment; availability and capacity interact correctly. reference/chatwoot/config/routes.rb:306-313
CSAT Resolve event sends survey once; widget/WhatsApp/Twilio paths are modeled where supported; public submit/update honors lock window; metrics and download filters match Chatwoot. .hermes/plans/2026-05-24-automation-macro-csat.md, docs/requirements/M7-reporting-and-csat.md
Automation and macros Conditions/actions match Chatwoot; macro execute side effects are real; execution logs and async webhook/email transcript actions are durable and retryable. .hermes/plans/2026-05-24-automation-macro-csat.md, docs/requirements/M6-automation-and-templates.md
Captain/Copilot Assistant, tools, documents, responses, scenarios, inbox bindings, copilot threads/messages, tasks, streaming, and LLM/tool-call behavior are implemented or explicitly feature-gated. docs/requirements/M10-captain-and-copilot.md

Excluded tracking table:

Feature Decision Required handling
SSO Excluded Do not prioritize implementation. Existing surfaces should not block core frontend use.
SAML Excluded Do not expand beyond already present code unless needed to disable safely.
LDAP Excluded Omit from parity scope.
OIDC Excluded Omit from parity scope.

Phase 5: Background Jobs And Integrations

Status: planned.

Known hotspots:

  • internal/worker/worker.go is still mostly placeholder.
  • internal/automation/action_service.go has pending webhook/email transcript work.
  • internal/automation/csat_survey_listener.go has pending CSAT enable/send behavior.
  • internal/auth/webhook_registry.go has pending signature verification for Facebook/WhatsApp.
  • internal/service/analytics_service.go has placeholder analytics paths.

Checklist:

  • Map Chatwoot jobs/listeners to Go worker responsibilities.
  • Implement durable job dispatch for automation, CSAT, notifications, webhooks, and search indexing.
  • Add retry and failure logging for external calls.
  • Add tests for job enqueueing and idempotency.

Acceptance:

  • User-visible side effects do not depend on synchronous handler-only execution.
  • Failed background work is observable and retryable.

Tracking table:

ID Task Current hotspot Status
P5.1 Choose and wire durable job runner compatible with current Go stack. internal/worker/worker.go, internal/channel/dispatcher.go Todo
P5.2 Move search indexing into retryable jobs where Chatwoot uses callbacks/jobs. search services and worker Todo
P5.3 Implement automation webhook delivery with retry, timeout, and logs. internal/automation/action_service.go Todo
P5.4 Implement email transcript delivery once email infrastructure is available. internal/automation/action_service.go Todo
P5.5 Complete CSAT survey send listener and idempotency. internal/automation/csat_survey_listener.go, internal/csat/listener.go Todo
P5.6 Complete webhook signature verification for Facebook/WhatsApp/Twilio/provider paths. internal/auth/webhook_registry.go, channel providers Todo
P5.7 Replace placeholder analytics with real report builders/queries. internal/service/analytics_service.go, reporting services Todo

Phase 6: Core Product Placeholder Burn-down

Status: planned.

Purpose: route parity is not enough; existing handlers that return placeholder JSON must be converted into real Chatwoot-compatible behavior before the frontend can be reused directly.

Tracking table:

ID Area Known references Required next work Status
P6.1 Account APIs docs/ROUTE_GAP_ANALYSIS.md, account handlers Replace placeholder responses with repository-backed behavior and serializer tests. Todo
P6.2 Contact APIs docs/ROUTE_GAP_ANALYSIS.md, contact handlers/services Implement show/create/update/list/search relations, labels, notes, merge. Todo
P6.3 Conversation APIs docs/ROUTE_GAP_ANALYSIS.md, conversation handlers/services Implement frontend-critical filters, assignment, status, snooze, merge, bulk actions. Todo
P6.4 Message APIs docs/ROUTE_GAP_ANALYSIS.md, message handlers/services Implement create/list/delete, private notes, attachments, source attribution, events. Todo
P6.5 Inbox APIs docs/ROUTE_GAP_ANALYSIS.md, inbox handlers/services Implement CRUD, assignable agents, avatar, campaigns, channel settings, reset secret. Todo
P6.6 Widget/public APIs docs/ROUTE_GAP_ANALYSIS.md, widget/channel provider code, chatwootParityStub routes Implement init/config, campaigns, events, contact, conversations, messages, cable token, direct uploads, public inbox flows, and public CSAT with Chatwoot contracts. Doing
P6.7 Webhook ingress internal/router/router.go, internal/handler/webhook/*, channel providers Replace generic placeholder with provider-specific verified ingestion and dispatch. Todo

Phase 7: Verification Harness

Status: planned.

Checklist:

  • Add repeatable command to compare Chatwoot and GoChat route dumps.
  • Add fixture-based JSON parity tests for major frontend endpoints.
  • Add Meilisearch mock tests and optional integration test mode gated by env vars.
  • Add frontend smoke path using reused Chatwoot frontend once backend boot flow is ready.
  • Keep a generated gap report in docs/parity/ with date, reference commit, Go commit, and pass/fail summary.

Required verification before each feature commit:

env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./...
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go run ./cmd/dump_routes

Verification milestone gates:

Gate Command or artifact Required before
V1 env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./... Every commit that changes Go code.
V2 env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go run ./cmd/dump_routes > docs/parity/gochat_routes.txt Every route/router/handler registration change.
V3 env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go run ./cmd/route_parity Every tracked route or route generator change.
V4 JSON fixture parity tests for touched endpoint family. Every serializer or handler payload change.
V5 Optional live Meilisearch integration test gated by env var. Search behavior changes that claim Meilisearch compatibility.
V6 Reused Chatwoot frontend smoke flow. Before declaring frontend reuse viable.

Task Status Legend

  • Todo: not started or only skeleton exists.
  • Doing: implementation is underway in the current working tree.
  • Review: code is implemented and needs parity/test verification.
  • Done: committed, tested, and linked to the matching reference/chatwoot behavior.
  • Blocked: needs a decision, missing dependency, or reference behavior cannot yet be reproduced.

Ongoing Tracking Rules

  • Every parity task should name the matching file or behavior in reference/chatwoot.
  • Every route change should keep cmd/dump_routes passing.
  • Every phase must keep go test ./... green before moving on.
  • Test-only route fixes should be limited to malformed tests. Production route changes must preserve external Chatwoot-compatible URLs.
  • New search work must target Meilisearch first.
  • Update this document in the same commit as each completed parity slice: change task status, add verification command output summary, and link the touched reference/chatwoot behavior.
  • Do not count a feature as done because a model/handler exists; it is done only when route behavior, persistence, authorization, side effects, response shape, and tests are covered.
  • Keep .codegraph/ and other generated local analysis artifacts out of product commits unless explicitly requested.

Progress Log

  • 2026-06-04: Baseline stabilized and committed as 42cdab8 chore: stabilize chatwoot parity baseline; go test ./... passed and route dump reported TOTAL: 704.
  • 2026-06-04: Phase 1 search foundation added: Meilisearch config/env defaults, SearchEngine contract, Meilisearch HTTP wrapper with bootstrap/settings, DB fallback adapter, document builders, reindex command, and no-live-Meilisearch tests. Verified go test ./... in unsandboxed mode because miniredis/httptest need local sockets; route dump still reports TOTAL: 704.
  • 2026-06-04: Phase 1 indexing hooks wired for conversations, messages, contacts, companies, and articles. Create/update/delete paths now call the service-layer SearchIndexer boundary, bootstrap injects the Meilisearch-backed search service, and unit tests cover each entity hook path.
  • 2026-06-04: Phase 2 route parity tracking added. Ruby/Bundler are unavailable in this workspace, so cmd/route_parity records static Chatwoot route DSL declarations from reference/chatwoot/config/routes.rb, consumes cmd/dump_routes output, and writes docs/parity/route_parity.md. First tracked critical route summary: 76 exact, 2 method-compatible, 0 parameter-compatible, 3 missing out of 81; GoChat route dump remains TOTAL: 704.
  • 2026-06-04: First tracked Phase 2 route gaps closed. Added Chatwoot-compatible contact conversations, contact export POST, conversation toggle_priority, and PUT aliases for conversation/message updates; fixed contact handlers to accept :account_id as well as legacy :id. Regenerated parity report: 81 exact, 0 method-compatible, 0 parameter-compatible, 0 missing out of 81; route dump now reports TOTAL: 709.
  • 2026-06-04: Expanded Phase 2 route parity from 81 to 138 tracked frontend-critical account routes. Added account-scoped notification routes, notification_settings PUT alias, and Chatwoot account-level inbox_members create/show/update/destroy handlers. Regenerated parity report: 138 exact, 0 method-compatible, 0 parameter-compatible, 0 missing out of 138; route dump now reports TOTAL: 723.
  • 2026-06-04: Expanded Phase 2 route parity from 138 to 251 tracked frontend-critical routes. Added tracking and route-level coverage for Captain/Copilot, assignment policies, /api/v1/widget, public inbox/contact/conversation/message APIs, public CSAT survey, and /api/v2 reports. Regenerated parity report: 251 exact, 0 method-compatible, 0 parameter-compatible, 0 missing out of 251; route dump now reports TOTAL: 791. Added router boot regression coverage for Captain static/dynamic routes, widget collection routes, public nested message routes, and v2 reports.
  • 2026-06-04: Started Phase 3/6 widget behavior parity for the reused Chatwoot frontend. /api/v1/widget/config now returns Chatwoot-style website_channel_config, contact pubsub token, and global config; /api/v1/widget/messages accepts X-Auth-Token and nested message.content, returns Chatwoot message shape, and exposes latest messages as {payload, meta}; /api/v1/widget/contact and core conversation actions now route to real handlers instead of parity stubs. Legacy /widget/* response compatibility is preserved. Focused widget/service/router tests pass.
  • 2026-06-04: Continued Phase 3/6 widget behavior parity. Replaced more /api/v1/widget stubs with handlers for campaigns, events, inbox_members, labels, and label removal. Inbox member payload now follows Chatwoot {payload: [...]} shape; campaigns return enabled inbox campaigns with trigger rules; events validate website/contact token context and return 204; labels mutate the latest widget conversation only when the label exists in the account. Added focused widget handler coverage for available agents, events, and label add/remove. Remaining widget stubs: message update, transcript, contact/set_user, and Dyte participant integration; public inbox/contact/conversation/message routes are still placeholder-backed.
  • 2026-06-04: Completed the remaining /api/v1/widget stub burn-down. Message update now persists submitted email/form values and identifies the contact; contact/set_user validates identifier HMAC, supports verified contact identification, and returns widget_auth_token when the contact context changes; conversation transcript returns Chatwoot-compatible status behavior around missing conversations; Dyte participant endpoint validates integration messages and returns a meeting token payload. Added model/repository support for contact inbox HMAC verification and identifier lookup. Public inbox/contact/conversation/message routes remain the next P6.6 placeholder group.