diff --git a/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md b/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md index da7144ed..ce325f5f 100644 --- a/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md +++ b/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md @@ -16,9 +16,9 @@ Build GoChat as a Go backend that can directly reuse the frontend from `referenc ## Current Baseline -- Latest implementation checkpoint: `b197e54 feat(capacity): align chatwoot inbox capacity limits`. -- Latest documentation checkpoint before this consolidation: `492d916 docs: detail agent capacity parity plan`. -- Worktree status at this planning checkpoint: clean after the matching implementation checkpoint; next active slice is final B5.5 channel route-response cleanup review. +- Latest implementation checkpoint: `f04a03b feat(channels): align channel route inbox payloads`. +- Latest documentation checkpoint before this update: `10c7df0 docs: record capacity parity checkpoint`. +- Worktree status at this planning checkpoint: clean after the matching implementation checkpoint; next active slice is B6 Meilisearch live-shape review. - `go test ./...` passes. - Route dump succeeds with `TOTAL: 829` after adding Chatwoot-compatible nested AgentCapacityPolicy users and inbox-limit routes. - Route parity artifacts now exist under `docs/parity/` and are generated by `cmd/route_parity`. @@ -32,13 +32,13 @@ Build GoChat as a Go backend that can directly reuse the frontend from `referenc | Phase | Name | Status | Blocking gaps | | --- | --- | --- | --- | | Phase 0 | Test and route baseline | Done | none | -| Phase 1 | Meilisearch search engine | Review | live Meilisearch integration and document-shape parity still need reference verification | +| Phase 1 | Meilisearch search engine | Doing | B6 live-shape review is the next active slice; document/payload parity and optional live integration still need verification | | Phase 2 | Route and controller parity audit | Doing | Ruby/Bundler unavailable, so Chatwoot route extraction currently uses static `routes.rb` fallback | | Phase 3 | Data and serializer parity | Doing | JSON fixture coverage is partial and still endpoint-family based | | Phase 4 | Enterprise feature completion | Doing | excluded SSO family must stay out of scope; all other enterprise features remain included | | Phase 5 | Background jobs and integrations | Planned | durable worker choice and job parity are open | | Phase 6 | Core placeholder burn-down | Doing | account/contact/conversation/message/inbox placeholder groups remain broad | -| Phase 7 | Verification harness | Planned | route/JSON/frontend smoke harness not complete | +| Phase 7 | Verification harness | Planned | search live gate and reused-frontend smoke harness are not complete | ## Tracking Artifacts @@ -92,12 +92,13 @@ This ledger records the committed parity checkpoints that future slices should b | `f0aae79 feat(inboxes): deepen channel config parity` | Advanced B5.5 channel config parity: generic inbox JSON updates now hoist flat frontend SMTP/IMAP/channel setting keys into `channel_config`, the serializer exposes deeper Email, WhatsApp, LINE, SMS, and Twilio voice/config fields, channel defaults match Chatwoot closer for WebWidget/API/Email/WhatsApp, and the Twilio frontend create route accepts nested `twilio_channel` payloads while returning the raw Chatwoot inbox serializer. | `go test ./internal/handler/api/v1 -run 'TestInboxHandler_Chatwoot(ChannelSpecificConfigDepth\|CreateUpdateRequestBinding\|SerializerParity)\|TestTwilioChannel_Create' -count=1`; `go test ./internal/service -run Inbox -count=1`; `go test ./internal/handler/api/v1 -count=1`; `go test ./...`; `git diff --check`. | Continue B5.5 with InboxLimit enforcement and any remaining channel-specific route response cleanup. | | `8fd40ec docs: record channel config checkpoint` | Recorded the B5.5 channel config checkpoint and kept the route count at `TOTAL: 821` with tracked route parity still at 262 exact and 0 missing. | Documentation-only checkpoint after the B5.5 channel config implementation. | Next active slice is B5.5c AgentCapacityPolicy/InboxCapacityLimit route, serializer, and service parity. | | `b197e54 feat(capacity): align chatwoot inbox capacity limits` | Completed B5.5c AgentCapacityPolicy/InboxCapacityLimit API/data parity: policy CRUD now returns raw Chatwoot payloads with Unix timestamps, `assigned_agent_count`, and `inbox_capacity_limits`; `assignment_logic` is optional/defaulted; nested policy users and inbox limits are registered; `InboxCapacityLimit` validates account scope, duplicate inbox assignment, and non-negative limits; account users can be assigned/unassigned to capacity policies. | `go test ./internal/service -run AgentCapacity -count=1`; `go test ./internal/handler/api/v1 -run AgentCapacity -count=1`; `go test ./internal/router -count=1`; `go test ./internal/handler/api/v1 -count=1`; sandboxed `go test ./...` failed on local socket restrictions; escalated `go test ./...` passed; route dump regenerated with `TOTAL: 829`; route parity is `267 exact, 7 parameter-compatible, 0 missing`; `git diff --check`. | Continue final B5.5 review for remaining channel-specific route response cleanup, then move to B6 Meilisearch live-shape review. | +| `f04a03b feat(channels): align channel route inbox payloads` | Completed the final B5.5 channel route-response cleanup: Email, Twilio SMS, and LINE dedicated channel create/get/update/list routes now return Chatwoot frontend-compatible raw inbox payloads or `{ payload: [...] }` lists instead of `{ channel }`, `{ channels }`, `{ channel, inbox }`, or success-message envelopes. Delete routes now return empty `200 OK`, and channel creation binds the dedicated channel ID/config back onto the inbox before serialization. | `go test ./internal/handler/api/v1 -run 'Test(Email\|Twilio\|LINE)Channel' -count=1`; `go test ./internal/service -run Inbox -count=1`; `go test ./internal/handler/api/v1 -count=1`; `go test ./...`; `git diff --check`. No route changes; route dump remains `TOTAL: 829`. | B5 inbox/channel API parity moves to Done for current frontend-critical scope; next active slice is B6 Meilisearch live-shape review. | ## Next Slice Contract -Completed implementation slice: B5.1-B5.4 now cover inbox serializer shape, Chatwoot frontend create/update binding, working-hours persistence, out-of-office behavior, and inbox member assignment payload/mutation semantics. B4 remains in review after contact/company CRUD payloads, relations, labels, merge, import/export, notes, nested conversations, Meilisearch CRM search, and API smoke coverage landed. +Completed implementation slice: B5.1-B5.5 now cover inbox serializer shape, Chatwoot frontend create/update binding, working-hours persistence, out-of-office behavior, inbox member assignment payload/mutation semantics, channel-specific config depth, AgentCapacityPolicy/InboxCapacityLimit API data contracts, and dedicated Email/Twilio/LINE channel route response shapes. B4 remains in review after contact/company CRUD payloads, relations, labels, merge, import/export, notes, nested conversations, Meilisearch CRM search, and API smoke coverage landed. -Next implementation slice: final B5.5 channel-specific route response cleanup review. Keep B3 and B4 in review for delivery/storage side-effect parity and real browser frontend validation. +Next implementation slice: B6 Meilisearch live-shape review. Keep B3 and B4 in review for delivery/storage side-effect parity and real browser frontend validation. | Step | Required result | Reference source | Verification | | --- | --- | --- | --- | @@ -106,7 +107,8 @@ Next implementation slice: final B5.5 channel-specific route response cleanup re | N3 | Persist inbox working hours and out-of-office behavior with Chatwoot defaults. | `OutOfOffisable`, `Inbox#OFFISABLE_ATTRS`, settings pages. | Done by `945782e`; update tests prove weekly schedule persistence and service tests prove out-of-office behavior. | | N4 | Align inbox member payloads and membership mutation semantics. | `InboxMembersController`, `Inbox#add_members/remove_members`, dashboard `inboxMembers.js`. | Done by `82167f5`; account-scoped and nested member routes return `{ payload: [agent] }`, create is add-only/idempotent, update is diff-based, and delete returns empty `200 OK`. | | N5 | Land AgentCapacityPolicy/InboxCapacityLimit Chatwoot API parity. | `reference/chatwoot/config/routes.rb:123-127`, enterprise agent capacity policy and inbox limit controllers/views/models. | Done by `b197e54`; policy CRUD returns raw Chatwoot payloads, nested inbox-limit and user routes are registered, duplicate/negative/wrong-account limits and `assigned_agent_count` are covered, route dump is `TOTAL: 829`, and tracked route parity has 0 missing routes. | -| N6 | Update this tracker after every implementation checkpoint. | This document. | `git diff --check`; `go test ./...` for Go changes. | +| N6 | Align dedicated Email, Twilio SMS, and LINE channel response envelopes for reused frontend compatibility. | `reference/chatwoot/app/controllers/api/v1/accounts/channels/twilio_channels_controller.rb`, dashboard channel clients and generic inbox serializer. | Done by `f04a03b`; create/get/update return raw inbox payloads, list returns `{ payload: [...] }`, delete returns empty `200 OK`, and focused channel handler tests cover all three dedicated handlers. | +| N7 | Update this tracker after every implementation checkpoint. | This document. | `git diff --check`; `go test ./...` for Go changes. | Current B2 profile checkpoint: @@ -172,7 +174,8 @@ Current B5 inbox/channel checkpoint: - Generic inbox JSON create/update now persists flat channel-specific frontend keys used by Email IMAP/SMTP settings and settings-page toggles, not only nested `channel` payloads. - Inbox serializer depth now covers Email IMAP/SMTP/forwarding fields, WhatsApp `provider_config` and generated webhook verify token, LINE channel credentials, SMS provider config, and Twilio SMS/WhatsApp/voice fields. Twilio channel creation accepts Chatwoot's nested `twilio_channel` payload and returns the raw inbox serializer instead of `{ channel, inbox }`. - AgentCapacityPolicy and InboxCapacityLimit API/data parity now covers raw policy serializers, optional/defaulted `assignment_logic`, nested users and inbox-limit routes, account-scoped inbox validation, duplicate prevention, non-negative limits, and `assigned_agent_count` through `account_users.agent_capacity_policy_id`. -- Remaining B5 gap: review any remaining channel-specific route response cleanup outside the generic inbox path. +- Dedicated Email, Twilio SMS, and LINE channel create/get/update/list/delete routes now use frontend-compatible inbox payload contracts: raw inbox objects for single-resource mutations, `{ payload: [...] }` for lists, and empty `200 OK` for deletes. The handlers bind the dedicated channel record ID/config back onto `inboxes.channel_id/channel_config` before serialization. +- Remaining B5 gap: none for the current frontend-critical API scope. Browser validation remains deferred to B12/M7. Active B5 task board: @@ -182,7 +185,7 @@ Active B5 task board: | B5.2 | Inbox create/update request binding and settings persistence. | `buildInboxData`, `permitted_params`, settings pages. | Done | `ee93546`; JSON and multipart `channel[...]` requests persist core inbox/channel settings. | | B5.3 | Working hours and out-of-office parity. | `OutOfOffisable`, working hour controller/model. | Done | `945782e`; weekly schedule create/update/show and `out_of_office` service tests match Chatwoot semantics. | | B5.4 | Inbox member payload and round-robin side effects. | `InboxMembersController`, `Inbox#add_members/remove_members`. | Done | `82167f5`; account-scoped and nested member routes return `{ payload }` agents, create is add-only/idempotent, update is diff-based, and delete is empty `200 OK`. | -| B5.5 | Channel-specific config depth and inbox limits. | WebWidget/API/Telegram/Email/WhatsApp/SMS/LINE channel models/controllers, enterprise inbox limits. | Review | `b197e54`; Email/WhatsApp/LINE/SMS/Twilio config payloads, Twilio create route, and AgentCapacityPolicy/InboxCapacityLimit API/data parity are covered. Remaining work is final channel-specific route response cleanup review. | +| B5.5 | Channel-specific config depth and inbox limits. | WebWidget/API/Telegram/Email/WhatsApp/SMS/LINE channel models/controllers, enterprise inbox limits. | Done | `f04a03b`; Email/WhatsApp/LINE/SMS/Twilio config payloads, Twilio create route, AgentCapacityPolicy/InboxCapacityLimit API/data parity, and dedicated Email/Twilio/LINE response cleanup are covered. | B5.2 execution breakdown: @@ -216,10 +219,11 @@ B5.5 planned breakdown: | Step | Implementation target | Reference source | Required tests | Status | | --- | --- | --- | --- | --- | -| B5.5a | Compare current Go channel config fields against Chatwoot channel models/controllers for WebWidget, API, Telegram, Email, WhatsApp, Twilio SMS, and LINE. | `reference/chatwoot/app/models/channel/*`, channel controllers, dashboard inbox setting screens. | `f0aae79` documents and tests the first matrix through Email/WhatsApp/LINE/SMS/Twilio serializer fields; keep open for final route-response cleanup review. | Review | +| B5.5a | Compare current Go channel config fields against Chatwoot channel models/controllers for WebWidget, API, Telegram, Email, WhatsApp, Twilio SMS, and LINE. | `reference/chatwoot/app/models/channel/*`, channel controllers, dashboard inbox setting screens. | Done by `f04a03b`; config matrix is covered and dedicated Email/Twilio/LINE route responses are frontend-compatible. | Done | | B5.5b | Persist and serialize deeper channel-specific settings used by reused settings screens, preferring first-class columns only where GoChat already has them and `channel_config` otherwise. | Chatwoot channel model validations and `InboxesController#permitted_params`. | Done by `f0aae79`; handler tests cover Email IMAP/SMTP flat JSON update, WhatsApp provider config, LINE credentials, and Twilio nested create raw inbox payload. | Done | | B5.5c | Enforce enterprise InboxLimit during inbox/channel creation and return frontend-compatible over-limit errors. | Chatwoot enterprise inbox limit policy/model behavior. | Done by `b197e54`; nested policy inbox limits validate duplicate/wrong-account/non-negative inputs and expose Chatwoot payloads. Assignment-path enforcement remains in B7/P4.4. | Done | | B5.5d | Keep route artifacts unchanged unless new Chatwoot-compatible routes are registered; regenerate route dump only on route changes. | `cmd/dump_routes`, `cmd/route_parity`. | Done by `b197e54`; route dump regenerated to `TOTAL: 829`, route parity expanded to 274 tracked routes with 0 missing. | Done | +| B5.5e | Clean up dedicated channel controller envelopes outside generic inbox CRUD. | Twilio channel controller/view, dashboard channel clients, `api/v1/models/_inbox.json.jbuilder`. | Done by `f04a03b`; Email/Twilio/LINE create/get/update return raw inbox payloads, list returns `{ payload: [...] }`, delete returns empty `200 OK`, and no route artifacts changed. | Done | B5.5c AgentCapacityPolicy / InboxCapacityLimit parity contract: @@ -248,10 +252,20 @@ B5.5 channel config matrix after `f0aae79`: | --- | --- | --- | --- | | WebWidget | Generic FormData/JSON `channel[...]`, selected feature flags, HMAC, domains, pre-chat defaults. | Website token, HMAC token, widget color, welcome copy, pre-chat options, continuity, reply time. | Review final settings-page edge fields only. | | API | Generic JSON/FormData `webhook_url`, HMAC, additional attributes, generated identifier/secret. | Secret, webhook URL, inbox identifier, HMAC token, additional attributes. | Review validation parity for `agent_reply_time_window`. | -| Email | Flat JSON IMAP/SMTP updates and nested create fields are hoisted into `channel_config`. | Email, forwarding, IMAP, SMTP, auth, SSL/TLS, domain fields. | Dedicated email-channel controller response shape still needs final review. | +| Email | Flat JSON IMAP/SMTP updates and nested create fields are hoisted into `channel_config`; dedicated email-channel create/update bind channel IDs/config back to inboxes. | Email, forwarding, IMAP, SMTP, auth, SSL/TLS, domain fields. | Done for current frontend-critical API scope. | | WhatsApp | Manual/cloud create stores `phone_number`, `provider`, nested `provider_config`, and generates cloud webhook verify token. | Phone number, provider, provider config, message templates, reauthorization, voice flag. | Provider credential validation and embedded signup deep behavior remain later integration work. | -| Twilio SMS/WhatsApp | Nested `twilio_channel` frontend create payload accepted; SMS/WhatsApp medium and phone normalization stored in inbox config. | Phone, messaging service SID, medium, content templates, auth/account/API key fields, voice flags. | Update/delete/list route responses still need final raw-inbox parity review. | -| LINE/SMS | Generic create stores LINE credentials and Bandwidth SMS provider config. | LINE credentials; SMS phone/provider config. | LINE is present in local reference but lacks deep serializer fields upstream; keep behavior frontend-compatible. | +| Twilio SMS/WhatsApp | Nested `twilio_channel` frontend create payload accepted; SMS/WhatsApp medium and phone normalization stored in inbox config; dedicated Twilio create/get/update/list/delete responses now use raw inbox/list/empty contracts. | Phone, messaging service SID, medium, content templates, auth/account/API key fields, voice flags. | Done for current frontend-critical API scope. | +| LINE/SMS | Generic create stores LINE credentials and Bandwidth SMS provider config; dedicated LINE create/get/update/list/delete responses now use raw inbox/list/empty contracts. | LINE credentials; SMS phone/provider config. | LINE behavior is frontend-compatible and preserves both Chatwoot-style `line_channel_*` keys and local webhook `channel_*` config aliases. | + +Active B6 task board: + +| ID | Task | Reference source | Status | Exit gate | +| --- | --- | --- | --- | --- | +| B6.1 | Inventory Chatwoot search frontend request/response consumers and current Go search routes. | `reference/chatwoot/app/javascript/dashboard/api/search.js`, `conversationSearch.js`, `SearchController`, `internal/handler/api/v1/search_handler.go`. | Todo | A checked matrix lists global, contacts, conversations, messages, and articles search params and payload fields. | +| B6.2 | Compare Meilisearch document fields and filters against frontend payload needs. | `internal/search/engine.go`, `engine_meili.go`, document builders, Chatwoot search views/entities. | Todo | Mocked Meilisearch tests prove account scoping, type filters, pagination, and result data shape without DB-only assumptions. | +| B6.3 | Tighten endpoint serializers for `/search`, `/search/contacts`, `/search/conversations`, `/search/messages`, and `/search/articles`. | `reference/chatwoot/app/controllers/api/v1/accounts/search_controller.rb`, dashboard search API specs. | Todo | Handler fixture tests assert Chatwoot-compatible `payload/meta` or documented search result shapes for each endpoint. | +| B6.4 | Add optional live Meilisearch integration gate. | Local Meilisearch flow in Phase 1 and `cmd/reindex_search`. | Todo | Env-gated test or documented command runs reindex plus representative searches against a live Meilisearch instance. | +| B6.5 | Document DB fallback as development-only and verify production config remains Meilisearch-first. | User decision ledger and search config. | Todo | Config tests and docs make `meilisearch` the default and warn on DB fallback. | Active B4 task board: @@ -281,7 +295,7 @@ This is the ordered queue for the next implementation slices. Do not skip the ro | Q2 | Patch route aliases discovered by Q1, especially Chatwoot widget/public paths such as `/api/v1/widget/...` versus existing `/widget/...`. | Phase 2 | Missing tracked routes return to zero or are explicitly documented with implementation tasks. | Done | | Q3 | Add route boot regression coverage for wildcard conflict groups before expanding more Rails-style resources. | Phase 2 | Router tests cover nested dynamic resources that previously risked Gin conflicts. | Done | | Q4 | Start serializer parity fixtures for auth/session, conversations/messages, contacts/companies, inboxes, notifications, and search. | Phase 3 | Each area has at least one reference fixture and Go response test. | Doing | -| Q5 | Review Meilisearch document shape and endpoint payloads against Chatwoot frontend consumers. | Phase 1 and Phase 3 | Search remains Meilisearch-first and payload mismatches are fixed or tracked. | Todo | +| Q5 | Review Meilisearch document shape and endpoint payloads against Chatwoot frontend consumers. | Phase 1 and Phase 3 | Search remains Meilisearch-first and payload mismatches are fixed or tracked. | Doing | | Q6 | Implement provider-specific webhook ingress for Chatwoot public webhook paths. | Phase 6 | Generic webhook placeholder no longer masks provider gaps; Telegram, LINE, SMS/Twilio, WhatsApp, Instagram/Twitter/TikTok routes resolve and verify like Chatwoot where supported. | Done | | Q7 | Burn down enterprise gaps in this order: SLA, assignment policy and capacity, CSAT, automation/macros, Audit, CustomRole, InboxLimit, Captain/Copilot. | Phase 4 and Phase 5 | Each feature passes route, persistence, auth, side-effect, response, and test checks. | Todo | | Q8 | Add frontend smoke harness using the reused Chatwoot frontend once core API flows boot end-to-end. | Phase 7 | Login, inbox list, conversation list/detail, message send, contact view, and widget init run without frontend adapters. | Todo | @@ -305,7 +319,7 @@ These milestones are the tracking spine for the remaining Chatwoot frontend reus | Milestone | Scope | Exit gate | Status | | --- | --- | --- | --- | | M0 | Test, route, and documentation baseline. | Clean worktree, `go test ./...`, route dump/parity artifacts current. | Done | -| M1 | Meilisearch-first search foundation. | Config, engine, indexing hooks, reindex command, mocked tests, and live-shape review tracked. | Review | +| M1 | Meilisearch-first search foundation. | Config, engine, indexing hooks, reindex command, mocked tests, and live-shape review tracked. | Doing | | M2 | Route parity expansion for frontend-critical routes. | Tracked route set has zero missing routes and every new route group has router boot coverage. | Doing | | M3 | Serializer parity for frontend API families. | Fixture tests cover auth/profile, accounts/users, inboxes, conversations/messages, contacts/companies, notifications, reports, widget/public, and search. | Doing | | M4 | Core handler placeholder burn-down. | Account/contact/conversation/message/inbox/webhook handlers are repository-backed and no frontend-critical route returns placeholder JSON. | Doing | @@ -323,8 +337,8 @@ Work proceeds top-down unless a failing test or frontend blocker forces a narrow | B2 | Auth/profile serializer fixtures. | `reference/chatwoot/app/controllers/api/v1/profile*`, frontend auth client. | Fixture tests for login/current user/profile/availability/settings. | Done | | B3 | Conversation/message serializer and behavior fixtures. | Chatwoot conversation/message controllers, entities, jobs. | Fixture tests for list/show/create/update/private notes/attachments/status/assignment. | Review | | B4 | Contact/company behavior fixtures. | Chatwoot contact/company controllers, merge/import/export/notes/labels. | Fixture tests for CRUD/search/merge/relation/import-export shells and frontend CRM API smoke. | Review | -| B5 | Inbox/channel behavior fixtures. | Chatwoot inbox/channel controllers and channel models. | Fixture tests for inbox CRUD, settings, business hours, members, avatar, channel config. | Doing | -| B6 | Meilisearch live-shape review. | Chatwoot frontend search usage and search controllers. | Meilisearch-backed response fixtures plus optional live integration gate. | Todo | +| B5 | Inbox/channel behavior fixtures. | Chatwoot inbox/channel controllers and channel models. | Fixture tests for inbox CRUD, settings, business hours, members, avatar, channel config. | Done | +| B6 | Meilisearch live-shape review. | Chatwoot frontend search usage and search controllers. | Meilisearch-backed response fixtures plus optional live integration gate. | Doing | | B7 | SLA and assignment capacity. | Chatwoot enterprise SLA and assignment policy behavior. | Unit/integration tests for SLA state, breach, assignment capacity, policy selection. | Todo | | B8 | CSAT account-side completion. | Chatwoot CSAT survey responses, reports, downloads, listeners. | Metrics/list/review/download/send idempotency tests. | Todo | | B9 | Automation/macros durable side effects. | Chatwoot automation/macro services and jobs. | Action execution, logs, webhook/email transcript retry tests. | Todo | @@ -554,7 +568,7 @@ Frontend-critical API groups to audit first: | --- | --- | --- | --- | | P3.1 | Auth/session/profile | Login, logout, current user, profile, availability, notification settings. | Done | | 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.3 | Inboxes/channels | Inbox CRUD, assignable agents, avatars, channel config, business hours, widget config. | Done | | P3.4 | Conversations/messages | List filters, status changes, assignment, labels, private notes, attachments, drafts, typing/read events. | Review | | P3.5 | Contacts/companies | CRUD, merge, labels, notes, custom attributes, import/export, conversations relation. | Doing | | P3.6 | Labels/custom attributes/custom filters | Create/update/list behavior and exact response shapes. | Todo | @@ -569,7 +583,7 @@ Serializer parity work plan: | S1 | Auth and profile | `reference/chatwoot/app/controllers/api/v1/profile*`, frontend auth API usage | fixture tests for current user/profile payloads | Done | | S2 | Conversations and messages | `reference/chatwoot/app/controllers/api/v1/accounts/conversations*`, serializers/entities | fixture tests for index/show/message create/update | Review | | S3 | Contacts and companies | `reference/chatwoot/app/controllers/api/v1/accounts/contacts*`, `companies*` | fixture tests for list/show/search/merge/relation payloads | Doing | -| S4 | Inboxes and channels | `reference/chatwoot/app/controllers/api/v1/accounts/inboxes*`, channel controllers | fixture tests for inbox CRUD, channel settings, widget config | Doing | +| S4 | Inboxes and channels | `reference/chatwoot/app/controllers/api/v1/accounts/inboxes*`, channel controllers | fixture tests for inbox CRUD, channel settings, widget config | Done | | S5 | Notifications and settings | `reference/chatwoot/app/controllers/api/v1/accounts/notifications*` | fixture tests for notification list/actions/settings | Todo | | S6 | Reports and CSAT | `reference/chatwoot/app/controllers/api/v1/accounts/reports*`, `csat_survey_responses*` | fixture tests for report filters and CSAT metrics/list | Todo | | S7 | Widget/public | `reference/chatwoot/app/controllers/api/v1/widget*`, `public/api/v1*` | widget smoke fixtures and public flow tests | Doing | @@ -842,3 +856,4 @@ Verification milestone gates: - 2026-06-05: B5.5 channel config depth checkpoint committed as `f0aae79 feat(inboxes): deepen channel config parity`; generic inbox JSON updates now hoist flat SMTP/IMAP/channel settings into channel config, Email/WhatsApp/LINE/SMS/Twilio serializers expose deeper Chatwoot frontend fields, WebWidget/API/Email/WhatsApp defaults are closer to Chatwoot, and Twilio channel create accepts nested `twilio_channel` payloads while returning the raw inbox serializer. Focused channel-depth tests, service inbox tests, handler package tests, full `go test ./...`, and `git diff --check` passed. Route dump unchanged at `TOTAL: 821`. - 2026-06-05: B5.5c planning contract added for AgentCapacityPolicy/InboxCapacityLimit parity; the next slice now tracks exact Chatwoot route sources, raw policy and inbox-limit serializers, optional `assignment_logic`, nested `users` and `inbox_limits` routes, duplicate/wrong-account/non-negative validation gates, and route artifact regeneration rules before implementation starts. - 2026-06-05: B5.5c AgentCapacityPolicy/InboxCapacityLimit checkpoint committed as `b197e54 feat(capacity): align chatwoot inbox capacity limits`; policy CRUD now returns raw Chatwoot serializers, nested policy users and inbox limits are implemented, `account_users.agent_capacity_policy_id` is persisted, duplicate/wrong-account/non-negative limit checks are covered, route dump is `TOTAL: 829`, tracked route parity is `267 exact, 7 parameter-compatible, 0 missing`, focused service/handler/router tests passed, sandboxed full tests failed only on socket restrictions, escalated full `go test ./...` passed, and `git diff --check` passed. +- 2026-06-05: B5.5 final channel route-response cleanup committed as `f04a03b feat(channels): align channel route inbox payloads`; Email, Twilio SMS, and LINE dedicated channel routes now return raw Chatwoot-compatible inbox payloads for create/get/update, `{ payload: [...] }` for list, and empty `200 OK` for delete. `InboxService.BindChannel` keeps dedicated channel IDs/configs reflected in inbox serialization. Focused Email/Twilio/LINE channel tests, service inbox tests, handler package tests, full `go test ./...`, and `git diff --check` passed. Route dump unchanged at `TOTAL: 829`; next active slice is B6 Meilisearch live-shape review.