docs: record inbox request binding checkpoint

This commit is contained in:
2026-06-05 05:10:16 +08:00
parent ee93546def
commit ff98202c38
+14 -10
View File
@@ -16,7 +16,7 @@ Build GoChat as a Go backend that can directly reuse the frontend from `referenc
## Current Baseline
- Latest implementation checkpoint: `0e83e8d feat(inboxes): align chatwoot inbox serializers`.
- Latest implementation checkpoint: `ee93546 feat(inboxes): bind chatwoot channel settings`.
- Latest documentation checkpoint before this consolidation: `1f6ec3e docs: record inbox serializer checkpoint`.
- Worktree status at this planning checkpoint: clean after docs checkpoint.
- `go test ./...` passes.
@@ -86,6 +86,7 @@ This ledger records the committed parity checkpoints that future slices should b
| `c2766fe feat(crm): email contact export completions` | Completed B4 contact export email delivery: the completed export artifact now triggers a Chatwoot-style `contact_export_complete` mailer boundary for the requesting user's email, using the same subject and download URL semantics while preserving the existing persisted notification. The default mailer reads Chatwoot-compatible SMTP env vars and no-ops when SMTP is not configured. | Focused export/service/API tests passed; full `go test ./...` passed; `git diff --check` passed. No route changes; route dump remains `TOTAL: 820`. | Continue B4 with frontend CRM smoke fixtures. |
| `ad29dc3 test(crm): cover chatwoot frontend crm smoke` | Closed the B4 CRM API smoke gap with a repeatable handler-level flow that mirrors the reused Chatwoot dashboard contact/company clients: contact create/list/search/show/update/custom-attribute deletion/labels/contactable-inboxes/notes/conversations plus company create/list/search/show/update/custom-attribute deletion/contact attach/list/search/notes/conversations. | `go test ./internal/handler/api/v1 -run TestChatwootFrontendCRMSmoke -count=1`; `go test ./internal/handler/api/v1 -count=1`; `go test ./...`; `git diff --check`. | Move B4 to review. True browser Playwright validation with the reused frontend remains tracked by B12/M7. |
| `0e83e8d feat(inboxes): align chatwoot inbox serializers` | Started B5 inbox/channel parity by rendering Chatwoot `api/v1/models/_inbox.json.jbuilder`-style payloads for inbox list/show/create/update/reset-secret flows, mapping local channel slugs to `Channel::*` class names, exposing channel-specific settings from `channel_config`, returning Chatwoot's async delete message, making avatar delete empty `200 OK`, and adding the frontend-used `PATCH /inboxes/:id` route. | `go test ./internal/handler/api/v1 -run 'TestInboxHandler_ChatwootSerializerParity|TestInbox' -count=1`; `go test ./internal/handler/api/v1 -count=1`; regenerated `docs/parity/gochat_routes.txt` (`TOTAL: 821`); `go run ./cmd/route_parity`; `go test ./...`; `git diff --check`. | Continue B5 with create/update request binding for Chatwoot multipart `channel[...]` payloads, working-hours/settings persistence, inbox members, and channel-specific config depth. |
| `ee93546 feat(inboxes): bind chatwoot channel settings` | Completed B5.2 request binding for reused dashboard inbox create/update flows: JSON and multipart/urlencoded bodies now accept top-level inbox settings, nested `channel[...]`, nested `csat_config[...]`, selected feature flags, API webhook config, generated web widget/API secrets, and Telegram create without explicit `name`. | `go test ./internal/handler/api/v1 -run 'TestInboxHandler_ChatwootSerializerParity\|TestInboxHandler_ChatwootCreateUpdateRequestBinding\|TestInbox' -count=1`; `go test ./internal/service -run Inbox -count=1`; `go test ./internal/handler/api/v1 -count=1`; escalated `go test ./...` after sandbox socket denial; `git diff --check`. | Continue B5.3 with durable working-hours update behavior and out-of-office parity, then B5.4 inbox members and B5.5 channel-specific config depth. |
## Next Slice Contract
@@ -96,8 +97,8 @@ Next implementation slice: continue B5 inbox/channel behavior fixtures. Keep B3
| Step | Required result | Reference source | Verification |
| --- | --- | --- | --- |
| N1 | Align inbox list/show/create/update/delete/avatar/reset-secret serializer shapes. | `InboxesController`, `api/v1/models/_inbox.json.jbuilder`, dashboard inbox store. | Done by `0e83e8d`; list returns `{ payload: [...] }`, item responses are raw inbox payloads, channel slugs serialize as `Channel::*`, and route dump is `TOTAL: 821`. |
| N2 | Accept Chatwoot frontend inbox create/update request bodies, including multipart FormData and `channel[...]` nested params. | `dashboard/store/modules/inboxes.js#buildInboxData`, `InboxesController#permitted_params`. | Handler tests cover website/API/telegram create and settings update request bodies. |
| N3 | Persist inbox settings and working hours with Chatwoot defaults. | `OutOfOffisable`, `Inbox#OFFISABLE_ATTRS`, settings pages. | Update tests prove greeting, CSAT, auto-assignment, timezone, sender, business name, and weekly schedule behavior. |
| N2 | Accept Chatwoot frontend inbox create/update request bodies, including multipart FormData and `channel[...]` nested params. | `dashboard/store/modules/inboxes.js#buildInboxData`, `InboxesController#permitted_params`. | Done by `ee93546`; handler tests cover website multipart create, API JSON create, Telegram no-name create, and settings update request bodies. |
| N3 | Persist inbox working hours and out-of-office behavior with Chatwoot defaults. | `OutOfOffisable`, `Inbox#OFFISABLE_ATTRS`, settings pages. | Next; update tests prove weekly schedule and out-of-office behavior, while core settings are already covered by `ee93546`. |
| N4 | Deepen inbox member/channel-specific flows. | `InboxMembersController`, channel controllers/models. | Member list/update and channel config tests return frontend-compatible payloads. |
| N5 | Update this tracker after every implementation checkpoint. | This document. | `git diff --check`; `go test ./...` for Go changes. |
@@ -157,14 +158,16 @@ Current B5 inbox/channel checkpoint:
- Local channel slugs are serialized to frontend-required Rails channel class names such as `Channel::WebWidget`, `Channel::Api`, `Channel::Telegram`, and `Channel::TwilioSms`.
- Channel-specific fields stored in `channel_config` are surfaced in the inbox payload for web widget, API, Telegram, Facebook/Instagram/TikTok, Twilio, Email, and WhatsApp-style keys.
- Added the frontend-used `PATCH /api/v1/accounts/:account_id/inboxes/:inbox_id` route alias; route dump is now `TOTAL: 821`, and tracked route parity remains regenerated with zero missing tracked routes.
- Remaining B5 gaps: Chatwoot multipart `channel[...]` create/update binding, durable working-hours update behavior, full inbox settings persistence, inbox member payload depth, channel-specific creation/config parity, and inbox limit enforcement.
- Chatwoot dashboard create/update request bodies now bind through the generic inbox route for JSON, urlencoded forms, and multipart FormData. The binder accepts top-level inbox settings, nested `channel[...]`, `channel[selected_feature_flags][]`, and nested `csat_config[...]` values generated by `buildInboxData`.
- Create/update now persists greeting/email collection/CSAT/auto-assignment/timezone/post-resolve/single-conversation/sender/business settings, stores channel-specific fields in `channel_config`, generates web widget `website_token`/`hmac_token`, generates API `secret`/`hmac_token`/identifier, and derives a Telegram inbox name when the frontend omits `name`.
- Remaining B5 gaps: durable working-hours update behavior, out-of-office schedule semantics, inbox member payload depth, deeper LINE/Twilio/Email/WhatsApp channel-specific creation/config parity, and inbox limit enforcement.
Active B5 task board:
| ID | Task | Reference source | Status | Exit gate |
| --- | --- | --- | --- | --- |
| B5.1 | Inbox CRUD serializer and route shape. | `InboxesController`, `_inbox.json.jbuilder`, dashboard inbox store/API. | Done | `0e83e8d`; serializer parity test, route dump `TOTAL: 821`, full tests. |
| B5.2 | Inbox create/update request binding and settings persistence. | `buildInboxData`, `permitted_params`, settings pages. | Todo | JSON and multipart `channel[...]` requests persist core inbox/channel settings. |
| 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. | Todo | Weekly schedule create/update/show and `out_of_office` tests match Chatwoot semantics. |
| B5.4 | Inbox member payload and round-robin side effects. | `InboxMembersController`, `Inbox#add_members/remove_members`. | Todo | Account-scoped and nested member routes return `{ payload }` agents and update membership idempotently. |
| B5.5 | Channel-specific config depth. | WebWidget/API/Telegram/Email/WhatsApp/SMS/LINE channel models/controllers. | Todo | Channel create/update/show tests cover frontend settings screens. |
@@ -173,11 +176,11 @@ B5.2 execution breakdown:
| Step | Implementation target | Reference source | Required tests | Status |
| --- | --- | --- | --- | --- |
| B5.2a | Add a request binder that accepts JSON, urlencoded form, and multipart FormData from the reused dashboard inbox screens. It must parse top-level settings plus nested keys such as `channel[type]`, `channel[website_url]`, `channel[selected_feature_flags][]`, and `csat_config[...]`. | `reference/chatwoot/app/javascript/dashboard/store/modules/inboxes/channelActions.js`, `reference/chatwoot/app/javascript/dashboard/store/modules/inboxes.js` | Handler tests for website multipart create, API JSON create, Telegram JSON create without explicit name, and settings update. | Next |
| B5.2b | Normalize channel type aliases from frontend slugs and Rails class names into the local storage format while keeping serializers Rails-compatible. | `reference/chatwoot/app/models/channel/*`, `_inbox.json.jbuilder` | Serializer tests prove stored slug returns `Channel::*` and unknown channel types are rejected with frontend-readable validation errors. | Todo |
| B5.2c | Persist core inbox settings sent by `permitted_params`: greeting, email collection, CSAT flag/config, auto-assignment, working-hours flag, out-of-office message, timezone, post-resolve messages, single-conversation lock, sender name type, business name, and portal ID. | `reference/chatwoot/app/controllers/api/v1/accounts/inboxes_controller.rb`, inbox settings Vue screens | Create/update tests reload the inbox and assert fields survive round trip in Chatwoot payload names. | Todo |
| B5.2d | Persist channel-specific settings into dedicated fields where they exist and `channel_config` where GoChat has no first-class column yet. | WebWidget/API/Telegram/LINE/Twilio/Email channel models and settings screens | Tests cover web widget `website_url/widget_color/welcome_*`, API `webhook_url`, Telegram `bot_token`, and LINE `line_channel_id` shapes. | Todo |
| B5.2e | Preserve backward compatibility for internal tests and existing local callers that still construct `service.CreateInboxRequest` with `channel_type` and simple fields. | Existing Go service callers and handler tests | Existing `TestInbox*` suite stays green. | Todo |
| B5.2a | Add a request binder that accepts JSON, urlencoded form, and multipart FormData from the reused dashboard inbox screens. It must parse top-level settings plus nested keys such as `channel[type]`, `channel[website_url]`, `channel[selected_feature_flags][]`, and `csat_config[...]`. | `reference/chatwoot/app/javascript/dashboard/store/modules/inboxes/channelActions.js`, `reference/chatwoot/app/javascript/dashboard/store/modules/inboxes.js` | Handler tests for website multipart create, API JSON create, Telegram JSON create without explicit name, and settings update. | Done |
| B5.2b | Normalize channel type aliases from frontend slugs and Rails class names into the local storage format while keeping serializers Rails-compatible. | `reference/chatwoot/app/models/channel/*`, `_inbox.json.jbuilder` | Serializer tests prove stored slug returns `Channel::*` and unknown channel types are rejected with frontend-readable validation errors. | Done |
| B5.2c | Persist core inbox settings sent by `permitted_params`: greeting, email collection, CSAT flag/config, auto-assignment, working-hours flag, out-of-office message, timezone, post-resolve messages, single-conversation lock, sender name type, business name, and portal ID. | `reference/chatwoot/app/controllers/api/v1/accounts/inboxes_controller.rb`, inbox settings Vue screens | Create/update tests reload the inbox and assert fields survive round trip in Chatwoot payload names. | Done |
| B5.2d | Persist channel-specific settings into dedicated fields where they exist and `channel_config` where GoChat has no first-class column yet. | WebWidget/API/Telegram/LINE/Twilio/Email channel models and settings screens | Tests cover web widget `website_url/widget_color/welcome_*`, API `webhook_url`, and Telegram `bot_token` shapes. LINE deep settings remain in B5.5. | Review |
| B5.2e | Preserve backward compatibility for internal tests and existing local callers that still construct `service.CreateInboxRequest` with `channel_type` and simple fields. | Existing Go service callers and handler tests | Existing `TestInbox*` suite stays green. | Done |
B5.2 exit command set:
@@ -769,3 +772,4 @@ Verification milestone gates:
- 2026-06-05: B5 inbox serializer checkpoint committed as `0e83e8d feat(inboxes): align chatwoot inbox serializers`; inbox list now returns `{ payload: [...] }`, show/create/update/reset-secret return raw Chatwoot-style inbox payloads, channel slugs serialize as `Channel::*`, avatar delete returns empty `200 OK`, async delete message matches Chatwoot, and `PATCH /api/v1/accounts/:account_id/inboxes/:inbox_id` was added. Focused inbox tests, handler package tests, route dump `TOTAL: 821`, route parity, full `go test ./...`, and `git diff --check` passed.
- 2026-06-05: B5 documentation checkpoint committed as `1f6ec3e docs: record inbox serializer checkpoint`; B5.1 is Done and B5.2 multipart/JSON `channel[...]` create/update binding is the next active implementation slice.
- 2026-06-05: Planning tracker expanded for handoff continuity. B5.2 now has executable substeps, B6-B12 have explicit first checkpoints and Done rules, and every future checkpoint has a required documentation update rule.
- 2026-06-05: B5.2 inbox request binding checkpoint committed as `ee93546 feat(inboxes): bind chatwoot channel settings`; generic inbox create/update now accepts Chatwoot frontend JSON and multipart/urlencoded FormData, persists top-level inbox settings and nested channel/CSAT config, generates web widget/API secrets, and supports Telegram creation without an explicit name. Focused inbox handler tests, service inbox tests, handler package tests, escalated full `go test ./...`, and `git diff --check` passed. Route dump unchanged at `TOTAL: 821`.