From b5f2a47ef84092cd198b3b28a80f307b66a4a1b5 Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 5 Jun 2026 10:53:24 +0800 Subject: [PATCH] docs: land remaining parity tracker --- docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md | 76 +++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md b/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md index 8cc16e7a..d60b8357 100644 --- a/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md +++ b/docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md @@ -17,8 +17,8 @@ Build GoChat as a Go backend that can directly reuse the frontend from `referenc ## Current Baseline - Latest implementation checkpoint: `feat(audit): cover operational mutations`. -- Latest documentation checkpoint: this checkpoint, recorded with the B10.2b audit writer implementation. -- Worktree status at this implementation checkpoint: B10.2 audit writer coverage now includes automation rules, macros, custom roles, CSAT review notes, inbox create/update, conversation update/assignment/status/delete, SLA policy CRUD, AgentCapacityPolicy CRUD, capacity users, and inbox capacity limits; next active slice is B10.3 CustomRole permission parity. +- Latest documentation checkpoint: `docs: land remaining parity tracker`. +- Worktree status at this implementation checkpoint: B10.2 audit writer coverage now includes automation rules, macros, custom roles, CSAT review notes, inbox create/update, conversation update/assignment/status/delete, SLA policy CRUD, AgentCapacityPolicy CRUD, capacity users, and inbox capacity limits; the tracker now carries executable contracts for B10.3 CustomRole parity, B10.4 InboxLimit enforcement, B11 Captain/Copilot, and B12 reused-frontend smoke validation. - `go test ./...` passes. - Route dump succeeds with `TOTAL: 830` after adding the Chatwoot-compatible applied-SLA index route. - Route parity artifacts now exist under `docs/parity/` and are generated by `cmd/route_parity`. @@ -144,6 +144,7 @@ This ledger records the committed parity checkpoints that future slices should b | `feat(audit): align chatwoot audit log payloads` | Completed B10.1 audit log list parity for the reused enterprise settings screen: `/audit_logs` now returns Chatwoot top-level `per_page`, `total_entries`, `current_page`, and `audit_logs`; pagination is fixed at 25 per page; list/get require administrator/super_admin role; account scoping matches associated audits as well as local `account_id`; and serializer fields match the enterprise Jbuilder shape with Unix `created_at`. | `go test ./internal/handler/api/v1 -run Audit -count=1`; `go test ./internal/repository -run Audit -count=1`; `go test ./internal/service -run Audit -count=1`; `go test ./internal/handler/api/v1 -count=1`; `go test ./...`; `git diff --check`. No route changes; route dump remains `TOTAL: 830`. | Continue B10.2 audit writer coverage, then B10.3 CustomRole permission-key/account-user parity. | | `feat(audit): record enterprise mutations` | Completed B10.2a audit writer boundary and first enterprise mutation coverage: `AuditService.Record` now creates account-associated audit rows with actor, request UUID, remote address, action, auditable type/id, and JSON changes; automation-rule create/update/delete/clone/toggle, macro create/update/delete, custom-role create/update/delete, and CSAT review-note update call the shared writer. | `go test ./internal/handler/api/v1 -run 'CustomRole\|AutomationRule\|Macro\|CsatSurvey' -count=1`; `go test ./internal/service -run Audit -count=1`; `go test ./internal/handler/api/v1 -count=1`; `go test ./...`; `git diff --check`. No route changes; route dump remains `TOTAL: 830`. | Continue B10.2b inbox/conversation/SLA/capacity audit writer coverage, then B10.3 CustomRole permission parity. | | `feat(audit): cover operational mutations` | Completed B10.2b audit writer coverage for the remaining named operational mutations: inbox create/update, conversation update/delete/assign/status, SLA policy create/update/delete, AgentCapacityPolicy create/update/delete, inbox capacity limit create/update/delete, and capacity-policy user assignment/removal now call the shared audit writer. | `go test ./internal/handler/api/v1 -run 'SlaPolicy\|AgentCapacity\|Inbox\|Conversation' -count=1`; `go test ./internal/service -run Audit -count=1`; `go test ./internal/handler/api/v1 -count=1`; `go test ./...`; `git diff --check`. No route changes; route dump remains `TOTAL: 830`. | Continue B10.3 CustomRole permission-key/account-user parity and B10.4 remaining InboxLimit create-path enforcement. | +| `docs: land remaining parity tracker` | Converted the immediate remaining plan into executable tracking contracts: B10.3 now lists CustomRole reference files, permission-array migration, AccountUser role resolution, delete nullification, admin gates, and test exits; B10.4 records InboxLimit create-path enforcement; B11/B12 now have route/persistence/feature-gate and smoke-report landing rules. | Documentation-only checkpoint; `git diff --check` passed. | Start B10.3 implementation from the recorded CustomRole contract. | ## Next Slice Contract @@ -673,6 +674,47 @@ env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./... git diff --check ``` +B10.3 CustomRole landing contract: + +| Area | Chatwoot reference contract | Current Go gap to close | Required landing work | +| --- | --- | --- | --- | +| Reference files | `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`. | Prior checkpoints audited audit emission, not permission-array or account-user role behavior. | Re-check these files immediately before code changes and keep tests tied to their request/response/status contracts. | +| Permission keys | Chatwoot stores `permissions` as a text array containing only `conversation_manage`, `conversation_unassigned_manage`, `conversation_participating_manage`, `contact_manage`, `report_manage`, and `knowledge_base_manage`. | Go currently models permissions as a JSON map with local keys and read/full/none levels. | Accept and serialize Chatwoot arrays, reject invalid keys, and either migrate storage to array semantics or provide a compatibility shim that never leaks the local map shape to frontend APIs. | +| CustomRole API payloads | Index returns a raw array; show/create/update return the raw custom role partial with `id`, `name`, `description`, `permissions`, `created_at`, `updated_at`; destroy is `head :ok`. Permitted params are `custom_role.name`, `description`, and `permissions: []`. | Go custom role handlers still use local response envelopes/statuses and map-shaped permissions. | Replace handler serializer/binder boundary for frontend routes, allow nested `custom_role` params, return raw payloads, make delete return empty `200 OK`, and keep audit writer calls from B10.2. | +| AccountUser role resolution | Chatwoot `AccountUser.role` remains `agent` or `administrator`; custom role is represented by `custom_role_id`. `permissions` returns `custom_role.permissions + ['custom_role']` when present. | Go allows/uses `role = custom_role` in multiple paths and `HasCustomRole` currently depends on the role string. | Keep persisted role as `agent` when assigning a custom role, treat `custom_role_id > 0` as the source of custom-role permissions, and expose `custom_role_id` plus nested `custom_role` in account-user serializers. | +| Authorization semantics | CustomRole admin screens are administrator/super_admin only. Custom-role agents should be authorized by the six Chatwoot permission keys, including the conversation manage/unassigned/participating hierarchy. | Go policy code maps local dimensions and levels; custom-role load checks currently depend on `role == custom_role`. | Load custom roles by `custom_role_id`, translate permission arrays into policy checks, add conversation-scope tests for manage/unassigned/participating, and preserve Chatwoot-style denial payload/status. | +| Delete nullification | `CustomRole has_many :account_users, dependent: :nullify`; deleting a role clears member `custom_role_id` without deleting users. | Go delete currently soft-deletes the role and role cleanup is split across repository/RBAC paths. | On delete, account-scope the role, clear related `account_users.custom_role_id`, keep role as `agent` for legacy rows, and cover reload assertions. | +| Tests and docs | The reused frontend reads raw `response.data` from `customRole.js` and role labels from `permissionsHelper.js`. | Current tests are not enough to prove frontend compatibility. | Add handler/service/policy tests for raw list/create/update/delete, invalid permissions, admin/non-admin access, `Role=agent + CustomRoleID` permission resolution, and delete nullification. Update this tracker and commit with verification. | + +B10.3 exit commands: + +```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 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 ./... +git diff --check +``` + +B10.4 InboxLimit landing contract: + +| Area | Chatwoot reference contract | Current Go gap to close | Required landing work | +| --- | --- | --- | --- | +| Limit source of truth | Enterprise inbox/account limits decide whether new inbox/channel creation is allowed. Capacity-policy inbox limits are separate assignment-capacity data. | Go has AgentCapacityPolicy/InboxCapacityLimit parity, but remaining account-limit create-path behavior is still under review. | Re-audit `reference/chatwoot` enterprise account/inbox limit code and identify the exact plan/limit model used by create flows before implementation. | +| Generic inbox create | Frontend generic inbox create must fail before persistence when the account is over limit, with a frontend-readable error shape. | Current create paths may rely on capacity-policy limits or skip account-limit checks. | Add a shared account-limit guard before generic inbox persistence and prove no inbox/channel rows are created on failure. | +| Dedicated channel create | Email, Twilio, LINE, WhatsApp, API, WebWidget, and similar dedicated channel creates must use the same guard. | Dedicated channel routes were aligned for payload shape but not fully audited for account limit enforcement. | Call the guard in dedicated channel handlers/services and preserve raw Chatwoot-compatible success payloads. | +| Tests and docs | Under-limit and over-limit paths must be covered for at least generic inbox and one dedicated channel path. | No focused B10.4 tests yet. | Add create-path tests, record exact reference files, update this tracker, and run full tests before commit. | + +B10.4 exit commands: + +```bash +env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'Inbox|Channel|Capacity|Limit' -count=1 +env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/service -run 'Inbox|Channel|Capacity|Limit' -count=1 +env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./... +git diff --check +``` + B11 Captain/Copilot breakdown: | Step | Implementation target | Reference source | Required tests | Status | @@ -681,6 +723,25 @@ B11 Captain/Copilot breakdown: | B11.2 | Implement document sync/indexing gates for Meilisearch or the chosen embedding/search backend without blocking the frontend when LLM config is absent. | Captain document and embedding services. | Tests cover disabled state, failed sync observability, and successful fake backend indexing. | Todo | | B11.3 | Align Copilot thread/message/task APIs, tool calls, preferences, and streaming fallback. | Copilot controllers/services/frontend clients. | Handler tests cover thread/message/task lifecycle, tool-call persistence, disabled-state payloads, and non-streaming fallback. | Todo | +B11 landing rules: + +| Area | Landing requirement | Done signal | +| --- | --- | --- | +| Captain assistant resources | Audit the current `reference/chatwoot` Captain route/controller/frontend client set before code changes, then implement account-scoped CRUD and nested assistant resources with raw frontend-compatible payloads. | Handler tests cover list/show/create/update/delete, inbox binding, response/scenario/document/custom-tool paths, and disabled-state responses. | +| Captain document sync | External embedding/LLM work must sit behind fakeable interfaces and config gates; missing provider config must not break the reused frontend. | Tests cover disabled config, fake successful sync, failure metadata, and no unhandled external call in default test mode. | +| Copilot persistence | Threads, messages, tasks, preferences, playground state, and tool-call records must persist enough data for frontend reloads. | Tests cover create/list/show/update flows, account/user scoping, tool-call serialization, and task lifecycle. | +| Streaming fallback | If Chatwoot streams a response but GoChat cannot yet stream safely, return a documented frontend-compatible non-streaming or disabled state rather than a placeholder success. | Tests prove the frontend API path receives a deterministic payload/status. | +| Deferred external depth | Model/provider-specific LLM behavior may be feature-gated, but every gate must be visible in this tracker and covered by tests. | B11 stays `Review`, not `Done`, while any external-provider depth remains deferred. | + +B11 exit commands: + +```bash +env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'Captain|Copilot' -count=1 +env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/service -run 'Captain|Copilot' -count=1 +env GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./... +git diff --check +``` + B12 reused frontend verification breakdown: | Step | Implementation target | Reference source | Required tests | Status | @@ -689,6 +750,16 @@ B12 reused frontend verification breakdown: | B12.2 | Cover login, current user, inbox list, conversation list/detail, message send, contact/company view, and widget init/message. | Dashboard/widget frontend routes and API clients. | Smoke output records pass/fail and links failed API calls to route/serializer tasks. | Todo | | B12.3 | Add enterprise smoke coverage as B8-B11 land: SLA reports, CSAT public/account reports, automation/macros, audit/custom roles, Captain/Copilot. | Enterprise frontend screens and clients. | Smoke output keeps enterprise failures as named follow-up tasks, not hidden browser-only debt. | Todo | +B12 smoke harness contract: + +| Area | Landing requirement | Output artifact | +| --- | --- | --- | +| Boot command | Provide one documented command or script that starts GoChat in test/dev mode and starts the reused `reference/chatwoot` frontend pointed at GoChat without frontend adapters. | Command recorded in this tracker and, if scripted, checked into the repo. | +| Seed data | Create or document deterministic seed data for admin login, account, inbox, contact, conversation, CSAT, SLA, macro, automation, audit, and custom-role screens. | Seed command or fixture reference in `docs/parity/`. | +| Core smoke paths | Cover login/current-user, inbox list/settings, conversation list/detail/message send, contact/company views, widget config/message, and public CSAT. | `docs/parity/frontend_smoke_report.md` with pass/fail status and failed API calls. | +| Enterprise smoke paths | Cover SLA reports, CSAT reports/download, automation rules, macros, audit logs, custom roles, capacity settings, Captain, and Copilot as their slices land. | Same smoke report links each failure to the owning B-slice. | +| Exit rule | A failing smoke does not block code commits if the failure is named, scoped, and tracked; hidden failures block moving B12 out of `Doing`. | B12 moves to `Review` only with a repeatable command and checked report. | + Hermes plan material now mapped: - `.hermes/plans/2025-05-24-global-search-meilisearch.md` maps to Phase 1/B6. The Meilisearch interface, config, documents, indexing hooks, reindex command, payload shape, and live gate are already tracked here. Remaining search work is only future payload gaps discovered by frontend smoke or route expansion. @@ -1317,3 +1388,4 @@ Verification milestone gates: - 2026-06-05: B10.1 audit list checkpoint prepared as `feat(audit): align chatwoot audit log payloads`; audit logs now return the enterprise Jbuilder top-level payload consumed by the reused settings screen, use fixed 25-row pagination, enforce administrator/super_admin access, scope through Chatwoot associated audits or local account IDs, and emit actor/request/change fields with Unix timestamps. Focused audit handler/repository/service tests, handler package tests, full `go test ./...`, and `git diff --check` passed. Next slice is B10.2 audit writer coverage, then B10.3 CustomRole permission parity. - 2026-06-05: B10.2a audit writer checkpoint prepared as `feat(audit): record enterprise mutations`; a shared `AuditService.Record` boundary now writes account-associated audit rows with actor/request metadata and JSON changes, and automation-rule, macro, custom-role, and CSAT review-note mutations call it. Focused CustomRole/AutomationRule/Macro/CsatSurvey handler tests, audit service tests, handler package tests, full `go test ./...`, and `git diff --check` passed. Next slice is B10.2b inbox/conversation/SLA/capacity writer coverage, then B10.3 CustomRole permission parity. - 2026-06-05: B10.2b operational audit checkpoint prepared as `feat(audit): cover operational mutations`; inbox create/update, conversation update/delete/assignment/status, SLA policy CRUD, AgentCapacityPolicy CRUD, nested inbox capacity limits, and capacity-policy users now call the shared audit writer. Focused SLA/capacity/inbox/conversation handler tests, audit service tests, handler package tests, full `go test ./...`, and `git diff --check` passed. B10.2 moves to Review; next slice is B10.3 CustomRole permission parity. +- 2026-06-05: Remaining parity tracker checkpoint prepared as `docs: land remaining parity tracker`; the document now carries executable landing contracts for B10.3 CustomRole permission arrays/account-user resolution/delete nullification, B10.4 account/inbox limit create-path enforcement, B11 Captain/Copilot persistence and feature gates, and B12 reused Chatwoot frontend smoke reporting. Documentation-only checkpoint; `git diff --check` passed.