Files
gochat/docs/parity/contract-fixture-coverage.md
rogee 0dabb8cfa5 docs: 整理文档目录结构 — 清理过时文档、归集功能子目录、统一命名规范
清理:
- 删除 34 份过时文档(gap reports/QA临时报告/验收报告/阶段性文档)
- 删除 docs/.hermes/skills 第三方 skills 副本(16 文件)
- 删除 skills-lock.json

目录归集:
- 根目录仅保留 README.md 索引
- product/ — 产品与架构设计(PRD + ARCHITECTURE + P2设计文档 + AI/企业路线图)
- tracking/ — Chatwoot parity 开发跟踪
- requirements/ — M01-M12 模块需求
- plans/ — 历史实现计划
- parity/ — 路由 parity 与前端契约
- qa/ — QA 报告与测试计划
- ops/ — 运维部署

命名规范:
- 全小写 kebab-case,禁止全大写文件名
- product/tracking/ops 用 NN- 序号前缀
- requirements 用 MNN- 两位零填充模块号
- plans/qa 用 YYYY-MM-DD- 日期前缀
- requirements M1-M9 零填充为 M01-M09(修复字典序)

同步更新:
- backend/cmd/route_parity/main.go 路径默认值
- backend/scripts/parity_frontend_smoke.sh 报告路径
- 所有 docs 内部交叉引用
- .gitignore 排除编译产物 (backend/gochat, backend/route_parity)
- 新增迁移 000052/000053
- 前端 WS 相关修改
2026-07-09 14:53:27 +08:00

44 KiB

Contract Fixture Coverage

Updated: 2026-06-13
Purpose: track P0/P1 Chatwoot/Woochat frontend contract evidence while aligning GoChat business-service behavior.

Summary

This file records current focused tests that act as contract fixtures for frontend-direct-connect behavior. A row is Covered only when the test asserts response shape, route behavior, or side effects used by the reused Chatwoot/Woochat frontend. A row remains Needs evidence when only broad route existence or implementation presence is known. Current inventory backlog is 0 rows after the latest dashboard, CSAT, and widget literal closure.

P0 / P1 Coverage Matrix

Owner Area Frontend Contract Source GoChat Evidence Current Status Next Evidence Needed
Dashboard literal APIs dashboard/api/specs/labels.spec.js, macros.spec.js, notifications.spec.js, reports.spec.js, search.spec.js, slaReports.spec.js label/macro/notification/analytics/search/SLA focused handler fixtures listed in docs/parity/frontend-contract-inventory.md Fixture covered for labels, macros, notifications, APIV2 reports, search, and applied-SLA literal frontend paths Keep as drift guard; add dedicated fixtures only if Woochat introduces new dashboard API literals.
Widget and survey literals widget/api/*, survey/api/*, dashboard/api/teams.js, summaryReports.js, userNotificationSettings.js, webhooks.js, yearInReview.js widget handler, public CSAT, team, summary-report, notification-setting, webhook, and year-in-review focused fixtures listed in docs/parity/frontend-contract-inventory.md Fixture covered for all remaining frontend inventory rows; inventory has 0 Mapped; needs fixture/smoke evidence rows Keep full regression, route parity, and live browser smoke as release gates before declaring product-level completion.
Auth/Profile/Account dashboard/api/endPoints.js, dashboard/api/account.js, dashboard/api/mfa.js, CacheEnabledApiClient.js API/enterprise smoke sign-in, validate-token, profile; browser login + dashboard token validation; internal/handler/api/v1/auth_handler_test.go::TestChatwootAuthSignInReturnsDeviseHeadersAndUserPayload; internal/handler/api/v1/auth_handler_test.go::TestChatwootAuthValidateTokenReturnsPayloadData; internal/handler/api/v1/profile_handler_test.go::TestGet_Success; internal/handler/api/v1/profile_handler_test.go::TestSetAvailability_ReturnsChatwootUserSerializer; internal/handler/api/v1/profile_handler_test.go::TestSetAutoOffline_ReturnsChatwootUserSerializer; internal/handler/api/v1/profile_handler_test.go::TestSetActiveAccount_UpdatesMembershipActiveAt; internal/handler/api/v1/mfa_handler_test.go::TestProfileMFA_StatusUsesChatwootRawPayload; internal/handler/api/v1/mfa_handler_test.go::TestProfileMFA_EnableVerifyBackupAndDisableUseFrontendPayloads; internal/handler/api/v1/account_handler_test.go::TestCacheKeys_Success; internal/repository/account_repo_test.go::TestAccountUserRepo_UpdateActiveAt_SetsCurrentTimestamp; auth/CORS token-header tests Fixture covered for auth/profile bootstrap, availability, auto-offline, active account, MFA payloads, and account cache keys Keep as drift guard; broaden only if Woochat adds new auth/account API calls.
SSO/Identity dashboard/api/samlSettings.js internal/handler/api/v1/account_saml_settings_handler_test.go::TestAccountSamlSettingsHandlerTestSuite/TestChatwootFrontendCollectionCRUDPayloads; RegisterAccountSamlSettingsRoutes Fixture covered for Woochat SAML settings collection GET/POST/PUT/DELETE, { saml_settings: ... } create/update wrapper, raw response.data payload, sso_url/certificate aliases, fingerprint/id fields, delete/not-found behavior, and legacy id-route compatibility Keep as drift guard; end-to-end SSO login, LDAP, and OIDC remain deployment/feature-gated outside this settings API contract.
Inbox/Agents/Assignment dashboard/api/inboxes.js, agents.js, teams.js, assignmentPolicies.js, agentCapacityPolicies.js, assignableAgents.js API/enterprise smoke inbox list and agent-capacity list/users; internal/handler/api/v1/inbox_handler_parity_test.go::TestInboxHandler_ChatwootSerializerParity; internal/handler/api/v1/inbox_handler_parity_test.go::TestInboxHandler_HealthReturnsWhatsAppCloudRawPayload; internal/handler/api/v1/inbox_handler_parity_test.go::TestInboxHandler_HealthReturnsProviderFailureState; internal/handler/api/v1/inbox_member_handler_test.go::TestAccountScopedInboxMembers_ChatwootPayloadAndDiffUpdate; internal/handler/api/v1/assignment_policy_handler_test.go::TestInboxAssignmentPolicy_ChatwootRoutes; internal/handler/api/v1/agent_capacity_handler_test.go::TestChatwootPolicyInboxLimitAndUserFlow; internal/handler/api/v1/agent_capacity_handler_test.go::TestChatwootPolicyInboxLimitAndUserValidationErrors; internal/handler/api/v1/facebook_callbacks_handler_test.go::TestFacebookCallbacks_RegisterFacebookPage; internal/handler/api/v1/tiktok_channel_handler_test.go::TestTikTokChannel_Create_ChatwootSetupPayloadAndConfig; LINE/Twilio setup config assertions in internal/handler/api/v1/line_channel_handler_test.go and internal/handler/api/v1/twilio_channel_handler_test.go; root OAuth callback inbox config assertions in internal/router/router_test.go::TestChannelCallbacksCreateInboxesAndRedirect; assignable-agent route tests Fixture covered for inbox list/detail/channel settings, members, health, provider failure state, Facebook callback-created inbox/channel config, root OAuth-created Instagram/TikTok/Twitter inbox config, TikTok/LINE/Twilio setup-created inbox/channel config, assignment-policy inbox override, agent-capacity user create/list/delete, inbox-limit create/update/delete, inbox avatar/campaigns/sync-template literal runtime paths, account create literal path, account-scoped agent bulk-create runtime path, and validation/not-found envelopes on Chatwoot literal nested paths Keep as drift guard; add new provider callback fixtures only when Woochat adds channel setup UI calls or provider payloads change.
Conversation/Message dashboard/api/conversations.js, inbox/message.js, inbox/conversation.js, store modules API/enterprise smoke conversation list, message list, and message create; internal/handler/api/v1/conversation_handler_crud_test.go::TestList_Success; internal/handler/api/v1/message_handler_test.go::TestCreate_ChatwootFrontendPayloadDefaultsOutgoing; internal/handler/api/v1/message_handler_test.go::TestCreate_MultipartAttachmentPersistsAndSerializes; internal/handler/api/v1/message_handler_test.go::TestDelete_Success; internal/handler/api/v1/message_handler_test.go::TestRetry_Success; internal/handler/api/v1/conversation_handler_test.go::TestUnread_DisplayIDRouteSetsLastSeenBeforeIncoming; internal/handler/api/v1/conversation_handler_test.go::TestUpdateLastSeen_DisplayIDRouteMarksNotificationRead; internal/service/message_service_test.go::TestMessageService_Update; internal/service/message_service_test.go::TestMessageService_Delete; internal/service/message_service_test.go::TestMessageService_Retry; internal/service/conversation_service_test.go::TestConversationService_MutationEventsCarryChatwootChangeData; internal/service/conversation_service_test.go::TestConversationService_ToggleTypingDispatchesChatwootPayload; internal/handler/api/v1/draft_message_handler_test.go::Test_CollectionDrafts_UseDisplayIDRoute; internal/handler/api/v1/conversation_participant_handler_test.go::Test_DisplayIDRouteEndToEnd; internal/handler/api/v1/conversation_serializer_test.go serializer fixtures; internal/ws/event_publisher_test.go::TestEventPublisher_MessageCreatedChatwootPayloadShape; internal/ws/event_publisher_test.go::TestEventPublisher_MessageUpdatedChatwootPayloadShape; internal/ws/event_publisher_test.go::TestEventPublisher_ConversationMutationChatwootPayloadShape; internal/ws/event_publisher_test.go::TestEventPublisher_TypingChatwootPayloadShape; internal/ws/event_publisher_test.go::TestEventPublisher_PresenceUpdateChatwootPayloadShape; internal/ws/presence_test.go::TestPresenceTracker_BroadcastsChatwootPresenceUpdatePayload; internal/ws/presence_test.go::TestCleanupExpired_BroadcastsChatwootOfflinePayloadAndClearsStatus Fixture covered for list envelope, meta sender, labels, attributes, last messages, message create, sender, content attributes, attachments, display conversation IDs, message update external-error dispatch, delete tombstones/attachment cleanup, retry status reset/external-error cleanup, unread transition last-seen rollback, update-last-seen notification read side effect, draft show/create/list display-ID routes, participants fetch/update/remove display-ID routes, conversation status/priority/labels/assignment event change data, typing on/off event data, Chatwoot presence.update users/contacts maps, heartbeat refresh, and expiry offline broadcasts, and message.created/message.updated/conversation.updated/conversation.typing_on realtime wire shapes Keep as drift guard; broaden only if Woochat adds new conversation/message realtime calls.
CRM dashboard/api/contacts.js, companies.js, contactNotes.js, labels modules API/enterprise smoke contact and company show; internal/handler/api/v1/crm_frontend_smoke_test.go::TestChatwootFrontendCRMSmoke; internal/handler/api/v1/contact_handler_crud_test.go::TestChatwootFrontendContactMergeImportExportContracts; internal/handler/api/v1/contact_handler_crud_test.go::TestChatwootFrontendContactsSpecRuntimeRoutes; internal/handler/api/v1/contact_handler_crud_test.go::TestListAttachmentsTimelineDepthMatchesChatwootFrontend; internal/handler/api/v1/contact_handler_crud_test.go::TestUpdatePublishesChatwootContactUpdatedEvent; internal/handler/api/v1/contact_handler_crud_test.go::TestDeletePublishesChatwootContactDeletedEvent; internal/handler/api/v1/contact_handler_crud_test.go::TestMergePublishesBaseUpdateAndMergeeDeleteEvents; internal/handler/api/v1/company_handler_test.go::TestUpdatePublishesChatwootCompanyUpdatedEvent; contact/company/custom-attribute tests Fixture covered for dashboard CRM list/show/search/update/labels/notes/company-contact paths, contacts literal-spec runtime paths, contact merge/import/export contracts, attachment timeline ordering/scoping/sender/media fields, and contact/company realtime update event payloads plus contact delete and merge source-side events Keep as drift guard; broaden only if Woochat adds new CRM API calls.
Widget/Public widget/api/endPoints.js, widget direct-upload components, public inbox APIs API/enterprise smoke widget config and message create; internal/handler/widget/widget_handler_test.go::TestWidgetHandler_ChatwootConfig_Success; TestWidgetHandler_ChatwootConfigPreChatFormOptionsMatchFrontendMixin; TestWidgetHandler_ChatwootConversationQueryTokenReusesSession; TestWidgetHandler_ChatwootConfigCwConversationReusesContactInbox; TestWidgetHandler_ChatwootConversationCookieReusesSession; TestWidgetHandler_ChatwootEventsAndLabels; TestWidgetHandler_ChatwootMessages_AuthTokenAndNestedPayload; TestWidgetHandler_ChatwootMessagePublishesWidgetRealtimePayload; TestWidgetHandler_ChatwootMessageDirectUploadAttachment; internal/handler/api/v1/upload_handler_test.go::TestUploadHandler_WidgetActiveStorageDirectUploadFlow; TestWidgetHandler_PublicAPIMessageDirectUploadAttachment; TestWidgetHandler_ChatwootCampaigns_Success; TestWidgetHandler_PublicAPIInboxContactConversationMessageFlow; public API contact/conversation/message tests Fixture covered for widget config/contact token bootstrap, Chatwoot preChatFormEnabled/preChatFormOptions frontend mixin shape, cw_conversation popout query and cookie session reuse, config boot contact-inbox reuse without creating a new visitor, message create/list envelopes, widget message.created pubsub-token realtime delivery, labels/events with header/query/cookie auth, ActiveStorage widget direct-upload create/complete fields, direct-upload attachment payloads, campaigns, public contact update shape, public conversation status/read flows, core public API message windows, and browser-smoke harness coverage for reused widget boot plus messages/inbox-members/campaign requests Keep as drift guard; rerun live browser smoke when widget SDK requests change.
Automation/Macros/Campaigns dashboard/api/automation.js, dashboard/api/macros.js, dashboard/api/campaigns.js, dashboard/api/cannedResponse.js, dashboard/api/bulkActions.js API/enterprise smoke automation and macros; internal/handler/api/v1/automation_rule_handler_test.go::TestChatwootFrontendCRUDCloneTogglePayloadsAndValidation; internal/handler/api/v1/campaign_handler_test.go::TestChatwootFrontendPayloadsAndLifecycleUseDisplayID; internal/handler/api/v1/campaign_handler_test.go::TestStartCreatesCampaignConversationsAndMessages; internal/handler/api/v1/macro_handler_test.go::TestExecute_UsesConversationDisplayIDsAndMutatesConversation; internal/handler/api/v1/macro_handler_test.go::TestExecute_ChatwootFrontendAwaitsEmptyOKAndSupportsSingleConversationID; canned-response CRUD/search fixtures in internal/handler/api/v1/canned_response_handler_test.go; automation-rule, bot-rule, campaign, macro, and bulk-action suites; internal/handler/api/v1/bulk_action_handler_test.go::TestBulkActionHandler_ConversationEnqueuesChatwootPayload; internal/service/conversation_maintenance_worker_test.go::TestConversationMaintenanceJobsConversationBulkActionQueuesSearchIndex; internal/service/conversation_maintenance_worker_test.go::TestConversationMaintenanceJobsContactBulkActionQueuesSearchIndexAndCompletes; internal/service/conversation_maintenance_worker_test.go::TestConversationMaintenanceJobsTriggerScheduledItemsFanOut; internal/service/conversation_maintenance_worker_test.go::TestConversationMaintenanceJobsProcessCampaignSnoozeAndResolution; internal/service/conversation_maintenance_worker_test.go::TestConversationMaintenanceJobsCampaignTriggerDispatchesEvents Fixture covered for automation-rule create/list/update/clone/toggle/delete payloads, validation error envelope, Chatwoot condition/action param normalization, campaign nested { campaign: ... } create/update payloads, Chatwoot display-id route semantics, campaign start/stop response envelopes, campaign trigger conversation/message side effects, scheduled campaign trigger job dispatch payload/idempotency/completion, campaign trigger conversation/message/opened/outgoing event dispatch, dashboard audience/trigger/template JSON shapes, frontend audience-array trigger tolerance, macro execute side effects against display/single conversation IDs, empty-200 execute response awaited by the frontend, validation envelope for missing body, canned-response raw CRUD/search payloads, and bulk-action enqueue/progress completion plus conversation/contact search-index side effects Keep as drift guard; re-open only if Woochat changes macro execution to consume a non-empty response body.
Help Center dashboard/api/helpCenter/*, widget/api/endPoints.js help-center article paths internal/handler/api/v1/portal_handler_test.go::TestPublicRedirectDefaultLocale; TestPublicRedirectDefaultLocaleFallsBackToPortalLocale; TestPublicSitemap_ReturnsPublishedArticleURLs; internal/handler/api/v1/category_handler_test.go::TestPublicList_ReturnsChatwootCategoryPayloads; TestPublicGet_FiltersBySlugAndLocale; internal/handler/api/v1/article_handler_test.go::TestDashboardArticleCRUD_ChatwootFrontendPayloadsAndRoutes; internal/handler/api/v1/article_handler_test.go::TestPublicList_WidgetPopularArticles; TestPublicList_CategoryRouteFiltersArticlesBySlugAndLocale; TestPublicMarkdown_ReturnsOnlyPublishedMarkdown; TestPublicTrackingPixel_IncrementsPublishedArticleViews Fixture covered for dashboard article create/list/show/edit/update/delete payload shape and slug-portal routes, locale redirect/default fallback, sitemap URL/content type excluding drafts, category JSON/list by slug+locale, article JSON list sorting/meta/category filters, Chatwoot suffix-compatible .md raw markdown, and .png 1x1 tracking pixel side effects Keep as drift guard; Article spec bare /api/v1/portals/... URLs are frontend unit-test artifacts; runtime account-scoped article paths are fixture-covered. add browser smoke only if Woochat portal UI changes.
CSAT/Survey dashboard/api/csatReports.js, survey/api/*, public CSAT routes API/enterprise smoke public CSAT show, CSAT list/metrics/download; internal/handler/api/v1/csat_survey_handler_test.go::TestCSATFrontendContractShapes; internal/handler/api/v1/csat_survey_handler_test.go::TestMetrics_DashboardValueDriftFiltersMatchChatwootFrontend; internal/handler/api/v1/csat_survey_handler_test.go::TestUpdate_ChatwootReviewNotesAuditAndSerializerParity; internal/handler/api/v1/csat_survey_handler_test.go::TestPublicCsatUpdate_ChatwootPutPersistsShowPayload; internal/handler/api/v1/csat_survey_handler_test.go::TestPublicCsatUpdate_LockedAfter14Days; CSAT survey handler/service tests Fixture covered for dashboard list/metrics/download, dashboard metric value-drift filters, Chatwoot account/date-only total_sent_messages_count, review-note audit/serializer behavior, public PUT show/update persistence, and locked-after-14-days non-mutation behavior Keep status-transition/job-send fixtures as follow-up drift guards.
Search/Indexing dashboard/api/search.js, conversation search store, dashboard/api/companies.js, help-center article search calls Live enterprise-browser smoke on 2026-06-13 reran Meilisearch reindex/search and captured seeded /search/conversations, /search/messages, /search/contacts, /companies/search, and /search/articles Chatwoot payloads as .tmp/frontend-smoke-live/search_conversations.json, search_messages.json, search_contacts.json, search_companies.json, search_articles.json, plus search_reindex.log; smoke seed creates a help-center portal/category/article; search handler/indexer tests; company/article hooks assert updated objects reach indexing; Meilisearch request/filter contract tests; release-mode fallback rejection config test Fixture and live Meilisearch gate covered for the current reused frontend search paths Keep as release drift guard; rerun live Meilisearch smoke/reindex after search schema or searchable mutation changes.
Reports/Audit dashboard/api/reports.js, summaryReports.js, liveReports.js, auditLogs.js Enterprise smoke audit logs; internal/handler/api/v1/analytics_handler_test.go::TestAPIV2Reports_ChatwootPayloadShapes; internal/handler/api/v1/analytics_handler_test.go::TestAPIV2Reports_AllFrontendEndpointShapes; internal/handler/api/v1/analytics_handler_test.go::TestAPIV2Reports_TimeseriesTimezoneValueParity; internal/handler/api/v1/analytics_handler_test.go::TestAPIV2Reports_CSVDownloadEntrypointsMatchChatwootFrontend; internal/handler/api/v1/analytics_handler_test.go::TestAPIV2Reports_OutgoingMessagesCountValueParity; internal/handler/api/v1/live_report_handler_test.go::TestAPIV2LiveReports_ChatwootFrontendPayloadShapes; internal/handler/api/v1/live_report_handler_test.go::TestAPIV2LiveReports_StoreRefreshSequenceMatchesChatwootFrontend; internal/router/router_test.go::TestAPIV2LiveReportsRouterAuthAndAccountScope; internal/middleware/account_scope_test.go::TestAccountScope_RouteAccountMustMatchContext; internal/handler/api/v1/audit_handler_test.go::TestList_ChatwootPayloadFiltersAndSerializer; analytics/report/audit/live-report service and handler tests Fixture covered for audit list payloads, fixed Chatwoot page size, pagination meta, descending page order, API v2 reports.js index/summary/conversations/agents/inboxes/labels/teams/conversations_summary/conversation_traffic/bot_metrics/bot_summary endpoint shapes, frontend CSV download entrypoints, timezone-offset day grouping value parity, outgoing message count value parity, live-report frontend payloads, live-report store-refresh sequence, and live-report auth/account-scope enforcement Keep as drift guard; broaden only if Woochat adds new audit filters or report pagination calls.
Notifications/Realtime/Cache dashboard/store/modules/notifications, notificationSubscription.js, user notification settings, helper/actionCable.js internal/handler/api/v1/notification_handler_test.go list/read/unread/delete/destroy-all fixtures; internal/handler/api/v1/notification_handler_test.go::TestNotificationHandler_MutationsPublishChatwootRealtimePayload; internal/handler/api/v1/notification_subscription_handler_test.go::TestNotificationSubscriptionCreateAcceptsPushHelperPayload; internal/handler/api/v1/notification_subscription_handler_test.go::TestNotificationSubscriptionCreateAcceptsAccountScopedPushHelperPayload; internal/handler/api/v1/notification_setting_handler_test.go::TestNotificationSettingHandlerSuite/TestUpdate_ReturnsRawChatwootPayload; internal/ws/event_publisher_test.go::TestEventPublisher_NotificationChatwootPayloadShape; internal/ws/event_publisher_test.go::TestEventPublisher_AccountCacheInvalidatedChatwootPayloadShape; internal/ws/event_publisher_test.go::TestEventPublisher_WidgetEvent_PubsubTokenRoomDelivery; internal/handler/ws/subscriber.go topic bridge for notification updated/deleted and account cache invalidation Fixture covered for notification list/read-state/delete REST behavior, source-side read/unread/snooze/delete realtime publication, PushHelper browser subscription create/destroy including account-scoped routes, user notification settings show/update selected flag persistence, notification.created/notification.updated/notification.deleted realtime payloads, account.cache_invalidated.cache_keys label/inbox/team revalidation, and widget message.created delivery to the contact pubsub_token room Keep as drift guard; add browser-store smoke evidence if Woochat changes subscription/preference UI behavior.
Enterprise/Captain dashboard/api/captain/*, customRole.js, sla.js, enterprise account APIs Enterprise API and browser route-request smoke passed for SLA, CSAT, automation, macros, audit, custom roles, capacity, Captain, and Copilot; internal/handler/api/v1/enterprise_account_handler_test.go::TestEnterpriseAccountLiteralFrontendPathsUseCurrentAccountContext; internal/handler/api/v1/enterprise_account_handler_test.go::TestEnterpriseAccountBillingErrorBoundariesDoNotMutateAccount; internal/handler/api/v1/enterprise_account_handler_test.go::TestEnterpriseAccountLimits_CaptainUsageDoesNotExposeNegativeAvailability; internal/handler/api/v1/enterprise_account_handler_test.go::TestEnterpriseAccountSubscriptionPreservesExistingCustomerState; internal/handler/api/v1/custom_role_handler_test.go::TestChatwootPermissionSetCreateUpdateListShowParity; internal/handler/api/v1/captain_assistant_handler_test.go::TestCaptainAssistantHandler_PlaygroundLegacyNoLLMFallback; internal/handler/api/v1/captain_assistant_handler_test.go::TestCaptainAssistantHandler_PlaygroundV2AppendsCurrentMessageOnce; internal/handler/api/v1/captain_assistant_handler_test.go::TestCaptainAssistantHandler_PlaygroundV2ProviderErrorReturnsChatwootFallback; internal/handler/api/v1/captain_resource_parity_handler_test.go::TestCaptainDocumentHandler_ChatwootDocumentPayloadsAndSync; internal/handler/api/v1/captain_resource_parity_handler_test.go::TestCaptainAssistantResponseHandler_ChatwootResponsePayloadsAndFilters; internal/service/captain_document_service_test.go::TestCaptainDocumentService_RequestSyncQueuesDurableJob; internal/service/captain_document_service_test.go::TestCaptainDocumentService_RequestCrawlQueuesParserJobs; internal/service/captain_document_service_test.go::TestCaptainDocumentService_ResponseBuilderCreatesResponsesAndEmbeddingJobs; internal/handler/api/v1/copilot_thread_handler_test.go::TestCopilotThreadCreateProviderDisabledReturnsStableUnavailableAssistantMessage; internal/handler/api/v1/copilot_thread_handler_test.go::TestCopilotThreadCreateProviderEnabledPersistsGeneratedAssistantMessage; internal/service/copilot_response_worker_test.go::TestCopilotResponseJobForFollowupMessageUsesStoredThreadHistoryAndIdempotency; internal/handler/api/v1/sla_policy_handler_test.go::TestSlaPolicyHandler_InboxAssociationChatwootPayloadAndSideEffects; captain/custom-role/SLA/agent-capacity tests Fixture covered for enterprise browser route smoke, Chatwoot enterprise account literal-path limits/billing actions, Captain limit availability clamping, subscription existing-customer no-op side effect, and billing error no-mutation boundaries, Chatwoot custom-role permission key create/update/list/show parity, Captain document list/show/sync payload keys plus assistant_id/filter/source/search_key filters, Captain assistant-response payload keys plus assistant_id/document_id/status/search filters and Captain::Document documentable shape, Captain document sync/crawl response-builder job queue/idempotency payloads, legacy CaptainDocument cleanup, generated approved FAQ responses, and embedding job fan-out, Captain playground legacy provider-disabled fallback, V2 provider-enabled response shape/history handling, V2 provider-error Chatwoot conversation_handoff fallback, Copilot thread provider disabled/enabled message persistence, background Copilot follow-up job payload/history/idempotency, and SLA inbox association response/DB side effects Keep as drift guard; broaden only when Woochat adds new Captain/Copilot provider modes.
Integrations/Channels dashboard/api/channel/*, integrations/* provider/channel service and webhook tests; Dyte meeting/add-participant handler fixtures; Linear teams/team-entities/create/link/unlink/search/linked-issues handler fixtures using fake GraphQL; Slack create/delete/list-all-channels handler fixtures using fake HTTP; generic app/hook no-trailing-slash fixtures; WhatsApp health raw-payload and provider-failure fixtures in internal/handler/api/v1/inbox_handler_parity_test.go; Facebook page setup/provider-failure/reauthorize fixtures in internal/handler/api/v1/facebook_callbacks_handler_test.go; root OAuth callback redirect/config fixture, existing-channel upsert fixture, email OAuth provider-error fallback fixture, and Linear/Shopify/Notion provider-error fallback fixture in internal/router/router_test.go; Telegram webhook success/failure reauthorization fixture in internal/channel/provider/telegram_test.go; TikTok setup payload/config fixture in internal/handler/api/v1/tiktok_channel_handler_test.go; LINE/Twilio setup payload/config fixtures in internal/handler/api/v1/line_channel_handler_test.go and internal/handler/api/v1/twilio_channel_handler_test.go; WhatsApp delivered/read/failed-delivery, Twilio delivered/read/failed-delivery, TikTok read-receipt, LINE valid/missing/invalid signature, and TestFacebookWebhookDeliveryReceiptPersistsDeliveredStatus/TestFacebookWebhookReadReceiptPersistsReadStatusForContactConversation and TestInstagramWebhookDeliveryReceiptPersistsDeliveredStatus/TestInstagramWebhookReadReceiptPersistsReadStatusForContactConversation fixtures in internal/handler/webhook/webhook_lookup_test.go Fixture covered for current reused frontend provider/channel paths; WhatsApp signed status callback now persists delivered/read/failed message statuses, delivery status timestamps, status events, frontend-visible external_error content attributes for failures, and duplicate same-status callbacks as idempotent no-ops; Twilio delivery-status callback now normalizes callback phone numbers, persists delivered/read/failed message statuses, delivery status rows, status events, and frontend-visible external_error for failures, and treats duplicate status callbacks as idempotent no-ops without duplicate realtime events; TikTok read receipts now persist read message status, delivery status, status event, and duplicate read-receipt retries as idempotent no-ops; contact-level read receipts now also backfill per-contact delivery status rows for messages already at the target read status (TestIncomingPersisterQueuesContactMessagesStatusUpdateWithWorker); LINE webhooks now cover valid, missing-signature, and invalid-signature behavior without creating phantom messages; Facebook and Instagram delivery/read receipts now persist delivered/read message statuses, delivery status rows, status events from their Chatwoot-compatible webhook endpoints, and duplicate receipt retries as idempotent no-ops; Facebook facebook_pages.json returns Chatwoot data.page_details/user_access_token and provider failures as 422, register_facebook_page returns the raw inbox payload, and reauthorize_page updates persisted page config; root Instagram/TikTok/Twitter OAuth callbacks now persist serializer-readable inbox channel config before redirecting Woochat to inbox setup, and repeated Google/Instagram/TikTok/Twitter callbacks refresh existing channel/inbox config and redirect to settings, while Google/Microsoft token payload errors redirect to the frontend fallback without creating phantom inboxes; Linear/Shopify/Notion OAuth token payload errors redirect to stable Chatwoot frontend destinations and do not create phantom integration hooks; Telegram webhook setup success stores webhook_url, and setup failure marks reauthorization_required instead of silently exposing a working channel; TikTok setup now returns a stable raw {channel,inbox} payload and persists tiktok_business_id/access_token channel config even when provider setup is disabled; LINE and Twilio setup now assert raw inbox payloads plus persisted channel linkage/config Keep as drift guard; add signed fixtures when Woochat or provider payloads introduce new delivery states. Generic integrations.js apps/hooks, Slack, and Shopify frontend paths are covered by TestIntegrationHookHandlerSuite/TestChatwootFrontendAppsAndHooksNoTrailingSlashPayloads, Slack handler/service fixtures, and TestShopifyIntegration_Auth_ReturnsChatwootRedirectPayload.

Current Focused Commands

GOCACHE=/tmp/go-build-cache GOMODCACHE=/tmp/go-mod-cache go test ./internal/handler/api/v1 -run 'TestAgentCapacityHandlerSuite|TestArticleHandlerSuite'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestInboxHandler_ChatwootSerializerParity|TestInboxHandler_HealthReturnsWhatsAppCloudRawPayload|TestInboxHandler_HealthReturnsProviderFailureState|TestInboxMemberHandlerSuite|TestInboxHandler_SensitiveFieldsRequireAdministratorRole|TestAgentBotHandlerSuite/TestAccountChatwootPayloadsAndRoutes|TestAgentCapacityHandlerSuite/TestChatwootPolicyInboxLimitAndUserFlow|TestAgentCapacityHandlerSuite/TestChatwootPolicyInboxLimitAndUserValidationErrors|TestAssignableAgentHandlerSuite/(TestList_StandaloneResourceUsesFrontendInboxIDsQuery|TestList_ResponseStructure)|TestAssignmentPolicyHandlerTestSuite/(TestPluralAssignmentPolicies_ChatwootPayloads|TestInboxAssignmentPolicy_ChatwootRoutes)|TestAgentHandlerSuite/TestCreateAgentChatwootFrontendPayload|TestCustomAttributeDefinitionHandler_ListChatwootFrontendPayload'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'Test(FacebookCallbacks_RegisterFacebookPage|GoogleAuthorization_ReturnsChatwootPayload|MicrosoftAuthorization_ReturnsChatwootPayload|InstagramAuthorization_ReturnsChatwootPayload|TikTokChannel_Create_ChatwootSetupPayloadAndConfig|TwilioChannel_Create_Success|TwitterAuthorization_ReturnsChatwootPayload|InboxHandler_ChatwootSerializerParity|WhatsAppCallHandler_AccountRoutesMatchFrontendAPI|WhatsAppCallHandler_ActionsAndRecordingPayloads)$' -count=1 && GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/router -run 'TestChannelCallbacks(CreateInboxesAndRedirect|UpdateExistingInboxesAndRedirectToSettings|RedirectErrorsToNewInbox)$' -count=1 && GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/webhook -run 'Test(TwilioDeliveryStatusPersistsDeliveredAndReadStatuses|WhatsAppWebhookPersistsDeliveredAndReadStatuses|TikTokWebhookReadReceiptUpdatesMessageStatus|FacebookWebhookDeliveryReceiptPersistsDeliveredStatus|InstagramWebhookDeliveryReceiptPersistsDeliveredStatus)$' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/router -run 'TestTwilioVoiceRoutesServeConferenceAndPersistCallbacks$' -count=1 && GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/service -run 'TestWhatsAppAuthorization_(CreateEmbeddedSignupInbox|ReauthorizesExistingInbox)$' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/ws -run 'TestEventPublisher_MessageCreatedChatwootPayloadShape|TestEventPublisher_WSMessageFormat|TestEventPublisher_ConversationEvent_RoomDelivery|TestEventPublisher_WidgetEvent_PubsubTokenRoomDelivery'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestConversationCrudTestSuite/TestList_Success|TestMessageHandlerTestSuite/TestCreate_ChatwootFrontendPayloadDefaultsOutgoing|TestMessageHandlerTestSuite/TestList_Success|TestMessageHandlerTestSuite/TestCreate_MultipartAttachmentPersistsAndSerializes|TestConversationSerializer'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestConversationCrudTestSuite/(TestList_Success|TestUpdateLabels_Success|TestToggleStatus.*|TestToggleTyping.*|TestFilter_ChatwootPayload.*)|TestConversationHandlerTestSuite/(TestMeta_Success|TestUnreadCounts_Success|TestTranscript_Success)|TestMessageHandlerTestSuite/(TestList_Success|TestCreate_ChatwootFrontendPayloadDefaultsOutgoing|TestCreate_MultipartAttachmentPersistsAndSerializes|TestDelete_Success|TestRetry_Success|TestTranslate_Success)' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestChatwootFrontendCRMSmoke|TestContactHandlerCRUDTestSuite/(TestChatwootFrontendContactMergeImportExportContracts|TestMergePublishesBaseUpdateAndMergeeDeleteEvents|TestInitiateCall_CreatesConversationCallAndVoiceMessage)|TestCsatSurveyHandlerTestSuite/TestCSATFrontendContractShapes|TestCustomRoleHandlerSuite|TestCustomFilterHandlerSuite|TestDashboardAppHandlerSuite'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/widget -run 'TestWidgetHandler_ChatwootConfig_Success|TestWidgetHandler_ChatwootMessages_AuthTokenAndNestedPayload|TestWidgetHandler_ChatwootMessagePublishesWidgetRealtimePayload|TestWidgetHandler_ChatwootMessageDirectUploadAttachment|TestWidgetHandler_ChatwootCampaigns_Success'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestArticleHandlerSuite/(TestDashboardArticleCRUD_ChatwootFrontendPayloadsAndRoutes|TestReorder_PositionsHashScoped|TestBulkActions_FrontendRoutes|TestBulkTranslate_FrontendRouteQueuesAndReturnsConflict)|TestCategoryHandlerSuite/(TestCreate_RawFrontendPayloadAndSlugPortal|TestList_Success|TestReorder_Success)|TestPortalHandlerSuite/(TestList_ReturnsChatwootPayloadEnvelope|TestUpdate_Success|TestDelete_BySlugReturnsOK|TestSendInstructions_ChatwootPayload)' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestInboxHandler_(ChatwootSerializerParity|HealthReturnsWhatsAppCloudRawPayload|HealthReturnsProviderFailureState|ChatwootCreateUpdateRequestBinding)|TestInboxMemberHandlerSuite/TestAccountScopedInboxMembers_ChatwootPayloadAndDiffUpdate|TestInboxSyncTemplates_ChatwootQueuedResponse' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestAuditHandlerSuite/(TestList_ChatwootPayloadFiltersAndSerializer|TestList_ChatwootPaginationMetaAndDescendingOrder)|TestAutomationRuleHandlerTestSuite/TestChatwootFrontendCRUDCloneTogglePayloadsAndValidation|TestCampaignHandlerTestSuite/TestChatwootFrontendPayloadsAndLifecycleUseDisplayID|TestCampaignHandlerSuite/TestStartCreatesCampaignConversationsAndMessages|TestMacroHandlerSuite/TestExecute_UsesConversationDisplayIDsAndMutatesConversation|TestMacroHandlerSuite/TestExecute_ChatwootFrontendAwaitsEmptyOKAndSupportsSingleConversationID|TestCannedResponseHandlerSuite/(TestList_Success|TestList_SearchParamReturnsRawRankedArray|TestCreate_RawFrontendBodyReturnsRawPayload|TestUpdate_PatchRawBodyIsAccountScoped|TestDelete_ReturnsOKEmptyAndScopesAccount)|TestBulkActionHandler_(ConversationEnqueuesChatwootPayload|ContactEnqueuesChatwootPayload|InvalidTypeMatchesChatwootPayload)' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'Test(LinearIntegration_ChatwootFrontendRuntimeRoutes|SlackIntegration_ListAllChannels_NoTrailingSlash_ReturnsChannelArray|SlackIntegration_(Create|Delete)_NoTrailingSlash_Returns|DyteIntegrationHandler(CreateMeetingReturnsMessagePayload|AddParticipantReturnsAuthToken))|TestIntegrationHookHandlerSuite/TestChatwootFrontendAppsAndHooksNoTrailingSlashPayloads|TestLabelHandlerSuite/(TestListTags_Success|TestCreateTag_RawNameCompatibility|TestUpdateTag_ChatwootPayloadAndAccountScope|TestDeleteTag_ReturnsOKAndRemovesAssociations)|TestLiveReportHandlerTestSuite/(TestAPIV2LiveReports_ChatwootFrontendPayloadShapes|TestAPIV2LiveReports_StoreRefreshSequenceMatchesChatwootFrontend)|TestMacroHandlerSuite/(TestList_Empty|TestCreate_Success|TestUpdateDeleteAuthorizationAndPayload|TestExecute_ChatwootFrontendAwaitsEmptyOKAndSupportsSingleConversationID)|TestMFAHandlerSuite/TestProfileMFA_(StatusUsesChatwootRawPayload|EnableVerifyBackupAndDisableUseFrontendPayloads)|TestNotificationSubscription(CreateAcceptsPushHelperPayload|CreateAcceptsAccountScopedPushHelperPayload|CreateAcceptsRailsWrapperAndUpdatesExisting|DestroyUsesPushTokenAndReturnsEmptyOK|DestroyAccountScopedUsesPushToken)$|TestNotificationHandler_(List_ChatwootEnvelopeAndIncludes|MutationsPublishChatwootRealtimePayload)|TestNotionIntegration_Authorization_ReturnsChatwootPayload|TestUpdateOnboarding_Success|TestSearchHandler_(GlobalSearch_UsesReferenceResultTypes|SearchConversations_ChatwootPayloadShape|SearchMessages_HydratesChatwootMessagePayload|SearchArticles_HydratesPortalAndCategoryPayload)|TestSlaPolicyHandler_(List_Success|Create_Success|InboxAssociationChatwootPayloadAndSideEffects|ListAppliedSlas_ChatwootPayloadAndFilters|GetAppliedSlaMetrics_ChatwootReportShape|GetAppliedSlaDownload_Success)' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/service -run 'TestLinearIntegrationService_ChatwootFrontendPayloads$' -count=1 && GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestShopifyIntegration_Auth_ReturnsChatwootRedirectPayload$' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestCaptainAssistantHandler_|TestCaptain(DocumentHandler_ChatwootDocumentPayloadsAndSync|AssistantResponseHandler_ChatwootResponsePayloadsAndFilters|ScenarioHandler_ChatwootScenarioPayloadsAndScope|CustomToolHandler_ChatwootToolPayloadsAndScope|BulkActionHandler_ChatwootResourceActions|CustomToolHandler_ChatwootTestToolPayload)$|TestCopilotThread(CreateReturnsChatwootPayload|MessagesListAndCreateUseNestedPayloads|CreateProviderDisabledReturnsStableUnavailableAssistantMessage|CreateProviderEnabledPersistsGeneratedAssistantMessage|MessagePayloadUsesThreadPushShape|MessagePushPayloadMatchesChatwootEventData)$|TestCaptainPreferences(GetReturnsRawChatwootConfig|UpdateMergesAccountModelsAndFeatures|UpdateRejectsNonAdminAndInvalidModel)$|TestCaptainTaskHandler_(Summarize_ChatwootRawPayload|Rewrite_NoProviderRawDisabled|StreamSummarize_ChatwootDisplayID)$|TestCaptainTaskExtendedHandler_(LabelSuggestion_ChatwootPostRawPayload|FollowUp_ChatwootPostUpdatesContext)$' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/service -run 'TestConversationMaintenanceJobs(TriggerScheduledItemsFanOut|ProcessCampaignSnoozeAndResolution|CampaignTriggerDispatchesEvents|ConversationBulkActionQueuesSearchIndex|ContactBulkActionQueuesSearchIndexAndCompletes)$' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestChatwootAuth|TestProfileHandlerSuite'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestChatwootAuth(SignInReturnsDeviseHeadersAndUserPayload|ValidateTokenReturnsPayloadData|SignOutRevokesRefreshSession|ResetPasswordReturnsReferenceMessage|UpdatePasswordWithResetToken)$|TestProfileHandlerSuite/(TestGet_Success|TestUpdateAvatar_Success|TestDeleteAvatar_ReturnsChatwootUserSerializer|TestSetAvailability_ReturnsChatwootUserSerializer|TestSetAutoOffline_ReturnsChatwootUserSerializer|TestSetActiveAccount_UpdatesMembershipActiveAt|TestResetAccessToken_RegeneratesTokenInChatwootUserSerializer|TestResendConfirmation_.*)$|TestFacebookCallbacks_FacebookPagesPayload' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/api/v1 -run 'TestMFAHandlerSuite|TestAccountHandlerSuite/(TestCacheKeys_Success|TestUpdateActiveAt_Success)'
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/ws -run 'TestEventPublisher_(NotificationChatwootPayloadShape|AccountCacheInvalidatedChatwootPayloadShape|AllEventTypes)$' -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/handler/ws -count=1
GOCACHE=/tmp/gochat-gocache GOMODCACHE=/tmp/gochat-gomodcache go test ./internal/repository -run 'TestAccount(User)?Repo_UpdateActiveAt'
GOCACHE=/tmp/go-build-cache GOMODCACHE=/tmp/go-mod-cache go test ./internal/router -run TestRegisterRoutesBootsWithChatwootParityConflictGroups
GOCACHE=/tmp/go-build-cache GOMODCACHE=/tmp/go-mod-cache go test ./...

Open Gates

  • Live scripts/parity_frontend_smoke.sh --enterprise-browser-smoke passed on 2026-06-13 on a fresh Docker PostgreSQL/Redis/Meilisearch stack after migrations and seed were made repeatable; the harness captures seeded conversation/message/contact/company/article search payloads as search_conversations.json, search_messages.json, search_contacts.json, search_companies.json, and search_articles.json.
  • Live browser smoke now covers reused Chatwoot login/dashboard boot, token validation, dashboard conversations request, widget boot, widget messages/inbox-members/campaigns endpoint checks, enterprise route requests, and no frontend-visible proxied API 4xx/5xx failures; latest browser report: .tmp/frontend-smoke-live/browser-smoke-report.json.
  • Live enterprise API and enterprise browser smoke passed after migration/seed against GoChat 127.0.0.1:13000, reused Chatwoot Vite localhost:3036, PostgreSQL 15432, Redis 16379, and Meilisearch 17700; browser evidence now includes 37 checks and explicit reused-frontend requests for /api/v1/accounts/:account_id/notifications?page=1 and /api/v1/accounts/:account_id/notification_settings.
  • Auth/profile/account fixture coverage now asserts exact frontend-visible user/account keys for sign-in, validate-token, profile, availability, auto-offline, active-account side effects, MFA raw payloads, and account cache keys.
  • Inbox fixture coverage now asserts Chatwoot-style list/detail envelopes, admin-only sensitive channel fields, inbox-member payload/diff updates, and raw WhatsApp Cloud health payloads.
  • Conversation/message fixture coverage now asserts Chatwoot-style list envelopes, meta sender, labels, additional/custom attributes, last message payloads, outgoing message create defaults, sender fields, content attributes, attachments, display conversation IDs, and message.created WS/SSE payload shape.
  • Notification/cache realtime fixture coverage now asserts the Chatwoot notifications store payload shape { notification, unread_count, count } for created/updated/deleted events and the account.cache_invalidated.cache_keys label/inbox/team payload used by CacheEnabledApiClient revalidation; browser-store smoke now verifies the current notification index and profile notification-preference screens request GoChat without frontend patches.
  • Fixture comparisons outside auth/profile/account are still broad and should be split into owner-slice tests as each frontend inventory row is closed; the CRM row now has frozen dashboard payload-shape assertions for the common contact/company frontend flows, including companies and contacts literal-spec runtime paths, and the widget/public row now has focused config/popout/message/direct-upload/create-complete/campaign payload-shape guards.