20 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/chatwootis 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: 704. - 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.
Phase 0: Test And Route Baseline
Status: done.
Checklist:
- Fix
internal/handler/api/v1route 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: next.
Source material:
.hermes/plans/2025-05-24-global-search-meilisearch.mdreference/chatwootsearch 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
SearchEngineinterface 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: planned.
Checklist:
- Dump Chatwoot routes from
reference/chatwoot. - Dump GoChat routes with
cmd/dump_routes. - Build a tracked route parity table covering method, path, controller, auth scope, request params, and response serializer.
- Prioritize frontend-critical routes used by the Chatwoot web app.
- Patch route names and wildcard params where Gin constraints require different internal names, while preserving external URLs.
- Add regression tests for route groups that previously conflicted.
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.* |
Todo |
| P2.2 | Generate GoChat route dump with cmd/dump_routes. |
docs/parity/gochat_routes.* |
Todo |
| P2.3 | Produce route parity table: method, path, controller/handler, auth, request params, serializer, status. | docs/parity/route_parity.md |
Todo |
| P2.4 | Mark frontend-critical gaps from Chatwoot web app route usage. | docs/parity/route_parity.md |
Todo |
| P2.5 | Convert existing placeholders/stubs into tracked feature tasks instead of hidden debt. | this doc and gap report | Todo |
| P2.6 | Add route boot regression tests for Gin wildcard/param conflicts. | router and handler tests | Todo |
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 |
Serializer comparison rules:
- Compare against
reference/chatwootserializers/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: planned.
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 |
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.gois still mostly placeholder.internal/automation/action_service.gohas pending webhook/email transcript work.internal/automation/csat_survey_listener.gohas pending CSAT enable/send behavior.internal/auth/webhook_registry.gohas pending signature verification for Facebook/WhatsApp.internal/service/analytics_service.gohas 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 APIs | docs/ROUTE_GAP_ANALYSIS.md, widget/channel provider code |
Implement init, contact, conversations, messages, cable token with Chatwoot widget contracts. | Todo |
| 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
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 matchingreference/chatwootbehavior.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_routespassing. - 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/chatwootbehavior. - 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 reportedTOTAL: 704. - 2026-06-04: Phase 1 search foundation added: Meilisearch config/env defaults,
SearchEnginecontract, Meilisearch HTTP wrapper with bootstrap/settings, DB fallback adapter, document builders, reindex command, and no-live-Meilisearch tests. Verifiedgo test ./...in unsandboxed mode because miniredis/httptest need local sockets; route dump still reportsTOTAL: 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
SearchIndexerboundary, bootstrap injects the Meilisearch-backed search service, and unit tests cover each entity hook path.