feat(integrations): align app hook payloads
This commit is contained in:
@@ -37,14 +37,14 @@ Hermes plan landing map:
|
||||
|
||||
## Current Baseline
|
||||
|
||||
- Current tracking checkpoint: 2026-06-06 after this implementation checkpoint, prepared as `feat(webhooks): align account payloads`.
|
||||
- Latest implementation checkpoint: this checkpoint, prepared as `feat(webhooks): align account payloads`.
|
||||
- Current tracking checkpoint: 2026-06-06 after this implementation checkpoint, prepared as `feat(integrations): align app hook payloads`.
|
||||
- Latest implementation checkpoint: this checkpoint, prepared as `feat(integrations): align app hook payloads`.
|
||||
- Latest documentation/tooling checkpoint: `docs: land parity execution tracker`; this document is now the active follow-up plan and supersedes `.hermes/plans/*`.
|
||||
- Worktree status at this implementation checkpoint: P3.10 account webhook API parity is now implemented for reused dashboard `webhooks` settings flows. Account `/webhooks` now tracks Chatwoot `routes.rb:342`, exposes frontend `PATCH` update, returns Chatwoot Jbuilder `{ payload: { webhooks } }` and `{ payload: { webhook } }` payloads, accepts nested `{ webhook: ... }` request bodies plus legacy raw bodies, persists `name`, `inbox_id`, `url`, `subscriptions`, generated `secret`, scopes show/update/delete through current account, validates Chatwoot webhook events and HTTP/HTTPS URLs, returns empty `200 OK` delete, and keeps outgoing delivery event filtering on the same subscription storage. P3.9 account agent-bot API, P6.8 contact outbound voice call, P3.7d enterprise help-center article translation, P6.5 inbox agent-bot member actions, P6 message retry parity, P6 conversation custom-attribute response parity, and P3.7a-P3.7c help-center payload parity remain in Review. The fresh placeholder audit found remaining `chatwootParityStub` routes only in webhook handler-not-injected fallbacks, not in the reused dashboard account/contact/conversation/message/inbox critical path. P3.6 custom filters/custom attribute definitions and label CRUD are already in Review. B11.1a-B11.3e Captain/Copilot slices remain in Review; B12.1/B12.2/B12.3 smoke harnesses remain in Review; P5 durable job work through P5.13b is in Review. Next active implementation slice is another Phase 6 placeholder burn-down item or a new Phase 2/3 drift slice from fresh reference/smoke evidence.
|
||||
- Worktree status at this implementation checkpoint: P3.11 account integrations apps/hooks API parity is now implemented for the reused dashboard integrations settings flows. Account `/integrations/apps` and `/integrations/hooks` now track Chatwoot `routes.rb:345-348`, return Chatwoot-style raw app/hook payloads, expose frontend no-trailing-slash create/list routes plus hook `PATCH`, accept raw frontend hook bodies and nested `{ hook: ... }`, persist `app_id` and `reference_id`, seed the reference app catalog additions, scope hook show/update/delete through current account, serialize hook `status` as boolean and `hook_type` as account/inbox, include app `hooks`, `settings_form_schema`, and `visible_properties`, and return empty `200 OK` delete. P3.10 account webhook API, P3.9 account agent-bot API, P6.8 contact outbound voice call, P3.7d enterprise help-center article translation, P6.5 inbox agent-bot member actions, P6 message retry parity, P6 conversation custom-attribute response parity, and P3.7a-P3.7c help-center payload parity remain in Review. The fresh placeholder audit found remaining `chatwootParityStub` routes only in webhook handler-not-injected fallbacks, not in the reused dashboard account/contact/conversation/message/inbox critical path. P3.6 custom filters/custom attribute definitions and label CRUD are already in Review. B11.1a-B11.3e Captain/Copilot slices remain in Review; B12.1/B12.2/B12.3 smoke harnesses remain in Review; P5 durable job work through P5.13b is in Review. Next active implementation slice is another Phase 6 placeholder burn-down item or a new Phase 2/3 drift slice from fresh reference/smoke evidence.
|
||||
- `go test ./...` passes.
|
||||
- Route dump succeeds with `TOTAL: 865` after adding account webhook PATCH update route.
|
||||
- Route dump succeeds with `TOTAL: 869` after adding account integration app/hook no-trailing-slash and PATCH routes.
|
||||
- Route parity artifacts now exist under `docs/parity/` and are generated by `cmd/route_parity`.
|
||||
- Tracked frontend-critical route audit covers 320 Chatwoot routes: 313 exact, 0 method-compatible, 7 parameter-compatible, 0 missing. The 7 parameter-compatible routes are Gin-internal parameter-name differences for nested AgentCapacityPolicy users/inbox limits; the external URL shape is equivalent.
|
||||
- Tracked frontend-critical route audit covers 328 Chatwoot routes: 321 exact, 0 method-compatible, 7 parameter-compatible, 0 missing. The 7 parameter-compatible routes are Gin-internal parameter-name differences for nested AgentCapacityPolicy users/inbox limits; the external URL shape is equivalent.
|
||||
- `/api/v1/widget` stubs are burned down and public inbox/contact/conversation/message core flows are backed by real handlers.
|
||||
- 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.
|
||||
@@ -126,14 +126,15 @@ This table is the shortest authoritative handoff view. If an older lower section
|
||||
|
||||
| Priority | Workstream | Current state | Next checkpoint | Commit close rule |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Phase 2/3 drift | Tracked route parity is 0 missing for the current 320-route critical set; help-center portal/category/article routes from `routes.rb:385-404`, enterprise contact outbound voice call from `routes.rb:216`, account agent-bot routes from `routes.rb:94-97`, and account webhook routes from `routes.rb:342` are now explicitly tracked. Notification list/action serializers, user notification-settings raw payloads, campaigns raw payload/display-id routes, Devise password reset/confirmation payloads, CRM shared attachment payloads plus fixed 100-row attachment pagination, account/settings payloads, assignable-agent payloads, agent index full-list behavior, agent create/update/delete defaults/errors/scope, account agent-bot route/payload/mutation behavior, account webhook payload/mutation behavior, label CRUD payloads, custom filters, custom attribute definitions, contact outbound voice calls, and help-center portal/category/article payloads now match the inspected Chatwoot frontend contract. | Run the next evidence-backed route/controller/serializer drift audit. | Regenerate parity artifacts when routes change and add endpoint-family fixture tests. |
|
||||
| 1 | Phase 2/3 drift | Tracked route parity is 0 missing for the current 328-route critical set; help-center portal/category/article routes from `routes.rb:385-404`, enterprise contact outbound voice call from `routes.rb:216`, account agent-bot routes from `routes.rb:94-97`, account webhook routes from `routes.rb:342`, and account integration app/hook routes from `routes.rb:345-348` are now explicitly tracked. Notification list/action serializers, user notification-settings raw payloads, campaigns raw payload/display-id routes, Devise password reset/confirmation payloads, CRM shared attachment payloads plus fixed 100-row attachment pagination, account/settings payloads, assignable-agent payloads, agent index full-list behavior, agent create/update/delete defaults/errors/scope, account agent-bot route/payload/mutation behavior, account webhook payload/mutation behavior, integration app/hook payload behavior, label CRUD payloads, custom filters, custom attribute definitions, contact outbound voice calls, and help-center portal/category/article payloads now match the inspected Chatwoot frontend contract. | Run the next evidence-backed route/controller/serializer drift audit. | Regenerate parity artifacts when routes change and add endpoint-family fixture tests. |
|
||||
| 2 | Phase 6 placeholder audit | Widget/public/webhook critical placeholders are burned down; inbox WhatsApp health/register-webhook and sync-template drift are closed; fresh `rg` audit shows only webhook nil-handler fallbacks still call `chatwootParityStub`; dashboard conversation transcript/custom-attribute response drift and message retry status drift are closed. | Continue targeted account/contact/conversation/message/inbox drift from reference/smoke evidence. | `rg` placeholder audit is recorded and no reused-frontend blocker is ownerless. |
|
||||
| 3 | P3.9 account agent-bot API | Implemented for the reused dashboard AgentBots settings route with no-trailing-slash routes, PATCH update, raw Jbuilder-style payloads, account mutation scope, system-bot show/list visibility, empty `200 OK` delete, and full reset/avatar action payloads. | Keep in Review; reopen only if live settings smoke exposes avatar upload storage or administrator-secret gating drift. | Focused AgentBot handler tests, service/router focused tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed. |
|
||||
| 4 | P3.10 account webhooks API | Implemented for the reused dashboard Webhooks settings route with PATCH update, Chatwoot `{ payload }` list/mutation serializers, nested `{ webhook: ... }` bodies, generated secret, account-scoped mutations, URL/subscription validation, optional inbox serialization, and empty `200 OK` delete. | Keep in Review; reopen only if live settings smoke exposes audit writer or delivery-signature drift beyond the existing delivery service boundary. | Focused webhook handler/service/router tests, migration test, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed. |
|
||||
| 5 | P6.8 contact outbound voice call | Implemented for the reused dashboard route with Twilio voice-enabled inbox validation, assigned-inbox check, open-conversation reuse, ContactInbox/conversation/call/message persistence, and Chatwoot response shape. | Keep in Review; reopen only if live smoke exposes provider initiation/status-update drift beyond the fakeable persisted boundary. | Focused contact call tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed. |
|
||||
| 6 | B12 optional live smoke | API/browser/enterprise smoke commands are checked in; live runs need PostgreSQL, Redis, Meilisearch, Vite, and Chrome. | Run full live smoke when environment is available and map failures to the board. | `docs/parity/frontend_smoke_report.md` records pass/fail and linked owners. |
|
||||
| 7 | B9.3 delayed automation actions | Current reference exposes no delayed automation action params; scheduled-item work is already P5.12; `send_email_to_team` is durable and `add_sla` mutates conversation/applied SLA state. | Keep automation drift closed if future reference/smoke exposes delayed params or unsupported action shapes. | Automation worker/action fixtures verify queued team email replay, retry visibility through worker jobs, and SLA action idempotency. |
|
||||
| 8 | P5.13 reports/analytics | P5.13a derives visible report aggregates from persisted rows; P5.13b adds lazy rollup freshness, durable day rollup jobs, and `/reports` metric timeseries. | Keep report drift closed as frontend smoke or reference inspection exposes additional metrics. | Report fixtures verify timeseries values, cache/freshness behavior, and no hidden placeholder JSON. |
|
||||
| 5 | P3.11 account integrations apps/hooks API | Implemented for reused dashboard integrations settings with `{ payload: [...] }` app index, raw app/show and hook mutation payloads, raw or nested create/update bodies, account-scoped hook show/update/delete, persisted `app_id/reference_id`, reference app catalog seed additions, app hook/settings schema serializers, hook boolean `status`, account/inbox `hook_type`, and empty `200 OK` delete. | Keep in Review; reopen if live settings smoke exposes app feature-flag activation, app-specific credential validation, or provider setup side effects beyond this generic hooks boundary. | Focused integration hook handler/service tests, migration/router/route-parity tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed. |
|
||||
| 6 | P6.8 contact outbound voice call | Implemented for the reused dashboard route with Twilio voice-enabled inbox validation, assigned-inbox check, open-conversation reuse, ContactInbox/conversation/call/message persistence, and Chatwoot response shape. | Keep in Review; reopen only if live smoke exposes provider initiation/status-update drift beyond the fakeable persisted boundary. | Focused contact call tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed. |
|
||||
| 7 | B12 optional live smoke | API/browser/enterprise smoke commands are checked in; live runs need PostgreSQL, Redis, Meilisearch, Vite, and Chrome. | Run full live smoke when environment is available and map failures to the board. | `docs/parity/frontend_smoke_report.md` records pass/fail and linked owners. |
|
||||
| 8 | B9.3 delayed automation actions | Current reference exposes no delayed automation action params; scheduled-item work is already P5.12; `send_email_to_team` is durable and `add_sla` mutates conversation/applied SLA state. | Keep automation drift closed if future reference/smoke exposes delayed params or unsupported action shapes. | Automation worker/action fixtures verify queued team email replay, retry visibility through worker jobs, and SLA action idempotency. |
|
||||
| 9 | P5.13 reports/analytics | P5.13a derives visible report aggregates from persisted rows; P5.13b adds lazy rollup freshness, durable day rollup jobs, and `/reports` metric timeseries. | Keep report drift closed as frontend smoke or reference inspection exposes additional metrics. | Report fixtures verify timeseries values, cache/freshness behavior, and no hidden placeholder JSON. |
|
||||
|
||||
## Open Checkpoint Contracts
|
||||
|
||||
@@ -154,6 +155,7 @@ These rows are the executable development plan from this point forward. A checkp
|
||||
| P3.7d enterprise article bulk translation | `internal/handler/api/v1/article_handler.go`, `internal/service/article_service.go`, `internal/repository/article_repo.go`, `internal/app/bootstrap.go`, article handler/service tests | `reference/chatwoot/enterprise/app/controllers/enterprise/api/v1/accounts/articles/bulk_actions_controller.rb`, `enterprise/app/jobs/captain/articles/translate_job.rb`, `enterprise/app/services/captain/llm/article_translation_service.rb`, dashboard `api/helpCenter/articles.js`, `BulkTranslateDialog.vue` | Article bulk translate now validates `captain_tasks`, portal allowed locales, optional target-locale category, and selected articles; detects existing root-article translations and returns `409 { duplicate_articles }` unless `force` is true; queues durable low-priority `captain:article_translate` jobs; maps locale codes to English language names; and creates or updates draft translated articles through the wired LLM translation backend using Chatwoot's title/content prompts. | Review by `feat(help-center): queue article translations`; focused service/handler tests, combined service/handler/repository/app tests, full `go test ./...`, and `git diff --check` passed. No route changes. |
|
||||
| P3.9 account agent-bot API parity | `internal/router/router.go`, `internal/handler/api/v1/agent_bot_handler.go`, `internal/service/agent_bot_service.go`, `internal/repository/agent_bot_repo.go`, agent bot handler tests | `reference/chatwoot/config/routes.rb:94-97`, `reference/chatwoot/app/controllers/api/v1/accounts/agent_bots_controller.rb`, `app/views/api/v1/accounts/agent_bots/*.json.jbuilder`, `app/views/api/v1/models/_agent_bot.json.jbuilder`, `app/models/agent_bot.rb`, `app/presenters/agent_bot_presenter.rb`, dashboard `api/agentBots.js`, `store/modules/agentBots.js`, settings `agentBots` route/components | Account agent-bot APIs now expose frontend no-trailing-slash GET/POST and PATCH update routes, track the full Chatwoot account agent-bot route set, return raw Jbuilder-style arrays/objects with `thumbnail`, `bot_config`, `system_bot`, account-scoped `access_token`/`secret`, accept JSON or multipart form bodies, preserve explicit empty update fields, scope create/update/delete/reset/avatar mutations to current-account bots, allow show/index of system bots through `accessible_to`, return empty `200 OK` delete, and return full bot payloads after reset-access-token/reset-secret/avatar deletion. | Review by `feat(agent-bots): align account payloads`; focused AgentBot handler tests, `go test ./internal/handler/api/v1 ./internal/service ./internal/router -run 'AgentBot\|Router' -count=1`, route dump/parity regenerated to `TOTAL: 864` and `308 exact, 7 parameter-compatible, 0 missing out of 315`, full `go test ./...`, and `git diff --check` passed. |
|
||||
| P3.10 account webhook API parity | `internal/router/router.go`, `internal/handler/api/v1/webhook_subscription_handler.go`, `internal/service/webhook_subscription_service.go`, `internal/repository/webhook_subscription_repo.go`, `internal/model/webhook_subscription.go`, webhook handler/service tests, migrations | `reference/chatwoot/config/routes.rb:342`, `reference/chatwoot/app/controllers/api/v1/accounts/webhooks_controller.rb`, `app/views/api/v1/accounts/webhooks/*.json.jbuilder`, `app/models/webhook.rb`, dashboard `api/webhooks.js`, `store/modules/webhooks.js`, settings `integrations/Webhooks/*` components | Account webhook APIs now match the reused dashboard settings flow: index returns `{ payload: { webhooks } }`, create/update return `{ payload: { webhook } }`, delete returns empty `200 OK`, frontend `PATCH` update is registered, nested `{ webhook: ... }` request bodies are accepted, `name/url/subscriptions/inbox_id/secret` serialize like Jbuilder, mutations are scoped through current account, URL/subscription validation follows the reference allowed event set, and outgoing delivery filtering keeps using the same persisted subscription rows. | Review by `feat(webhooks): align account payloads`; focused webhook handler/service tests, router focused test, `go test ./cmd/migrate -count=1`, route dump/parity regenerated to `TOTAL: 865` and `313 exact, 7 parameter-compatible, 0 missing out of 320`, full `go test ./...`, and `git diff --check` passed. |
|
||||
| P3.11 account integration apps/hooks API parity | `internal/router/router.go`, `internal/handler/api/v1/integration_hook_handler.go`, `internal/service/integration_hook_service.go`, `internal/repository/integration_hook_repo.go`, `internal/model/integration_hook.go`, integration hook handler/service tests, migrations, `cmd/route_parity` | `reference/chatwoot/config/routes.rb:345-348`, `reference/chatwoot/app/controllers/api/v1/accounts/integrations/apps_controller.rb`, `app/controllers/api/v1/accounts/integrations/hooks_controller.rb`, `app/views/api/v1/accounts/integrations/apps/*.jbuilder`, `app/views/api/v1/accounts/integrations/hooks/*.jbuilder`, `app/views/api/v1/models/_app.json.jbuilder`, `app/views/api/v1/models/_hook.json.jbuilder`, `app/models/integrations/app.rb`, `app/models/integrations/hook.rb`, `config/integration/apps.yml`, dashboard `api/integrations.js`, `store/modules/integrations.js`, settings integrations components | Account integration apps/hooks now match the reused dashboard integration settings contract: app index returns `{ payload: [...] }`; app show returns a raw app object; hooks create/show/update return raw hook objects; delete returns empty `200 OK`; frontend no-trailing-slash app/hook routes and hook `PATCH` update are registered and tracked; raw frontend hook bodies and nested `{ hook: ... }` are accepted; hooks persist `app_id`/`reference_id`; show/update/delete are account-scoped; hook serializers expose `app_id`, boolean `status`, `account_id`, account/inbox `hook_type`, `settings`, `reference_id`, and optional inbox; app serializers expose `hooks`, `action`, `button`, `allow_multiple_hooks`, `settings_form_schema`, and `visible_properties`; migration `000030` seeds the additional reference app catalog rows. | Review by `feat(integrations): align app hook payloads`; focused integration hook handler/service tests, `go test ./cmd/migrate -count=1`, `go test ./cmd/route_parity -count=1`, router focused test, route dump/parity regenerated to `TOTAL: 869` and `321 exact, 7 parameter-compatible, 0 missing out of 328`, full `go test ./...`, and `git diff --check` passed. |
|
||||
| P6.8 contact outbound voice call parity | `internal/router/router.go`, `internal/handler/api/v1/contact_handler.go`, `internal/service/contact_service.go`, `internal/model/call.go`, contact handler tests | `reference/chatwoot/config/routes.rb:216`, `reference/chatwoot/enterprise/app/controllers/api/v1/accounts/contacts/calls_controller.rb`, `reference/chatwoot/enterprise/app/services/voice/outbound_call_builder.rb`, `reference/chatwoot/enterprise/app/services/voice/call_message_builder.rb`, `reference/chatwoot/enterprise/app/models/call.rb`, dashboard `api/contacts.js`, `store/modules/contacts/actions.js`, `api/channel/voice/voiceAPIClient.js` | Contact outbound calls now match the Chatwoot enterprise route boundary: account contact lookup, current user's assigned `Channel::TwilioSms` inbox lookup, `voice_enabled` guard, phone-number guard, open display-ID conversation reuse only for same inbox/contact, new ContactInbox/open conversation creation when needed, persisted outgoing Twilio call metadata, linked `voice_call` message content attributes, and raw `{ conversation_id, inbox_id, call_sid, conference_sid }` response. | Review by `feat(contacts): initiate voice calls`; focused contact call tests cover success/reuse/resolved-hint ignored/no-phone/non-voice/unassigned cases; route dump/parity regenerated to `TOTAL: 861` and `299 exact, 7 parameter-compatible, 0 missing out of 306`; full `go test ./...` and `git diff --check` passed. |
|
||||
| P6 conversation transcript response parity | `internal/handler/api/v1/conversation_handler.go`, conversation handler tests | `reference/chatwoot/app/controllers/api/v1/accounts/conversations_controller.rb`, dashboard `api/inbox/conversation.js` | Account conversation transcript now follows Chatwoot's controller contract: missing email returns `422 { error: "email param missing" }`, nonblank email schedules through the existing service boundary and returns empty `200 OK`, and invalid-looking but nonblank email values are not rejected by local email format validation. | Review by `feat(conversations): align transcript responses`; focused transcript handler/service tests, combined handler/service/router tests, full `go test ./...`, and `git diff --check` must pass. |
|
||||
| P6 conversation custom attributes response parity | `internal/handler/api/v1/conversation_handler.go`, conversation handler tests | `reference/chatwoot/app/controllers/api/v1/accounts/conversations_controller.rb`, `app/views/api/v1/accounts/conversations/custom_attributes.json.jbuilder`, dashboard `api/inbox/conversation.js`, conversation store action | Account conversation custom attribute updates now return Chatwoot `{ custom_attributes: ... }` only, matching the store action that reads `response.data.custom_attributes`, instead of returning the full conversation serializer with unrelated fields. Empty/null JSON serializes as `{}`. | Review by `feat(conversations): align custom attribute response`; focused handler tests, combined handler/service/router tests, full `go test ./...`, and `git diff --check` passed. |
|
||||
@@ -193,6 +195,7 @@ This ledger records the committed parity checkpoints that future slices should b
|
||||
|
||||
| Commit | Scope | Verification summary | Follow-up state |
|
||||
| --- | --- | --- | --- |
|
||||
| `feat(integrations): align app hook payloads` | Advances P3.11 account integrations apps/hooks parity by matching Chatwoot `Integrations::AppsController`, `Integrations::HooksController`, app/hook Jbuilder views, `Integrations::App`, `Integrations::Hook`, `config/integration/apps.yml`, and the reused dashboard integrations API/store/settings components. GoChat now tracks `routes.rb:345-348`, registers frontend no-trailing-slash app/hook routes plus hook `PATCH`, returns Chatwoot `{ payload: [...] }` app index and raw app/hook objects, accepts raw frontend hook bodies plus nested `{ hook: ... }`, persists `app_id` and `reference_id`, scopes hook show/update/delete by account, serializes boolean hook `status`, account/inbox `hook_type`, settings, inbox, app hooks, settings schemas, visible properties, and seeds the additional reference app catalog rows. | `go test ./internal/handler/api/v1 -run IntegrationHook -count=1`; `go test ./internal/service -run IntegrationHook -count=1`; `go test ./cmd/migrate -count=1`; `go test ./cmd/route_parity -count=1`; `go test ./internal/router -run Router -count=1`; `go run ./cmd/dump_routes > docs/parity/gochat_routes.txt`; `go run ./cmd/route_parity`; `go test ./...`; `git diff --check`. Route dump is `TOTAL: 869`; tracked route parity is `321 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 328`. | P3.11 moves to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
| `feat(webhooks): align account payloads` | Advances P3.10 account webhook API parity by matching Chatwoot `WebhooksController`, account webhook Jbuilder views, `Webhook` model validation, and the reused dashboard `webhooks` API/store/settings components. GoChat now tracks `routes.rb:342`, registers frontend `PATCH /api/v1/accounts/:account_id/webhooks/:webhook_id`, returns Chatwoot `{ payload: { webhooks } }` and `{ payload: { webhook } }` payloads, accepts nested `{ webhook: ... }` bodies, persists `name`, `inbox_id`, `url`, `subscriptions`, and generated `secret`, scopes show/update/delete by account, validates HTTP/HTTPS URLs plus the reference allowed event set, returns empty `200 OK` delete, and keeps delivery filtering backed by persisted subscription rows. | `go test ./internal/handler/api/v1 -run WebhookSubscription -count=1`; `go test ./internal/service -run WebhookSubscription -count=1`; `go test ./internal/router -run Router -count=1`; `go test ./internal/handler/api/v1 ./internal/service ./internal/router ./cmd/route_parity -run 'WebhookSubscription\|Router\|RouteParity' -count=1`; `go test ./cmd/migrate -count=1`; `go run ./cmd/dump_routes > docs/parity/gochat_routes.txt`; `go run ./cmd/route_parity`; `go test ./...`; `git diff --check`. Route dump is `TOTAL: 865`; tracked route parity is `313 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 320`. | P3.10 moves to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
| `feat(agent-bots): align account payloads` | Advances P3.9 account agent-bot API parity by matching Chatwoot `AgentBotsController`, account agent-bot Jbuilder views, `_agent_bot.json.jbuilder`, `AgentBotPresenter`, and the reused dashboard `AgentBotsAPI`/`agentBots` store path. GoChat now registers frontend no-trailing-slash `GET/POST /api/v1/accounts/:account_id/agent_bots` plus `PATCH /agent_bots/:id`, tracks `routes.rb:94-97`, returns raw bot arrays/objects with `thumbnail`, `bot_config`, `system_bot`, account-scoped `access_token`/`secret`, accepts JSON and multipart form bodies, preserves explicit empty update values, scopes mutation/reset/avatar actions to current-account bots while allowing index/show of system bots, returns empty `200 OK` delete, and returns full bot payloads for reset/avatar actions. | `go test ./internal/handler/api/v1 -run AgentBot -count=1`; `go test ./internal/service -run AgentBot -count=1`; `go test ./internal/router -run Router -count=1`; `go test ./internal/handler/api/v1 ./internal/service ./internal/router -run 'AgentBot\|Router' -count=1`; `go run ./cmd/dump_routes > docs/parity/gochat_routes.txt`; `go run ./cmd/route_parity`; `go test ./cmd/route_parity -count=1`; `go test ./...`; `git diff --check`. Route dump is `TOTAL: 864`; tracked route parity is `308 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 315`. | P3.9 moves to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
| `feat(contacts): initiate voice calls` | Advances P6.8 contact outbound voice call parity by matching Chatwoot enterprise `Contacts::CallsController#create`, `Voice::OutboundCallBuilder`, `Voice::CallMessageBuilder`, `Call`, and the reused dashboard `ContactAPI.initiateCall`/voice client path. GoChat now registers `POST /api/v1/accounts/:account_id/contacts/:contact_id/call`, requires an assigned `Channel::TwilioSms` inbox with `voice_enabled`, requires a contact phone number, reuses only matching open display-ID conversations, creates ContactInbox/open conversation records when needed, persists Twilio outgoing call metadata and a linked `voice_call` message payload, and returns `{ conversation_id, inbox_id, call_sid, conference_sid }`. | `go test ./internal/handler/api/v1 -run 'ContactHandlerCRUDTestSuite/TestInitiateCall' -count=1`; `go test ./internal/service ./internal/handler/api/v1 ./internal/router -run 'Contact\|Router' -count=1`; `go run ./cmd/dump_routes > docs/parity/gochat_routes.txt`; `go run ./cmd/route_parity`; `go test ./cmd/route_parity -count=1`; `go test ./...`; `git diff --check`. Route dump is `TOTAL: 861`; tracked route parity is `299 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 306`. | P6.8 moves to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
@@ -1647,7 +1650,7 @@ Frontend-critical API groups to audit first:
|
||||
| P3.7 | Notifications/reports/help center/campaigns | Frontend-visible payloads and pagination/error envelopes. | Doing; notifications, reports, account campaign CRUD/scheduling, and help-center portal/category/article routes/payloads now have focused Chatwoot payload fixtures. Continue only with fresh reference/smoke drift. |
|
||||
| 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 |
|
||||
| P3.10 | Account webhooks/integration settings | Account webhook CRUD, payloads, event subscriptions, secrets, and delivery backing rows. | Review; reused dashboard Webhooks settings flow now gets Chatwoot `{ payload }` list/mutation serializers, PATCH update, nested `{ webhook }` bodies, generated secrets, scoped mutations, and empty `200 OK` delete. |
|
||||
| P3.10 | Account webhooks/integration settings | Account webhook CRUD, integration app/hook payloads, event subscriptions, secrets, and delivery backing rows. | Review; reused dashboard Webhooks settings flow now gets Chatwoot `{ payload }` list/mutation serializers, PATCH update, nested `{ webhook }` bodies, generated secrets, scoped mutations, and empty `200 OK` delete. P3.11 integration apps/hooks now also match the reused dashboard integrations list/create/delete path with raw app/hook serializers, `app_id/reference_id`, settings schemas, account-scoped hook mutations, and empty delete. |
|
||||
|
||||
Serializer parity work plan:
|
||||
|
||||
@@ -2155,6 +2158,7 @@ Verification milestone gates:
|
||||
|
||||
## Progress Log
|
||||
|
||||
- 2026-06-06: P3.11 account integrations apps/hooks checkpoint prepared as `feat(integrations): align app hook payloads`; audited Chatwoot `routes.rb:345-348`, `Integrations::AppsController`, `Integrations::HooksController`, app/hook Jbuilder views, `Integrations::App`, `Integrations::Hook`, `config/integration/apps.yml`, and reused dashboard `api/integrations.js`, `store/modules/integrations.js`, and settings integration components. Account integration apps/hooks now return Chatwoot `{ payload: [...] }` app index payloads and raw app/hook objects, accept raw frontend hook bodies plus nested `{ hook: ... }`, register frontend no-trailing-slash app/hook routes and hook `PATCH`, persist `app_id/reference_id`, scope hook show/update/delete by account, serialize boolean `status`, account/inbox `hook_type`, `settings`, `inbox`, app `hooks`, settings schemas, and visible properties, seed additional reference app catalog rows, and return empty `200 OK` delete. Focused integration hook handler/service tests, migration test, route parity test, router focused test, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed; route dump is `TOTAL: 869` and tracked route parity is `321 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 328`.
|
||||
- 2026-06-06: P3.10 account webhook API checkpoint prepared as `feat(webhooks): align account payloads`; audited Chatwoot `routes.rb:342`, `WebhooksController`, account webhook Jbuilder views, `Webhook`, reused dashboard `api/webhooks.js`, `store/modules/webhooks.js`, and settings Webhooks components. Account webhook APIs now return Chatwoot `{ payload: { webhooks } }` list payloads and `{ payload: { webhook } }` mutation/show payloads, accept nested `{ webhook: ... }` frontend bodies plus legacy raw bodies, register frontend `PATCH` update, persist `name/url/subscriptions/inbox_id/secret`, scope show/update/delete by account, validate HTTP/HTTPS URLs and allowed subscriptions, return empty `200 OK` delete, and keep outbound delivery event filtering on the same rows. Focused webhook handler/service/router tests, migration test, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed; route dump is `TOTAL: 865` and tracked route parity is `313 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 320`.
|
||||
- 2026-06-06: P3.9 account agent-bot API checkpoint prepared as `feat(agent-bots): align account payloads`; audited Chatwoot `routes.rb:94-97`, `AgentBotsController`, account agent-bot Jbuilder views, `_agent_bot.json.jbuilder`, `AgentBotPresenter`, `AgentBot`, and reused dashboard `api/agentBots.js`, `store/modules/agentBots.js`, and settings agent-bot screens. Account agent-bot APIs now expose frontend no-trailing-slash GET/POST and PATCH update routes, return raw Chatwoot bot arrays/objects instead of local success/data/meta envelopes, serialize `thumbnail`, `bot_config`, `system_bot`, account-scoped `access_token`/`secret`, accept JSON or multipart form bodies, preserve explicit empty update fields, scope create/update/delete/reset/avatar mutations to current-account bots, allow show/index of system bots through `accessible_to`, return empty `200 OK` delete, and return full bot payloads after reset-access-token/reset-secret/avatar deletion. Focused AgentBot handler/service/router tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed; route dump is `TOTAL: 864` and tracked route parity is `308 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 315`.
|
||||
- 2026-06-06: P6.8 contact outbound voice call checkpoint prepared as `feat(contacts): initiate voice calls`; audited Chatwoot `routes.rb:216`, enterprise `Contacts::CallsController#create`, `Voice::OutboundCallBuilder`, `Voice::CallMessageBuilder`, `Call`, and reused dashboard `api/contacts.js`, contact store action, and voice API client. GoChat now registers `POST /api/v1/accounts/:account_id/contacts/:contact_id/call`, validates account contact scope, current user's assigned Twilio voice inbox, `voice_enabled`, and contact phone number, reuses only matching open display-ID conversations, creates ContactInbox/open conversation rows when needed, persists outgoing Twilio call metadata and linked `voice_call` message content attributes, and returns `{ conversation_id, inbox_id, call_sid, conference_sid }`. Focused contact-call tests, combined service/handler/router tests, route dump/parity regeneration, `go test ./cmd/route_parity -count=1`, full `go test ./...`, and `git diff --check` passed; route dump is `TOTAL: 861` and tracked route parity is `299 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 306`.
|
||||
|
||||
@@ -268,8 +268,10 @@ GET /api/v1/accounts/:account_id/instagram/callback
|
||||
GET /api/v1/accounts/:account_id/instagram/oauth
|
||||
GET /api/v1/accounts/:account_id/instagram/webhooks
|
||||
GET /api/v1/accounts/:account_id/instagram_channels/
|
||||
GET /api/v1/accounts/:account_id/integrations/apps
|
||||
GET /api/v1/accounts/:account_id/integrations/apps/
|
||||
GET /api/v1/accounts/:account_id/integrations/apps/:id
|
||||
GET /api/v1/accounts/:account_id/integrations/hooks
|
||||
GET /api/v1/accounts/:account_id/integrations/hooks/
|
||||
GET /api/v1/accounts/:account_id/integrations/hooks/:id
|
||||
GET /api/v1/accounts/:account_id/integrations/linear/linked_issues
|
||||
@@ -484,6 +486,7 @@ PATCH /api/v1/accounts/:account_id/inboxes/:inbox_id/members/:user_id
|
||||
PATCH /api/v1/accounts/:account_id/inboxes/:inbox_id/members/update_multiple
|
||||
PATCH /api/v1/accounts/:account_id/inboxes/:inbox_id/tiktok_channels/:tt_id
|
||||
PATCH /api/v1/accounts/:account_id/inboxes/:inbox_id/twilio_sms_channels/:tw_id
|
||||
PATCH /api/v1/accounts/:account_id/integrations/hooks/:id
|
||||
PATCH /api/v1/accounts/:account_id/integrations/slack/
|
||||
PATCH /api/v1/accounts/:account_id/notification_settings
|
||||
PATCH /api/v1/accounts/:account_id/notification_settings/
|
||||
@@ -641,6 +644,7 @@ POST /api/v1/accounts/:account_id/inboxes/:inbox_id/sync_templates
|
||||
POST /api/v1/accounts/:account_id/inboxes/web_widget
|
||||
POST /api/v1/accounts/:account_id/instagram/webhooks
|
||||
POST /api/v1/accounts/:account_id/instagram_channels/
|
||||
POST /api/v1/accounts/:account_id/integrations/hooks
|
||||
POST /api/v1/accounts/:account_id/integrations/hooks/
|
||||
POST /api/v1/accounts/:account_id/integrations/hooks/:id/process_event
|
||||
POST /api/v1/accounts/:account_id/integrations/linear/create_issue
|
||||
@@ -863,4 +867,4 @@ PUT /public/api/v1/csat_survey/:id
|
||||
PUT /public/api/v1/inboxes/:inbox_id/contacts/:contact_id
|
||||
PUT /public/api/v1/inboxes/:inbox_id/contacts/:contact_id/conversations/:conversation_id/messages/:message_id
|
||||
PUT /widget/direct_uploads/:upload_uuid
|
||||
TOTAL: 865
|
||||
TOTAL: 869
|
||||
|
||||
@@ -7,7 +7,7 @@ Generated from:
|
||||
|
||||
This report covers tracked frontend-critical Chatwoot routes from `reference/chatwoot/config/routes.rb`, including API v1 account routes, Captain/Copilot, assignment policies, widget/public APIs, and API v2 reports. Ruby is not installed in the workspace, so Chatwoot routes are sourced from static route declarations instead of `bin/rails routes`.
|
||||
|
||||
Summary: 313 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 320 tracked critical routes.
|
||||
Summary: 321 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 328 tracked critical routes.
|
||||
|
||||
## Missing Critical Routes
|
||||
|
||||
@@ -68,6 +68,7 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| DELETE | `/api/v1/accounts/:account_id/inboxes/:inbox_id` | `/api/v1/accounts/:account_id/inboxes/:inbox_id` | `api/v1/accounts/inboxes#destroy` | `routes.rb:252` | exact |
|
||||
| DELETE | `/api/v1/accounts/:account_id/inboxes/:inbox_id/assignment_policy/` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/assignment_policy/` | `api/v1/accounts/inboxes/assignment_policy#destroy` | `routes.rb:311` | exact |
|
||||
| DELETE | `/api/v1/accounts/:account_id/inboxes/:inbox_id/avatar` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/avatar` | `api/v1/accounts/inboxes#avatar` | `routes.rb:257` | exact |
|
||||
| DELETE | `/api/v1/accounts/:account_id/integrations/hooks/:id` | `/api/v1/accounts/:account_id/integrations/hooks/:id` | `api/v1/accounts/integrations/hooks#destroy` | `routes.rb:346` | exact |
|
||||
| DELETE | `/api/v1/accounts/:account_id/labels/:tag_id` | `/api/v1/accounts/:account_id/labels/:tag_id` | `api/v1/accounts/labels#destroy` | `routes.rb:281` | exact |
|
||||
| DELETE | `/api/v1/accounts/:account_id/macros/:macro_id` | `/api/v1/accounts/:account_id/macros/:macro_id` | `api/v1/accounts/macros#destroy` | `routes.rb:118` | exact |
|
||||
| DELETE | `/api/v1/accounts/:account_id/notifications/:notification_id` | `/api/v1/accounts/:account_id/notifications/:notification_id` | `api/v1/accounts/notifications#destroy` | `routes.rb:283` | exact |
|
||||
@@ -151,6 +152,9 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| GET | `/api/v1/accounts/:account_id/inboxes/:inbox_id/assignment_policy/` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/assignment_policy/` | `api/v1/accounts/inboxes/assignment_policy#show` | `routes.rb:311` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/inboxes/:inbox_id/campaigns` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/campaigns` | `api/v1/accounts/inboxes#campaigns` | `routes.rb:254` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/inboxes/:inbox_id/health` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/health` | `api/v1/accounts/inboxes#health` | `routes.rb:259` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/integrations/apps` | `/api/v1/accounts/:account_id/integrations/apps` | `api/v1/accounts/integrations/apps#index` | `routes.rb:345` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/integrations/apps/:id` | `/api/v1/accounts/:account_id/integrations/apps/:id` | `api/v1/accounts/integrations/apps#show` | `routes.rb:345` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/integrations/hooks/:id` | `/api/v1/accounts/:account_id/integrations/hooks/:id` | `api/v1/accounts/integrations/hooks#show` | `routes.rb:346` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/labels/` | `/api/v1/accounts/:account_id/labels/` | `api/v1/accounts/labels#index` | `routes.rb:281` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/labels/:tag_id` | `/api/v1/accounts/:account_id/labels/:tag_id` | `api/v1/accounts/labels#show` | `routes.rb:281` | exact |
|
||||
| GET | `/api/v1/accounts/:account_id/macros/` | `/api/v1/accounts/:account_id/macros/` | `api/v1/accounts/macros#index` | `routes.rb:118` | exact |
|
||||
@@ -211,6 +215,7 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| PATCH | `/api/v1/accounts/:account_id/agent_bots/:agent_bot_id` | `/api/v1/accounts/:account_id/agent_bots/:agent_bot_id` | `api/v1/accounts/agent_bots#update` | `routes.rb:94` | exact |
|
||||
| PATCH | `/api/v1/accounts/:account_id/agent_capacity_policies/:id` | `/api/v1/accounts/:account_id/agent_capacity_policies/:id` | `api/v1/accounts/agent_capacity_policies#update` | `routes.rb:123` | exact |
|
||||
| PATCH | `/api/v1/accounts/:account_id/inbox_members/` | `/api/v1/accounts/:account_id/inbox_members/` | `api/v1/accounts/inbox_members#update` | `routes.rb:278` | exact |
|
||||
| PATCH | `/api/v1/accounts/:account_id/integrations/hooks/:id` | `/api/v1/accounts/:account_id/integrations/hooks/:id` | `api/v1/accounts/integrations/hooks#update` | `routes.rb:346` | exact |
|
||||
| PATCH | `/api/v1/accounts/:account_id/portals/:portal_id` | `/api/v1/accounts/:account_id/portals/:portal_id` | `api/v1/accounts/portals#update` | `routes.rb:385` | exact |
|
||||
| PATCH | `/api/v1/accounts/:account_id/portals/:portal_id/archive` | `/api/v1/accounts/:account_id/portals/:portal_id/archive` | `api/v1/accounts/portals#archive` | `routes.rb:387` | exact |
|
||||
| PATCH | `/api/v1/accounts/:account_id/portals/:portal_id/articles/:article_id` | `/api/v1/accounts/:account_id/portals/:portal_id/articles/:article_id` | `api/v1/accounts/articles#update` | `routes.rb:403` | exact |
|
||||
@@ -281,6 +286,8 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| POST | `/api/v1/accounts/:account_id/inboxes/:inbox_id/reset_secret` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/reset_secret` | `api/v1/accounts/inboxes#reset_secret` | `routes.rb:262` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/inboxes/:inbox_id/set_agent_bot` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/set_agent_bot` | `api/v1/accounts/inboxes#set_agent_bot` | `routes.rb:256` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/inboxes/:inbox_id/sync_templates` | `/api/v1/accounts/:account_id/inboxes/:inbox_id/sync_templates` | `api/v1/accounts/inboxes#sync_templates` | `routes.rb:258` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/integrations/hooks` | `/api/v1/accounts/:account_id/integrations/hooks` | `api/v1/accounts/integrations/hooks#create` | `routes.rb:346` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/integrations/hooks/:id/process_event` | `/api/v1/accounts/:account_id/integrations/hooks/:id/process_event` | `api/v1/accounts/integrations/hooks#process_event` | `routes.rb:348` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/labels/` | `/api/v1/accounts/:account_id/labels/` | `api/v1/accounts/labels#create` | `routes.rb:281` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/macros/` | `/api/v1/accounts/:account_id/macros/` | `api/v1/accounts/macros#create` | `routes.rb:118` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/macros/:macro_id/execute` | `/api/v1/accounts/:account_id/macros/:macro_id/execute` | `api/v1/accounts/macros#execute` | `routes.rb:119` | exact |
|
||||
@@ -339,6 +346,7 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| PUT | `/api/v1/accounts/:account_id/custom_attribute_definitions/:id` | `/api/v1/accounts/:account_id/custom_attribute_definitions/:id` | `api/v1/accounts/custom_attribute_definitions#update` | `routes.rb:250` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/custom_filters/:id` | `/api/v1/accounts/:account_id/custom_filters/:id` | `api/v1/accounts/custom_filters#update` | `routes.rb:251` | 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/integrations/hooks/:id` | `/api/v1/accounts/:account_id/integrations/hooks/:id` | `api/v1/accounts/integrations/hooks#update` | `routes.rb:346` | exact |
|
||||
| PUT | `/api/v1/accounts/:account_id/labels/:tag_id` | `/api/v1/accounts/:account_id/labels/:tag_id` | `api/v1/accounts/labels#update` | `routes.rb:281` | 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/notification_settings/` | `/api/v1/accounts/:account_id/notification_settings/` | `api/v1/accounts/notification_settings#update` | `routes.rb:293` | exact |
|
||||
|
||||
Reference in New Issue
Block a user