feat(routes): close first chatwoot parity gaps
This commit is contained in:
@@ -17,9 +17,9 @@ Build GoChat as a Go backend that can directly reuse the frontend from `referenc
|
||||
## Current Baseline
|
||||
|
||||
- `go test ./...` passes.
|
||||
- Route dump succeeds with `TOTAL: 704`.
|
||||
- Route dump succeeds with `TOTAL: 709`.
|
||||
- Route parity artifacts now exist under `docs/parity/` and are generated by `cmd/route_parity`.
|
||||
- First tracked frontend-critical API v1 route audit covers 81 Chatwoot routes: 76 exact, 2 method-compatible, 0 parameter-compatible, 3 missing.
|
||||
- First tracked frontend-critical API v1 route audit covers 81 Chatwoot routes: 81 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.
|
||||
|
||||
@@ -128,8 +128,9 @@ Checklist:
|
||||
- [x] Build a first tracked route parity table covering method, path, controller, source, and route status.
|
||||
- [x] 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 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.
|
||||
- [x] Patch first-batch route names and wildcard params where Gin constraints require different internal names, while preserving external URLs.
|
||||
- [x] Add regression tests for the contact conversations relation route added in this slice.
|
||||
- [ ] Expand route boot regression coverage for all Gin wildcard/param conflict groups.
|
||||
|
||||
Acceptance:
|
||||
|
||||
@@ -144,32 +145,32 @@ Tracking table:
|
||||
| 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` | 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. | router and handler tests | Todo |
|
||||
| P2.6 | Add route boot regression tests for Gin wildcard/param conflicts. | router and handler tests | Doing |
|
||||
|
||||
Current Phase 2 route findings:
|
||||
|
||||
| Type | Count | Required action |
|
||||
| --- | --- | --- |
|
||||
| Exact tracked critical routes | 76 | Keep covered while expanding audit scope. |
|
||||
| Method-compatible update routes | 2 | Register both Rails-compatible update methods or verify frontend only calls the implemented method. |
|
||||
| Missing tracked critical routes | 3 | Implement exact Chatwoot external paths before frontend reuse. |
|
||||
| Exact tracked critical routes | 81 | 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 | First tracked frontend-critical batch has no route-level gaps. |
|
||||
|
||||
Missing tracked critical routes:
|
||||
Closed tracked critical route gaps in this slice:
|
||||
|
||||
| Method | Path | Chatwoot controller | Required next task |
|
||||
| Method | Path | Chatwoot controller | Implementation note |
|
||||
| --- | --- | --- | --- |
|
||||
| GET | `/api/v1/accounts/:account_id/contacts/:contact_id/conversations` | `api/v1/accounts/contacts/conversations#index` | Add contact conversation relation endpoint and serializer parity test. |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/export` | `api/v1/accounts/contacts#export` | Add POST export route; current GoChat has `GET /contacts/export`, which is not frontend-compatible. |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/toggle_priority` | `api/v1/accounts/conversations#toggle_priority` | Add Chatwoot action path; current GoChat has `PATCH /conversations/:conversation_id/priority`. |
|
||||
| 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`. |
|
||||
|
||||
Method-compatible routes requiring exact Rails method coverage:
|
||||
Closed Rails update method gaps:
|
||||
|
||||
| Expected | Existing GoChat route | Required next task |
|
||||
| Expected | Existing GoChat route | Implementation note |
|
||||
| --- | --- | --- |
|
||||
| `PUT /api/v1/accounts/:account_id/conversations/:conversation_id` | `PATCH /api/v1/accounts/:account_id/conversations/:conversation_id` | Add PUT alias or prove frontend only calls PATCH. |
|
||||
| `PUT /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id` | `PATCH /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id` | Add PUT alias or prove frontend only calls PATCH. |
|
||||
| `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:
|
||||
|
||||
@@ -361,3 +362,4 @@ env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go run ./cmd/d
|
||||
- 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`.
|
||||
|
||||
@@ -178,6 +178,7 @@ GET /api/v1/accounts/:account_id/contacts/
|
||||
GET /api/v1/accounts/:account_id/contacts/:contact_id
|
||||
GET /api/v1/accounts/:account_id/contacts/:contact_id/contact_inboxes
|
||||
GET /api/v1/accounts/:account_id/contacts/:contact_id/contactable_inboxes
|
||||
GET /api/v1/accounts/:account_id/contacts/:contact_id/conversations
|
||||
GET /api/v1/accounts/:account_id/contacts/:contact_id/notes
|
||||
GET /api/v1/accounts/:account_id/contacts/:contact_id/notes/:note_id
|
||||
GET /api/v1/accounts/:account_id/contacts/active
|
||||
@@ -486,6 +487,7 @@ POST /api/v1/accounts/:account_id/contacts/:contact_id/contact_inboxes
|
||||
POST /api/v1/accounts/:account_id/contacts/:contact_id/custom_attributes/
|
||||
POST /api/v1/accounts/:account_id/contacts/:contact_id/destroy_custom_attributes
|
||||
POST /api/v1/accounts/:account_id/contacts/:contact_id/notes
|
||||
POST /api/v1/accounts/:account_id/contacts/export
|
||||
POST /api/v1/accounts/:account_id/contacts/filter
|
||||
POST /api/v1/accounts/:account_id/contacts/import
|
||||
POST /api/v1/accounts/:account_id/contacts/merge
|
||||
@@ -501,6 +503,7 @@ POST /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:messa
|
||||
POST /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id/translate
|
||||
POST /api/v1/accounts/:account_id/conversations/:conversation_id/mute
|
||||
POST /api/v1/accounts/:account_id/conversations/:conversation_id/participants/
|
||||
POST /api/v1/accounts/:account_id/conversations/:conversation_id/toggle_priority
|
||||
POST /api/v1/accounts/:account_id/conversations/:conversation_id/toggle_status
|
||||
POST /api/v1/accounts/:account_id/conversations/:conversation_id/toggle_typing_status
|
||||
POST /api/v1/accounts/:account_id/conversations/:conversation_id/transcript
|
||||
@@ -659,6 +662,8 @@ PUT /api/v1/accounts/:account_id/captain/preferences/
|
||||
PUT /api/v1/accounts/:account_id/captain/scenarios/:scenario_id
|
||||
PUT /api/v1/accounts/:account_id/companies/:company_id
|
||||
PUT /api/v1/accounts/:account_id/contacts/:contact_id
|
||||
PUT /api/v1/accounts/:account_id/conversations/:conversation_id
|
||||
PUT /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id
|
||||
PUT /api/v1/accounts/:account_id/conversations/:conversation_id/whatsapp_calls/:call_id
|
||||
PUT /api/v1/accounts/:account_id/custom_attribute_definitions/:id
|
||||
PUT /api/v1/accounts/:account_id/custom_filters/:id
|
||||
@@ -702,4 +707,4 @@ PUT /platform/api/v1/banners/:id
|
||||
PUT /platform/api/v1/installation_configs/:id
|
||||
PUT /webhooks/:channel_type/:identifier
|
||||
TRACE /webhooks/:channel_type/:identifier
|
||||
TOTAL: 704
|
||||
TOTAL: 709
|
||||
|
||||
@@ -7,15 +7,13 @@ Generated from:
|
||||
|
||||
This first report covers frontend-critical API v1 account routes from `reference/chatwoot/config/routes.rb`. Ruby is not installed in the workspace, so Chatwoot routes are sourced from static route declarations instead of `bin/rails routes`.
|
||||
|
||||
Summary: 76 exact, 2 method-compatible, 0 parameter-compatible, 3 missing out of 81 tracked critical routes.
|
||||
Summary: 81 exact, 0 method-compatible, 0 parameter-compatible, 0 missing out of 81 tracked critical routes.
|
||||
|
||||
## Missing Critical Routes
|
||||
|
||||
| Method | Chatwoot Path | GoChat Match | Controller | Source | Status |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| GET | `/api/v1/accounts/:account_id/contacts/:contact_id/conversations` | `-` | `api/v1/accounts/contacts/conversations#index` | `routes.rb:211` | missing |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/export` | `-` | `api/v1/accounts/contacts#export` | `routes.rb:204` | missing |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/toggle_priority` | `-` | `api/v1/accounts/conversations#toggle_priority` | `routes.rb:159` | missing |
|
||||
| - | - | - | - | - | none |
|
||||
|
||||
## Method-Compatible Routes
|
||||
|
||||
@@ -23,8 +21,7 @@ These routes exist at the same path but with a compatible HTTP method. Rails res
|
||||
|
||||
| Method | Chatwoot Path | GoChat Match | Controller | Source | Status |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| PUT | `/api/v1/accounts/:account_id/conversations/:conversation_id` | `PATCH /api/v1/accounts/:account_id/conversations/:conversation_id` | `api/v1/accounts/conversations#update` | `routes.rb:134` | method-compatible |
|
||||
| PUT | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id` | `PATCH /api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id` | `api/v1/accounts/conversations/messages#update` | `routes.rb:142` | method-compatible |
|
||||
| - | - | - | - | - | none |
|
||||
|
||||
## Parameter-Compatible Routes
|
||||
|
||||
@@ -58,6 +55,7 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| GET | `/api/v1/accounts/:account_id/companies/search` | `/api/v1/accounts/:account_id/companies/search` | `api/v1/accounts/companies#search` | `routes.rb:181` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/contacts/` | `/api/v1/accounts/:account_id/contacts/` | `api/v1/accounts/contacts#index` | `routes.rb:197` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/contacts/:contact_id` | `/api/v1/accounts/:account_id/contacts/:contact_id` | `api/v1/accounts/contacts#show` | `routes.rb:197` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/contacts/:contact_id/conversations` | `/api/v1/accounts/:account_id/contacts/:contact_id/conversations` | `api/v1/accounts/contacts/conversations#index` | `routes.rb:211` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/contacts/:contact_id/notes` | `/api/v1/accounts/:account_id/contacts/:contact_id/notes` | `api/v1/accounts/contacts/notes#index` | `routes.rb:214` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/contacts/search` | `/api/v1/accounts/:account_id/contacts/search` | `api/v1/accounts/contacts#search` | `routes.rb:201` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/conversations/` | `/api/v1/accounts/:account_id/conversations/` | `api/v1/accounts/conversations#index` | `routes.rb:134` | exact |
|
||||
@@ -90,6 +88,7 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| POST | `/api/v1/accounts/:account_id/companies/:company_id/contacts/:contact_id` | `/api/v1/accounts/:account_id/companies/:company_id/contacts/:contact_id` | `api/v1/accounts/companies/contacts#create` | `routes.rb:188` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/` | `/api/v1/accounts/:account_id/contacts/` | `api/v1/accounts/contacts#create` | `routes.rb:197` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/:contact_id/notes` | `/api/v1/accounts/:account_id/contacts/:contact_id/notes` | `api/v1/accounts/contacts/notes#create` | `routes.rb:214` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/export` | `/api/v1/accounts/:account_id/contacts/export` | `api/v1/accounts/contacts#export` | `routes.rb:204` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/filter` | `/api/v1/accounts/:account_id/contacts/filter` | `api/v1/accounts/contacts#filter` | `routes.rb:202` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/import` | `/api/v1/accounts/:account_id/contacts/import` | `api/v1/accounts/contacts#import` | `routes.rb:203` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/` | `/api/v1/accounts/:account_id/conversations/` | `api/v1/accounts/conversations#create` | `routes.rb:134` | exact |
|
||||
@@ -98,6 +97,7 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/` | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/` | `api/v1/accounts/conversations/messages#create` | `routes.rb:142` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id/retry` | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id/retry` | `api/v1/accounts/conversations/messages#retry` | `routes.rb:145` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id/translate` | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id/translate` | `api/v1/accounts/conversations/messages#translate` | `routes.rb:144` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/toggle_priority` | `/api/v1/accounts/:account_id/conversations/:conversation_id/toggle_priority` | `api/v1/accounts/conversations#toggle_priority` | `routes.rb:159` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/toggle_status` | `/api/v1/accounts/:account_id/conversations/:conversation_id/toggle_status` | `api/v1/accounts/conversations#toggle_status` | `routes.rb:158` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/:conversation_id/transcript` | `/api/v1/accounts/:account_id/conversations/:conversation_id/transcript` | `api/v1/accounts/conversations#transcript` | `routes.rb:157` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/conversations/filter` | `/api/v1/accounts/:account_id/conversations/filter` | `api/v1/accounts/conversations#filter` | `routes.rb:139` | exact |
|
||||
@@ -111,6 +111,8 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| PUT | `/api/v1/accounts/:account_id/automation_rules/:automation_id` | `/api/v1/accounts/:account_id/automation_rules/:automation_id` | `api/v1/accounts/automation_rules#update` | `routes.rb:115` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/companies/:company_id` | `/api/v1/accounts/:account_id/companies/:company_id` | `api/v1/accounts/companies#update` | `routes.rb:179` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/contacts/:contact_id` | `/api/v1/accounts/:account_id/contacts/:contact_id` | `api/v1/accounts/contacts#update` | `routes.rb:197` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/conversations/:conversation_id` | `/api/v1/accounts/:account_id/conversations/:conversation_id` | `api/v1/accounts/conversations#update` | `routes.rb:134` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id` | `/api/v1/accounts/:account_id/conversations/:conversation_id/messages/:message_id` | `api/v1/accounts/conversations/messages#update` | `routes.rb:142` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/inboxes/:inbox_id` | `/api/v1/accounts/:account_id/inboxes/:inbox_id` | `api/v1/accounts/inboxes#update` | `routes.rb:252` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/macros/:macro_id` | `/api/v1/accounts/:account_id/macros/:macro_id` | `api/v1/accounts/macros#update` | `routes.rb:118` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/sla_policies/:id` | `/api/v1/accounts/:account_id/sla_policies/:id` | `api/v1/accounts/sla_policies#update` | `routes.rb:121` | exact |
|
||||
|
||||
Reference in New Issue
Block a user