|
|
|
@@ -16,12 +16,12 @@ Build GoChat as a Go backend that can directly reuse the frontend from `referenc
|
|
|
|
|
|
|
|
|
|
## Current Baseline
|
|
|
|
|
|
|
|
|
|
- Current tracking checkpoint: 2026-06-06 after `7425e26 feat(conversations): align custom attribute response`, with this implementation checkpoint prepared as `feat(contacts): align active pagination payloads`.
|
|
|
|
|
- Latest implementation checkpoint: this checkpoint, prepared as `feat(contacts): align active pagination payloads`.
|
|
|
|
|
- Current tracking checkpoint: 2026-06-06 after `c76c25f feat(contacts): align active pagination payloads`, with this implementation checkpoint prepared as `feat(custom-roles): align update route semantics`.
|
|
|
|
|
- Latest implementation checkpoint: this checkpoint, prepared as `feat(custom-roles): align update route semantics`.
|
|
|
|
|
- Latest documentation-only checkpoint: `8b378c7 docs: refresh parity tracker baseline`; this document is now the active follow-up plan and supersedes `.hermes/plans/*`.
|
|
|
|
|
- Worktree status at this implementation checkpoint: Phase 6 contacts active/list/search/filter pagination drift is closed for the reused dashboard CRM route family: contact index/search/active/filter now use Chatwoot's `RESULTS_PER_PAGE = 15`, and `GET /contacts/active` now returns the same `{ meta: { count, current_page }, payload: [...] }` contact serializer as `contacts/active.json.jbuilder` instead of the local `{ contacts, meta: { page, page_size } }` envelope. The selected-key contact `destroy_custom_attributes` route is covered against Chatwoot's `{ payload }` response with `contact_inboxes`. Conversation transcript and custom-attribute response drifts are already closed. 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 the next named Phase 2/3 or Phase 6 drift from fresh reference/smoke evidence.
|
|
|
|
|
- Worktree status at this implementation checkpoint: B10.3 CustomRole frontend update drift is closed for the reused enterprise settings client: `PATCH /custom_roles/:id` is now registered alongside `PUT`, matching `ApiClient.update`, and custom-role updates can clear `description` while preserving omitted-field behavior. The preceding Phase 6 contacts pagination/active payload drift is closed. Conversation transcript and custom-attribute response drifts are already closed. 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 the next named Phase 2/3 or Phase 6 drift from fresh reference/smoke evidence.
|
|
|
|
|
- `go test ./...` passes.
|
|
|
|
|
- Route dump succeeds with `TOTAL: 837` after adding Chatwoot auth reset/confirmation routes and `GET /api/v1/accounts/:account_id/contacts/:contact_id/attachments`.
|
|
|
|
|
- Route dump succeeds with `TOTAL: 838` after adding the Chatwoot custom-role `PATCH /api/v1/accounts/:account_id/custom_roles/:id` update route.
|
|
|
|
|
- Route parity artifacts now exist under `docs/parity/` and are generated by `cmd/route_parity`.
|
|
|
|
|
- Tracked frontend-critical route audit covers 277 Chatwoot routes: 270 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.
|
|
|
|
@@ -143,6 +143,7 @@ This ledger records the committed parity checkpoints that future slices should b
|
|
|
|
|
|
|
|
|
|
| Commit | Scope | Verification summary | Follow-up state |
|
|
|
|
|
| --- | --- | --- | --- |
|
|
|
|
|
| `feat(custom-roles): align update route semantics` | Advances B10.3 CustomRole frontend parity by registering Chatwoot's Rails resource `PATCH /api/v1/accounts/:account_id/custom_roles/:id` update route used by the reused `ApiClient.update` path, while keeping the existing `PUT` alias. Custom role updates now distinguish omitted `description` from an explicit empty string, so the enterprise settings form can clear descriptions like `CustomRolesController#update` with strong params. | `go test ./internal/handler/api/v1 -run CustomRole -count=1`; `go test ./internal/service -run CustomRole -count=1`; `go run ./cmd/dump_routes > docs/parity/gochat_routes.txt`; `go run ./cmd/route_parity`; `go test ./internal/handler/api/v1 ./internal/service ./internal/router -count=1`; `go test ./...`; `git diff --check`. | Continue the next named Phase 2/3 or Phase 6 drift from reference/smoke evidence. |
|
|
|
|
|
| `feat(contacts): align active pagination payloads` | Advances Phase 6 dashboard CRM drift by aligning contact list/search/filter/active pagination with Chatwoot `ContactsController::RESULTS_PER_PAGE = 15` and `contacts/active.json.jbuilder`. The reused dashboard active-contacts route now returns `{ meta: { count, current_page }, payload }` using the contact serializer instead of the local `{ contacts, meta: { page, page_size } }` envelope, and selected-key `POST /contacts/:id/destroy_custom_attributes` is covered against Chatwoot's `{ payload }` response with `contact_inboxes`. | `go test ./internal/handler/api/v1 -run 'ContactHandlerCRUD' -count=1`; `go test ./internal/handler/api/v1 ./internal/service ./internal/router -count=1`; `go test ./...`; `git diff --check`. | Continue the next named Phase 2/3 or Phase 6 drift from reference/smoke evidence. |
|
|
|
|
|
| `feat(conversations): align custom attribute response` | Advances Phase 6 dashboard conversation drift by aligning `POST /api/v1/accounts/:account_id/conversations/:conversation_id/custom_attributes` with Chatwoot `custom_attributes.json.jbuilder` and the reused conversation store action. The endpoint still persists the submitted custom attributes, but the response is now only `{ custom_attributes: ... }` and no longer leaks the full local conversation serializer, `id`, or local envelope fields. | `go test ./internal/handler/api/v1 -run 'TestConversationHandlerTestSuite/TestUpdateCustomAttributes' -count=1`; `go test ./internal/handler/api/v1 ./internal/service ./internal/router -count=1`; `go test ./...`; `git diff --check`. | Continue the next named Phase 2/3 or Phase 6 drift from reference/smoke evidence. |
|
|
|
|
|
| `feat(conversations): align transcript responses` | Advances Phase 6 dashboard conversation drift by aligning `POST /api/v1/accounts/:account_id/conversations/:conversation_id/transcript` with Chatwoot `ConversationsController#transcript` and the reused dashboard conversation API. Transcript success now returns empty `200 OK` instead of the local `{ success, data }` envelope; missing `email` returns Chatwoot `422 { error: "email param missing" }`; local email-format validation no longer rejects nonblank values that Chatwoot would pass through to the mailer. Fresh placeholder audit found only webhook handler nil-fallback `chatwootParityStub` routes, with no account/contact/conversation/message/inbox dashboard-critical stub owner left by this slice. | `go test ./internal/handler/api/v1 -run 'TestConversationHandlerTestSuite/TestTranscript' -count=1`; `go test ./internal/service -run ConversationService_SendTranscript -count=1`; `go test ./internal/handler/api/v1 ./internal/service ./internal/router -count=1`; `go test ./...`; `git diff --check`. | Continue the next named Phase 2/3 or Phase 6 drift from reference/smoke evidence. |
|
|
|
|
@@ -856,6 +857,7 @@ B10.3 current checkpoint:
|
|
|
|
|
|
|
|
|
|
- `reference/chatwoot/enterprise/app/controllers/api/v1/accounts/custom_roles_controller.rb`, `enterprise/app/models/custom_role.rb`, `enterprise/app/models/enterprise/account_user.rb`, `enterprise/app/views/api/v1/models/_custom_role.json.jbuilder`, `enterprise/app/views/api/v1/models/_account_user.json.jbuilder`, dashboard `customRole.js`, and `permissionsHelper.js` were used as the reference contract.
|
|
|
|
|
- CustomRole create/update now accepts `custom_role.permissions` as Chatwoot string arrays and stores new rows as JSON arrays while retaining legacy JSON-map reads for old local rows.
|
|
|
|
|
- CustomRole update is registered for both Rails resource methods (`PATCH` and `PUT`), and explicit empty `description` values clear the field while omitted descriptions are preserved.
|
|
|
|
|
- CustomRole list/show/create/update now return raw Chatwoot custom-role serializers with array `permissions` and no local `{ success, data, meta }` envelope; destroy returns empty `200 OK`.
|
|
|
|
|
- CustomRole admin gates now require administrator/super_admin role and focused handler tests cover non-admin denial.
|
|
|
|
|
- `AccountUser.role` remains `agent` for custom-role users. `custom_role_id > 0` drives `HasCustomRole`, RBAC policy construction, AccountScope custom-role permission loading, and profile account payload permissions.
|
|
|
|
@@ -868,6 +870,8 @@ B10.3 verification:
|
|
|
|
|
```bash
|
|
|
|
|
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run CustomRole -count=1
|
|
|
|
|
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/service -run 'CustomRole|RBAC' -count=1
|
|
|
|
|
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
|
|
|
|
|
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/model -run 'CustomRole|AccountUser' -count=1
|
|
|
|
|
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/middleware -run AccountScope -count=1
|
|
|
|
|
env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -count=1
|
|
|
|
@@ -2068,6 +2072,7 @@ Verification milestone gates:
|
|
|
|
|
|
|
|
|
|
## Progress Log
|
|
|
|
|
|
|
|
|
|
- 2026-06-06: B10.3 CustomRole update-route checkpoint prepared as `feat(custom-roles): align update route semantics`; audited Chatwoot `CustomRolesController`, custom role Jbuilder views, and dashboard `customRole.js`/`ApiClient.update`. CustomRole update now exposes `PATCH /api/v1/accounts/:account_id/custom_roles/:id` alongside the existing `PUT` alias, route dump is `TOTAL: 838`, tracked route parity remains `270 exact, 7 parameter-compatible, 0 missing`, and explicit empty `description` values now clear the role description while omitted descriptions are preserved. Focused handler/service tests, route generation/parity, combined handler/service/router tests, full `go test ./...`, and `git diff --check` passed; continue Phase 2/3 drift audit next.
|
|
|
|
|
- 2026-06-06: Phase 6 contacts active/pagination checkpoint prepared as `feat(contacts): align active pagination payloads`; audited Chatwoot `ContactsController`, `contacts/index.json.jbuilder`, `contacts/search.json.jbuilder`, `contacts/filter.json.jbuilder`, `contacts/active.json.jbuilder`, `contacts/destroy_custom_attributes.json.jbuilder`, and dashboard `contacts.js`. Contact list/search/filter/active now use Chatwoot's fixed `RESULTS_PER_PAGE = 15`; active contacts now return `{ meta: { count, current_page }, payload }` through the contact serializer instead of the local `{ contacts, meta: { page, page_size } }` envelope; selected-key `destroy_custom_attributes` payload coverage confirms the Chatwoot `{ payload }` response and `contact_inboxes` inclusion. Focused handler tests, combined handler/service/router tests, full `go test ./...`, and `git diff --check` passed; continue Phase 6 placeholder audit next.
|
|
|
|
|
- 2026-06-06: P3.6 label CRUD checkpoint prepared as `feat(labels): align chatwoot label payloads`; audited Chatwoot `LabelsController`, label Jbuilder views, `Label` model/schema, and dashboard labels API/store. Account `/labels` list now returns `{ payload }`, create/show/update return raw label payloads, create/update accept nested `{ label }` bodies plus legacy raw `name`, title values are normalized/lowercased, color defaults to `#1f93ff`, `description` and `show_on_sidebar` are persisted, account-scoped get/update/delete prevents cross-account access, and delete returns empty `200 OK` while removing conversation/contact label associations and legacy conversation label text. Focused label handler/service/repository tests, combined handler/service/router tests, migration tests, full `go test ./...`, and `git diff --check` passed; continue Phase 6 placeholder audit next.
|
|
|
|
|
- 2026-06-06: Documentation checkpoint prepared as `docs: refresh parity tracker baseline`; current baseline now points at `2ab7b58 feat(accounts): align account payloads`, the clean handoff state is recorded, and P3.6 label CRUD parity is fully landed as the next executable slice. Direct reference audit covered `LabelsController`, label Jbuilder views, `Label` model/schema, and dashboard labels API/store; current Go gaps are local `{ success, data }` envelopes, `name` instead of `title`, missing `description/show_on_sidebar/default color`, `201/204` status drift, and missing label title update/delete association side effects. Verification for this docs-only checkpoint: `git diff --check`; next implementation commit is `feat(labels): align chatwoot label payloads`.
|
|
|
|
|