docs: land invitation parity tracker

This commit is contained in:
2026-06-06 11:53:39 +08:00
parent 2acd93831f
commit 34fdb077be
+25 -19
View File
@@ -49,10 +49,10 @@ Hermes task landing checklist:
## Current Baseline
- Current tracking checkpoint: 2026-06-06 after this implementation checkpoint, prepared as `feat(account-users): align inviter id`.
- Latest implementation checkpoint: this checkpoint, prepared as `feat(account-users): align inviter id`.
- Latest documentation/tooling checkpoint: this checkpoint, prepared as `docs: record placeholder smoke audit`; this document is now the active follow-up plan and supersedes `.hermes/plans/*`.
- Worktree status at this implementation checkpoint: P3.2 account-user invitation column drift from Chatwoot `account_users.inviter_id`, `AgentBuilder`, `_user.json.jbuilder`, and enterprise audit metadata is implemented. GoChat now persists AccountUser invitation source through the Chatwoot `inviter_id` column/JSON name, migrates existing `invited_by` values forward, keeps agent serializers from leaking inviter fields, and preserves profile `inviter_id` output through the existing `_user` serializer. Phase 6 placeholder audit remains in Review; B12 live API/browser/enterprise smoke still needs the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack. Next active implementation slice is B12 live smoke finding, remaining P3.2 invitations drift from fresh reference evidence, or another route/controller/serializer drift opened from current `reference/chatwoot` inspection.
- Current tracking checkpoint: 2026-06-06 documentation checkpoint, prepared as `docs: land invitation parity tracker`.
- Latest implementation checkpoint: `2acd938 feat(account-users): align inviter id`.
- Latest documentation/tooling checkpoint: this checkpoint, prepared as `docs: land invitation parity tracker`; this document is the active follow-up plan and supersedes `.hermes/plans/*`.
- Worktree status at this documentation checkpoint: clean before docs edits. P3.2 account-user invitation column drift from Chatwoot `account_users.inviter_id`, `AgentBuilder`, `_user.json.jbuilder`, and enterprise audit metadata is implemented. GoChat now persists AccountUser invitation source through the Chatwoot `inviter_id` column/JSON name, migrates existing `invited_by` values forward, keeps agent serializers from leaking inviter fields, and preserves profile `inviter_id` output through the existing `_user` serializer. The next active implementation slice is P3.2a invitation and confirmation mail parity: `ProfileService.ResendConfirmation` still only logs, and invited unconfirmed users need Chatwoot-shaped confirmation/invitation delivery behavior. Phase 6 placeholder audit remains in Review; B12 live API/browser/enterprise smoke still needs the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack.
- `go test ./...` passes.
- Route dump succeeds with `TOTAL: 905` after removing the non-Chatwoot `GET /platform/api/v1/users/:id/token` route and keeping the Chatwoot `GET /platform/api/v1/users/:id/login` route.
- Route parity artifacts now exist under `docs/parity/` and are generated by `cmd/route_parity`.
@@ -78,17 +78,19 @@ Next ordered checkpoints:
| Order | Slice | Required outcome | Primary verification |
| --- | --- | --- | --- |
| 1 | Phase 2/3 audit pass | Route/controller/serializer drift found by B12 or new reference inspection is captured as named slices, not free-form TODOs. | Regenerated route parity artifacts and fixture-backed serializer tests. |
| 2 | Phase 6 placeholder burn-down | Remaining account/contact/conversation/message/inbox placeholder handlers are either real Chatwoot-compatible flows or explicitly tracked as unsupported reference gaps. | `rg` placeholder audit, route smoke, and endpoint-family tests. |
| 3 | B12 optional live smoke | Run the checked smoke harness in a full PostgreSQL/Redis/Meilisearch/Vite/Chrome environment and turn failures into named slices. | `docs/parity/frontend_smoke_report.md` pass/fail entries linked to owners. |
| 1 | P3.2a invitation/confirmation mail parity | `ProfileService.ResendConfirmation` sends or queues Chatwoot-shaped confirmation mail, including invitation wording for users with `inviter_id`; SSO/SAML/OIDC variants remain excluded. | Focused profile/agent invitation mail tests plus full `go test ./...`. |
| 2 | Phase 2/3 audit pass | Route/controller/serializer drift found by B12 or new reference inspection is captured as named slices, not free-form TODOs. | Regenerated route parity artifacts and fixture-backed serializer tests. |
| 3 | Phase 6 placeholder burn-down | Remaining account/contact/conversation/message/inbox placeholder handlers are either real Chatwoot-compatible flows or explicitly tracked as unsupported reference gaps. | `rg` placeholder audit, route smoke, and endpoint-family tests. |
| 4 | B12 optional live smoke | Run the checked smoke harness in a full PostgreSQL/Redis/Meilisearch/Vite/Chrome environment and turn failures into named slices. | `docs/parity/frontend_smoke_report.md` pass/fail entries linked to owners. |
Execution queue for the next agent turn:
| Order | Slice ID | Why now | Required commit contents |
| --- | --- | --- | --- |
| 1 | Phase 2/3 drift audit | Route parity is currently green for the tracked set, but only fresh reference/frontend inspection proves the next missing reused-frontend path. | Named drift rows with inspected reference files, fixture tests where behavior is known, regenerated route artifacts if the route set changes. |
| 2 | Phase 6 placeholder audit | `chatwootParityStub` remains only as webhook nil-handler fallback, but every audit result must stay recorded so no frontend-critical stub becomes ownerless. | `rg` audit result, either a burn-down implementation or explicit non-frontend fallback classification, focused tests if code changes. |
| 3 | B12 live smoke | The harness is checked in; live pass/fail still needs the full PostgreSQL/Redis/Meilisearch/Vite/Chrome stack. | Updated smoke report with command, environment, failures, and linked owner rows. |
| 1 | P3.2a invitation/confirmation mail parity | Fresh reference audit found the next concrete reused-frontend/account-user gap: confirmation resend is a TODO-only log, while Chatwoot sends invitation-style confirmation mail for invited unconfirmed users. | Mail delivery boundary, profile resend behavior, focused tests, tracker update, and no route artifacts unless route wiring changes. |
| 2 | Phase 2/3 drift audit | Route parity is currently green for the tracked set, but only fresh reference/frontend inspection proves the next missing reused-frontend path. | Named drift rows with inspected reference files, fixture tests where behavior is known, regenerated route artifacts if the route set changes. |
| 3 | Phase 6 placeholder audit | `chatwootParityStub` remains only as webhook nil-handler fallback, but every audit result must stay recorded so no frontend-critical stub becomes ownerless. | `rg` audit result, either a burn-down implementation or explicit non-frontend fallback classification, focused tests if code changes. |
| 4 | B12 live smoke | The harness is checked in; live pass/fail still needs the full PostgreSQL/Redis/Meilisearch/Vite/Chrome stack. | Updated smoke report with command, environment, failures, and linked owner rows. |
Slice lifecycle:
@@ -138,15 +140,16 @@ 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 362-route critical set; dashboard `/app` shell routes from `routes.rb:19-20`, `.well-known` app association and custom-domain challenge routes from `routes.rb:657-660`, Twilio callback routes from `routes.rb:639-640`, enterprise Twilio voice routes from `routes.rb:643-646`, root Linear/Shopify/Notion OAuth callback routes from `routes.rb:630/634/654`, root Twitter/Google/Microsoft/Instagram/TikTok callback routes from `routes.rb:626/649-652`, assignment policy routes from `routes.rb:306-313`, help-center portal/category/article routes from `routes.rb:385-404`, public help-center portal/sitemap/article/category/search/article-detail routes from `routes.rb:590-601`, 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, assignment policy CRUD and inbox binding payloads, Twilio inbound/status callbacks, enterprise Twilio voice callbacks, Linear/Shopify/Notion root integration callbacks, Shopify OAuth auth redirects, root channel OAuth callbacks, help-center portal/category/article payloads, dashboard app shell route behavior, app association JSON payloads, Cloudflare custom hostname verification, public widget popular-article lists, public help-center category list/show payloads, public portal show/default-locale payloads, public portal search payloads, public article show/markdown/tracking routes, and public sitemap XML now match the inspected Chatwoot contract. | Continue the next evidence-backed route/controller/serializer drift or Phase 6 placeholder burn-down. | 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; refreshed `docs/parity/placeholder_audit.md` shows only webhook nil-handler fallbacks still call `chatwootParityStub`; dashboard conversation transcript/custom-attribute response drift and message retry status drift are closed. | Keep in Review; reopen only if fresh `rg`, route smoke, or B12 finds a frontend-reachable placeholder/stub in account/contact/conversation/message/inbox/widget/public paths. | `rg` placeholder audit and `scripts/parity_frontend_smoke.sh --check` are recorded; 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 | 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. |
| 1 | P3.2a invitation/confirmation mail parity | Account-user inviter persistence is implemented, but `ProfileService.ResendConfirmation` still logs instead of delivering confirmation mail. Chatwoot sends invitation wording for invited unconfirmed users with blank `unconfirmed_email`; normal unconfirmed users get confirmation wording. Enterprise SAML/OIDC variants are explicitly out of scope. | Implement a fakeable mail delivery boundary and wire resend/create invitation paths to Chatwoot-shaped confirmation/invitation email payloads. | Focused profile and agent invitation tests cover confirmed no-op, normal confirmation, invited workspace invitation, inviter/account wording, and excluded SSO variants; full `go test ./...` and `git diff --check` pass. |
| 2 | Phase 2/3 drift | Tracked route parity is 0 missing for the current 362-route critical set; dashboard `/app` shell routes from `routes.rb:19-20`, `.well-known` app association and custom-domain challenge routes from `routes.rb:657-660`, Twilio callback routes from `routes.rb:639-640`, enterprise Twilio voice routes from `routes.rb:643-646`, root Linear/Shopify/Notion OAuth callback routes from `routes.rb:630/634/654`, root Twitter/Google/Microsoft/Instagram/TikTok callback routes from `routes.rb:626/649-652`, assignment policy routes from `routes.rb:306-313`, help-center portal/category/article routes from `routes.rb:385-404`, public help-center portal/sitemap/article/category/search/article-detail routes from `routes.rb:590-601`, 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, assignment policy CRUD and inbox binding payloads, Twilio inbound/status callbacks, enterprise Twilio voice callbacks, Linear/Shopify/Notion root integration callbacks, Shopify OAuth auth redirects, root channel OAuth callbacks, help-center portal/category/article payloads, dashboard app shell route behavior, app association JSON payloads, Cloudflare custom hostname verification, public widget popular-article lists, public help-center category list/show payloads, public portal show/default-locale payloads, public portal search payloads, public article show/markdown/tracking routes, and public sitemap XML now match the inspected Chatwoot contract. | Continue the next evidence-backed route/controller/serializer drift after P3.2a or from B12 findings. | Regenerate parity artifacts when routes change and add endpoint-family fixture tests. |
| 3 | Phase 6 placeholder audit | Widget/public/webhook critical placeholders are burned down; inbox WhatsApp health/register-webhook and sync-template drift are closed; refreshed `docs/parity/placeholder_audit.md` shows only webhook nil-handler fallbacks still call `chatwootParityStub`; dashboard conversation transcript/custom-attribute response drift and message retry status drift are closed. | Keep in Review; reopen only if fresh `rg`, route smoke, or B12 finds a frontend-reachable placeholder/stub in account/contact/conversation/message/inbox/widget/public paths. | `rg` placeholder audit and `scripts/parity_frontend_smoke.sh --check` are recorded; no reused-frontend blocker is ownerless. |
| 4 | 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. |
| 5 | 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. |
| 6 | 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. |
| 7 | 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. |
| 8 | 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. |
| 9 | 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. |
| 10 | 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 +157,7 @@ These rows are the executable development plan from this point forward. A checkp
| ID | Owner files | Reference files | Work to land | Exit gate |
| --- | --- | --- | --- | --- |
| P3.2a invitation/confirmation mail parity | `internal/service/profile_service.go`, `internal/handler/api/v1/profile_handler.go`, `internal/service/agent_service.go`, `internal/repository/agent_repo.go`, existing fakeable mail delivery boundaries, profile/agent handler tests | `reference/chatwoot/app/controllers/api/v1/accounts/agents_controller.rb`, `reference/chatwoot/app/builders/agent_builder.rb`, `reference/chatwoot/app/views/devise/mailer/confirmation_instructions.html.erb`, `reference/chatwoot/spec/mailers/confirmation_instructions_spec.rb`, `reference/chatwoot/spec/enterprise/mailers/devise_mailer_spec.rb` for non-SAML invitation wording only | Replace TODO-only resend behavior with durable or fakeable confirmation mail delivery. For confirmed users, resend remains a no-op. For ordinary unconfirmed users, send confirmation-style mail. For invited unconfirmed users whose account membership has `inviter_id` and whose `unconfirmed_email` is blank, send workspace invitation-style confirmation mail with account and inviter context plus `Accept invitation` action text. Keep enterprise SSO/SAML/LDAP/OIDC mail variants out of scope per user decision. | Review by `feat(profile): send confirmation invitations`; focused tests cover resend no-op for confirmed users, normal confirmation mail, invited-user workspace invitation mail, agent creation/inviter context where applicable, and no network in default tests; full `go test ./...` and `git diff --check` pass. |
| P5.11a Captain document crawl/schedule | `internal/service/captain_document_service.go`, `internal/service/captain_document_worker.go`, `internal/app/bootstrap.go` | `reference/chatwoot/enterprise/app/jobs/captain/documents/crawl_job.rb`, `schedule_syncs_job.rb`, `perform_sync_job.rb`, Firecrawl/simple parser jobs | Durable schedule/crawl producers and handlers with fakeable crawl/parser boundaries. Missing provider config is a failed `crawl_disabled` state, not placeholder success. | Review by `feat(captain): queue document crawl jobs`; focused worker tests prove enqueue, replay, account scope, idempotent scheduler, and disabled/failure states. |
| P5.11b Captain response/embedding fan-out | Captain document/assistant-response services and repositories, Meilisearch/embedding boundaries | `response_builder_job.rb`, `enterprise/app/jobs/captain/llm/update_embedding_job.rb`, FAQ generator/embedding services | Queue FAQ response generation after successful document content changes, reset unedited responses, create/update assistant responses, and fan out embedding update work behind fakeable LLM gates. | Review by `feat(captain): queue response embedding jobs`; tests cover response reset/create, embedding-disabled retry, fake embedding success, account scope, and no external network in default tests. |
| P5.11c Copilot and conversation response jobs | `internal/service/copilot_service.go`, `internal/service/copilot_response_worker.go`, `internal/service/captain_conversation_service.go`, `internal/service/message_service.go`, `internal/app/bootstrap.go` | `enterprise/app/jobs/captain/copilot/response_job.rb`, `enterprise/app/jobs/captain/conversation/response_builder_job.rb`, `enterprise/app/services/captain/copilot/chat_service.rb`, `enterprise/app/services/enterprise/message_templates/hook_execution_service.rb`, `enterprise/app/models/copilot_message.rb` | Queue assistant replies after Copilot user messages and Captain pending-conversation triggers. Persist assistant messages, enqueue Captain conversation replies/handoff messages, open handoff conversations, and keep fakeable provider disabled/failure states observable through durable retry. | Review by `feat(captain): queue copilot response jobs`; focused tests cover Copilot enqueue/persist/fallback/retry, Captain conversation enqueue/handoff/retry/non-pending skip, and service/worker/app package replay. |
@@ -209,6 +213,7 @@ This ledger records the committed parity checkpoints that future slices should b
| Commit | Scope | Verification summary | Follow-up state |
| --- | --- | --- | --- |
| `docs: land invitation parity tracker` | Documentation-only checkpoint requested before continuing implementation. It records the clean `2acd938 feat(account-users): align inviter id` baseline, promotes P3.2a invitation/confirmation mail parity to the top active slice, maps the inspected Chatwoot Devise/AgentBuilder references into an executable row, and keeps SSO/SAML/LDAP/OIDC mail variants excluded. | `git diff --check`. No Go code changed and no route artifacts changed. | Start `feat(profile): send confirmation invitations`, then continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke from concrete reference/smoke evidence. |
| `feat(account-users): align inviter id` | Advances P3.2 invitation/account-user parity by matching Chatwoot `account_users.inviter_id`, `AgentBuilder#create_account_user`, `app/views/api/v1/models/_user.json.jbuilder`, and enterprise `Audit::AccountUser`. GoChat now maps `model.AccountUser.InvitedBy` to the Chatwoot `inviter_id` column and JSON name, emits account-user lifecycle payloads with `inviter_id`, adds migration `000031` to copy existing `invited_by` values forward, and keeps account agent serializers free of inviter fields. | `go test ./internal/model -run AccountUserDefaultValues -count=1`; `go test ./internal/handler/api/v1 -run 'TestAgentHandlerSuite/TestCreateAgent' -count=1`; `go test ./internal/service ./internal/repository -run 'AccountUser\|Agent' -count=1`; `go test ./cmd/migrate ./internal/app -count=1`; full `go test ./...`; `git diff --check`. No route artifacts changed. | AccountUser inviter persistence moves to Review for current reference evidence; continue remaining P3.2 invitation mail/confirmation drift, B12 live smoke, or the next evidence-backed route/controller/serializer drift. |
| `feat(profile): expose hmac identifier` | Advances P3.1 profile `_user` serializer parity by matching Chatwoot `app/views/api/v1/models/_user.json.jbuilder`, `UserAttributeHelpers#hmac_identifier`, `spec/models/user_spec.rb`, and reused frontend `scriptHelpers.js`. GoChat profile responses now omit `hmac_identifier` when `CHATWOOT_INBOX_HMAC_KEY` is not configured and include the SHA-256 HMAC of the user email keyed by that installation config when present. | `go test ./internal/handler/api/v1 -run 'ProfileHandlerSuite/TestGet' -count=1`; `go test ./internal/service -run Profile -count=1`; full `go test ./...`; `git diff --check`. No route artifacts changed. | Profile `_user` HMAC field moves to Review for current reference evidence; continue remaining P3.2 invitations drift, B12 live smoke, or the next evidence-backed route/controller/serializer drift. |
| `feat(platform): align user payloads` | Advances P3.2 platform user parity by matching Chatwoot `Platform::Api::V1::UsersController`, `app/views/platform/api/v1/models/_user.json.jbuilder`, `users/token.json.jbuilder`, and platform routes. GoChat now returns raw user/token/login payloads instead of local envelopes, creates or reuses users by email with confirmed active status, idempotently grants platform-app permission, generates/reuses personal access tokens, merges `custom_attributes` on update, returns empty `200 OK` deletes, registers `GET /platform/api/v1/users/:id/login`, and removes the non-reference `GET /platform/api/v1/users/:id/token` route from the dump. | `go test ./internal/handler/api/v1 -run PlatformUser -count=1`; `go test ./internal/service -run PlatformUser -count=1`; `go test ./internal/router -run RegisterRoutes -count=1`; `go test ./cmd/route_parity -count=1`; `go run ./cmd/dump_routes > docs/parity/gochat_routes.txt`; `go run ./cmd/route_parity`; full `go test ./...`; `git diff --check`. Route dump is `TOTAL: 905`; tracked route parity remains `353 exact, 0 method-compatible, 9 parameter-compatible, 0 missing out of 362`. | Platform users move to Review for current reference evidence; continue remaining P3.2 invitations drift, B12 live smoke, or the next evidence-backed route/controller/serializer drift. |
@@ -2373,3 +2378,4 @@ Verification milestone gates:
- 2026-06-06: Assignment policy payload checkpoint prepared as `feat(assignment-policies): align chatwoot payloads`; audited Chatwoot account assignment policy controllers, nested assignment-policy inbox controllers, inbox assignment policy controllers, Jbuilder views, reused dashboard assignment policy API/store, and routes `306-313`. GoChat now returns raw Chatwoot assignment policy arrays/objects, accepts raw and nested request bodies, persists Chatwoot policy fields, exposes assigned inbox counts, replaces inbox policy associations, lists policy inboxes as `{ inboxes: [...] }`, and returns empty `200 OK` deletes. Focused AssignmentPolicy tests, service/repository/router/app/migrate/route-parity packages, escalated full `go test ./...`, route dump `TOTAL: 906`, route parity `353 exact, 0 method-compatible, 9 parameter-compatible, 0 missing out of 362`, and `git diff --check` passed; continue Phase 6 placeholder audit, B12 live smoke, or the next evidence-backed drift.
- 2026-06-06: Placeholder/smoke audit checkpoint prepared as `docs: record placeholder smoke audit`; `docs/parity/placeholder_audit.md` now records the `chatwootParityStub` audit and classifies all remaining call sites as public webhook nil-handler guards, with no reused dashboard account/contact/conversation/message/inbox/widget/public critical-path stubs. `scripts/parity_frontend_smoke.sh --check` passed and refreshed `docs/parity/frontend_smoke_report.md`; live API/browser/enterprise smoke remains pending on the full external stack. Continue B12 live smoke when available or the next evidence-backed P2/P3 drift.
- 2026-06-06: P3.2 agent serializer-field checkpoint prepared as `feat(agents): align serializer fields`; audited Chatwoot `AgentsController` Jbuilder views and `app/views/api/v1/models/_agent.json.jbuilder`. Account agent list/create/show/update responses now remove local `invited_by` and `account_user_id` fields and keep only Chatwoot `_agent` fields plus enterprise `custom_role_id`, preserving account-user role, availability, auto-offline, and custom-role behavior behind the serializer. Focused agent handler/service/repository/router tests, escalated full `go test ./...`, and `git diff --check` passed; continue remaining P3.2 account users/invitations drift or B12 live smoke.
- 2026-06-06: Documentation checkpoint prepared as `docs: land invitation parity tracker`; worktree was clean at `2acd938 feat(account-users): align inviter id`, and the active plan now makes P3.2a invitation/confirmation mail parity the first executable slice. The row records Chatwoot AgentBuilder/Devise confirmation references, current Go owner files, normal confirmation vs invited workspace invitation behavior, excluded SSO/SAML/LDAP/OIDC mail variants, and focused exit gates. Verification for this docs-only checkpoint: `git diff --check`; next slice is `feat(profile): send confirmation invitations`.