Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

Channel sync: shared containers, dual-write, flag-gated dual-read, reconciler

merged#2452CedarCopilot

CedarCopilot wants to merge 0 commits into staging from feat/channel-sync-architecture

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Aug 10, 2026, 9:21 PM
  2. Merged
    Aug 10, 2026, 9:50 PM
  3. Live on prod
    Aug 10, 2026, 9:50 PM
  4. Observed 2 days
    Aug 10, 2026, 9:50 PM
  5. Pipelines steady after this deploy
    Aug 10, 2026, 9:50 PM
  6. Unobserved

    Live on prod, no production signal yet

    Aug 13, 2026, 7:36 PM

Behaviors Libra is checking

Background jobs behavior from cron/cron-task-registry.ts keeps working in prod.Inconclusivelow confidence

OTEL fallback saw 220,393 prod spans for the repo/env since deploy, but 5,334 were errors and the intent has no concrete surface to attribute them to.

prod, checked Aug 13, 2026, 5:36 PM
CRM integration behavior from db/crm-schema.ts, crm/conversations.ts, crm/dedup.ts keeps working in prod.Inconclusivelow confidence

Strict CloudWatch fallback found 56 prod failure log lines for [UpdateExternalCrmWorkflow] Driver update failed (Step updateDeal failed: HTTP 400: {\), up from 5 in the comparable baseline, but this domain-wide failure family is not tied to this intent.

prod, checked Aug 13, 2026, 6:35 PM
Data model behavior from migrations/channel_container_draft.sql, migrations/channel_container_names.sql, migrations/channel_container_sender_ref.sql keeps working in prod.Inconclusivelow confidence

OTEL fallback saw 224,627 prod spans for the repo/env since deploy, but 5,447 were errors and the intent has no concrete surface to attribute them to.

prod, checked Aug 13, 2026, 6:36 PM
Email workflow behavior from ui/horizontal-scroll-container.tsx, components/ConversationCard.tsx, components/LeftSidebarContent.tsx keeps working in prod.Inconclusivelow confidence

Strict CloudWatch fallback found 6 recent prod failure log lines for mail.listThreads.reconcileFailed ([aws-primary] Connection <id> is not authorized), but the same failure had 1 log lines in the comparable pre-deploy baseline. Libra is not blaming this PR intent without a.

prod, checked Aug 13, 2026, 7:36 PM
Slack integration behavior from cron/process-channel-reconcile.ts, migrations/shared_channel_containers_orphan_slack.sql, scripts/channel-health.ts keeps working in prod.Inconclusivelow confidence

Strict CloudWatch fallback found 7 prod failure log lines for [syncSlackChannelForConversation] Error syncing channel (Superglue workflow failed: fetch failed), but this domain-wide failure family is not tied to this intent.

prod, checked Aug 13, 2026, 7:36 PM

Libra has verdicts on 0 of 5 tracked behaviors on prod; 5 are still being checked. Libra checks hourly for 3 days after each deploy.

Unifies Slack/LinkedIn/WhatsApp sync onto shared containers. Phases 1, 2 and 13 of channel-sync-architecture.md.

The migrations are already applied to production. This PR makes the code match a schema that is live , the inverse of the usual risk. Everything applied was additive or guarded, and the old tables are still dual-written and authoritative until reads move.

Measured on the live database

beforeafter
envelope divergence1340
duplicate Slack messages3,3440
duplicate LinkedIn messages620
naive timestamp columns360
buffer rows per shared-channel messageup to 71
Slack messages with no container16,4270

What changed

The envelope is derived, not written per message. LinkedIn replayed Unipile's newest-first pages through an unguarded upsert, so the last write was the oldest message: 129 of 292 chats disagreed with their own bodies, one 832 days stale at the bottom of the inbox.

Containers are shared; link and read state are per-user. slack_channels was keyed on the owner, so a channel two reps share was two rows , 3,344 duplicated messages, and 6 of 24 shared channels already disagreed with themselves about which deal they belonged to.

crm_events inverted onto the message. crm_slack_messages.event_id was the PK, which made "one message = one event" structural. Ten readers assumed it; the compensating delete inverted outright (ported naively, every member but the first would have received no events at all).

Reads are dual-read behind PostHog cedar-channel-container-reads (100%). Both stores stay live, so setting the rollout to 0 reverts every reader with no deploy and nothing to replay.

A reconciler replaces manual SQL , channels.health / channels.reconcile, an hourly cron, and pnpm channel-health [--reconcile].

Found along the way

  • 606 Slack channels had messages but no container row , 16,427 deal-attached messages that would have been dropped silently at cutover. Recovered, and 603 names restored from the deprecated integration_metadata mirror with no API calls. 777 channels now visible to 14 users who could never see them.
  • projectMessageToLinkedMembers had never worked , bound an array as a scalar, and its caller swallowed the error. Teammates would silently have lost every event.
  • applyProviderEnvelopeFloor bound a live Date into a raw template , the 2026-07-31 mirror outage defect, again inside a swallowed catch.
  • The reconcile cron was registered but never scheduled, so it would never have run once.
  • Two pre-existing bugs: handleReexecuteEvent read a table the current ingest never writes (every Slack re-run has failed since that migration), and a statistic counted event_type = 'slack_message' where the stored value is 'slack' , always zero.

Test plan

  • pnpm run autofix:local , 187 suites / 1,831 tests green
  • verify-containers 15/15 ยท compare-feed 0 blocking diffs, 0 rows lost across 4 accounts
  • Feed tests pass with CHANNEL_CONTAINER_READS=0 and =1

Reviewer notes

  • Carries 2 commits predating this work (687c2c43c, 09661ece7) from the base branch.
  • Restart the workers after deploy. A process started before the dual-write keeps writing container_id NULL; the verifier will drift until it restarts. Convergence loop is channel_containers_converge.sql โ†’ repair-envelopes โ†’ verify-containers.
  • Phases 3,12 remain; Phase 6 (buffer/drain) and Phase 10 (linking ladder) are the large ones.

๐Ÿค– Generated with Claude Code

Greptile Summary

The PR introduces shared Slack, LinkedIn, and WhatsApp containers with dual-write, flag-gated reads, scoped per-user state, envelope reconciliation, and operational health tooling.

  • Adds shared container, membership, pa
Show production surfaces and changed-file mapping

Production surfaces

Libra has not measured any production surfaces for this change yet.

Changed files โ†’ surfaces

  • apps/mail/components/ui/horizontal-scroll-container.tsxno production surface mapped
  • apps/mail/docs/inbox-triage.mdno production surface mapped
  • apps/mail/docs/playbook-webhooks-and-post-api-design.mdno production surface mapped
  • apps/mail/docs/table-documents.mdno production surface mapped
  • apps/mail/modules/canvas/components/ConversationCard.tsxno production surface mapped
  • apps/mail/modules/conversations/components/LeftSidebarContent.tsxno production surface mapped
  • apps/mail/modules/conversations/components/timeline/ConversationTaskCard.tsxno production surface mapped
  • apps/mail/modules/userTasks/CURATED_AGENDA_DESIGN.mdno production surface mapped
  • apps/mail/modules/userTasks/components/TaskOutputPanel.tsxno production surface mapped
  • apps/mail/modules/userTasks/components/TaskOwnerBadge.tsxno production surface mapped
  • apps/mail/tests/modules/userTasks/taskOwnerBadge.test.tsxno production surface mapped
  • apps/server/docs/agent-email-surface.mdno production surface mapped
  • apps/server/docs/channel-sync-architecture.mdno production surface mapped
  • apps/server/docs/wiki/README.mdno production surface mapped
  • apps/server/docs/wiki/channel-envelope.mdno production surface mapped
  • apps/server/package.jsonno production surface mapped
  • apps/server/src/cron/cron-task-registry.tsno production surface mapped
  • apps/server/src/cron/process-channel-reconcile.tsno production surface mapped
  • apps/server/src/db/crm-schema.tsno production surface mapped
  • apps/server/src/db/migrations/channel_container_draft.sqlno production surface mapped
  • apps/server/src/db/migrations/channel_container_names.sqlno production surface mapped
  • apps/server/src/db/migrations/channel_container_sender_ref.sqlno production surface mapped
  • apps/server/src/db/migrations/channel_containers_converge.sqlno production surface mapped
  • apps/server/src/db/migrations/channel_message_dedupe.sqlno production surface mapped
  • apps/server/src/db/migrations/channel_message_identity.sqlno production surface mapped
  • apps/server/src/db/migrations/channel_read_state_reseed.sqlno production surface mapped
  • apps/server/src/db/migrations/channel_timestamptz.sqlno production surface mapped
  • apps/server/src/db/migrations/shared_channel_containers.sqlno production surface mapped
  • apps/server/src/db/migrations/shared_channel_containers_orphan_slack.sqlno production surface mapped
  • apps/server/src/db/outbound-schema.tsno production surface mapped
  • apps/server/src/env.tsno production surface mapped
  • apps/server/src/mastra/routeHandlers/event-execution/handleReexecuteEvent.tsno production surface mapped
  • apps/server/src/mastra/tools/event-execution/createAndLinkEventsTool.tsno production surface mapped
  • apps/server/src/mastra/tools/notify/__tests__/sendEmailNotificationTool.test.tsno production surface mapped
  • apps/server/src/mastra/tools/run-sql-query/__tests__/sql-guard.test.tsno production surface mapped
  • apps/server/src/mastra/tools/run-sql-query/sql-guard.tsno production surface mapped
  • apps/server/src/mastra/utils/context-items/hydrate.tsno production surface mapped
  • apps/server/src/scripts/channel-health.tsno production surface mapped
  • apps/server/src/scripts/compare-feed-sources.tsno production surface mapped
  • apps/server/src/scripts/repair-channel-envelopes.tsno production surface mapped
  • apps/server/src/scripts/task-group-label-headless.tsno production surface mapped
  • apps/server/src/scripts/verify-channel-containers.tsno production surface mapped
  • apps/server/src/services/analytics/slack-draft-analytics.tsno production surface mapped
  • apps/server/src/services/channels/__test__/envelope-db.test.tsno production surface mapped
  • apps/server/src/services/channels/__test__/envelope.test.tsno production surface mapped
  • apps/server/src/services/channels/__test__/reconcile.test.tsno production surface mapped
  • apps/server/src/services/channels/__test__/shared-container.test.tsno production surface mapped
  • apps/server/src/services/channels/containers.tsno production surface mapped
  • apps/server/src/services/channels/envelope.tsno production surface mapped
  • apps/server/src/services/channels/health.tsno production surface mapped
  • apps/server/src/services/channels/reconcile.tsno production surface mapped
  • apps/server/src/services/channels/types.tsno production surface mapped
  • apps/server/src/services/crm/__test__/channel-deal-binding.test.tsno production surface mapped
  • apps/server/src/services/crm/__test__/channel-message-events.test.tsno production surface mapped
  • apps/server/src/services/crm/channel-message-events.tsno production surface mapped
  • apps/server/src/services/crm/conversations.tsno production surface mapped
  • apps/server/src/services/crm/dedup.tsno production surface mapped
  • apps/server/src/services/crm/move-event.tsno production surface mapped
  • apps/server/src/services/crm/slack-events.tsno production surface mapped
  • apps/server/src/services/inbox/__test__/feed-db.test.tsno production surface mapped
  • apps/server/src/services/inbox/__tests__/feed-inbox-scope.test.tsno production surface mapped
  • apps/server/src/services/inbox/feed-containers.tsno production surface mapped
  • apps/server/src/services/inbox/feed.tsno production surface mapped
  • apps/server/src/services/integrations/linkedin/messaging.tsno production surface mapped
  • apps/server/src/services/integrations/slack/slack-events-webhook.tsno production surface mapped
  • apps/server/src/services/integrations/whatsapp/index.tsno production surface mapped
  • apps/server/src/services/mail/lib/email-processor.tsno production surface mapped
  • apps/server/src/services/posthog/posthog.tsno production surface mapped
  • apps/server/src/services/user-tasks/__tests__/apply-task-group-label.test.tsno production surface mapped
  • apps/server/src/services/user-tasks/__tests__/label-not-dropped.test.tsno production surface mapped
  • apps/server/src/services/user-tasks/apply-task-group-label.tsno production surface mapped
  • apps/server/src/services/user-tasks/tasks.tsno production surface mapped
  • apps/server/src/trpc/index.tsno production surface mapped
  • apps/server/src/trpc/routes/channels.tsno production surface mapped
  • apps/server/src/trpc/routes/crm.tsno production surface mapped
  • apps/server/src/trpc/routes/integrations.tsno production surface mapped
  • apps/server/src/trpc/routes/statistics.tsno production surface mapped
  • apps/server/src/trpc/routes/task-groups.tsno production surface mapped
  • aws/lib/stacks/app-stack.tsno production surface mapped