Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

feat(chat): internal chat-only access entitlement (chatAccessEnabled)

merged#2526CedarCopilot

CedarCopilot wants to merge 0 commits into staging from feat/chat-only-access

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

    Live on prod, no production signal yet

    Aug 23, 2026, 10:19 AM

Behaviors Libra is checking

Chat workflow behavior from imessage/imessage-bot-chat.ts, slack/slack-bot-chat.ts, sms/sms-bot-chat.ts keeps working in prod.Degradedlow confidence

Strict CloudWatch fallback found 1 prod failure log lines for [bufferSlackMessageEvent] Error buffering message (Failed query: \n SELECT cu.user_id, c.display_name AS channel_name\n FROM channel_container_users cu\n JOIN channel_containers c ON c.id = cu.container_id\n JOIN.

prod, checked Aug 23, 2026, 10:19 AM
Email workflow behavior from components/UserSettingsEditor.tsx, playground/user-management.tsx, chatComponents/agentAccess.ts keeps working in prod.Inconclusivelow confidence

Strict CloudWatch fallback found 1 prod failure log lines for [MEETING_NOTES_WEBHOOK] Error processing webhook (AskElephant webhook payload must contain at least one attendee with a valid email address), but this domain-wide failure family is not tied to this intent.

prod, checked Aug 21, 2026, 10:57 PM

Libra has verdicts on 0 of 2 tracked behaviors on prod; 2 are still being checked. Libra has 1 low-confidence degraded verdict it is still confirming. Libra checks hourly for 3 days after each deploy.

What

Adds chatAccessEnabled , an internal, admin-only entitlement that opens the Cedar chat agent for a user without enabling agent execution. Because every background/execution surface gates on agentExecutionEnabled alone, a user granted chat-only access can chat while all execution stays off ("everything off except chat").

Mirrors agentExecutionEnabled but is not surfaced in end-user settings.

Server-side enforcement (real gate, all chat-agent surfaces)

A shared helper isChatAccessAllowed(userId) = chatAccessEnabled || agentExecutionEnabled, read from the authoritative agent_settings jsonb column (same source as the per-event execution gates). Wired into every surface that runs the chat agent:

  • In-app chat + SDK harness , executeChatAgentStreaming (single choke point for both the REST and container paths)
  • Slack , runChatAgent
  • iMessage , handleImessageBotInteraction (also covers tapback dispatch)
  • SMS / WhatsApp , handleSmsBotInteraction

Denied users get a short "chat isn't enabled" reply on headless surfaces and a stream error+done in-app.

Intentionally left ungated

  • External MCP , governed by its own OAuth scope system (in-app scope already stripped from external callers).
  • Roadmap chat , separate lightweight agent, no mail/CRM tools.

Toggle plumbing

  • chatAccessEnabled added to the settings schema, agent_settings categorization (settings.ts), and defaultUserSettings.
  • admin.toggleChatAccess mutation (dual-writes the authoritative agent_settings column, mirroring toggleAgentExecution).
  • Playground "Chat Access (no execution)" switch per user + key in the generic user-settings editor.
  • In-app composer gate (agentAccess.ts) now grants chat on either flag; +3 unit tests.

Behavior change

Previously the headless bots (Slack/iMessage/SMS/WhatsApp) ran for any linked Cedar user, ungated. They now require chatAccessEnabled || agentExecutionEnabled. Users with agent execution on are unaffected; only users with both flags off are newly blocked.

Verification

  • pnpm --filter @zero/server run types Ā· @zero/mail run types , clean on all touched files
  • pnpm deps:check , no dependency violations (service helper imports only db/env/drizzle)
  • agentAccess jest suite , 10/10 pass

šŸ¤– Generated with Claude Code

Greptile Summary

Adds an internal chat-only entitlement, persists it alongside agent settings, and applies the resulting access gate to the in-app and headless chat-agent entry points.

  • Adds chatAccessEnabled to settings schemas, defaults, admin controls, and the in-app composer gate.
  • Introduces a shared authoritative entitlement lookup and checks it in chat workflow, Slack, iMessage, SMS, and WhatsApp handlers.
  • Adds frontend access tests and playground controls for assigning the entitlement.

Confidence Score: 2/5

The PR is not safe to merge until the entitlement mutation is restricted to Cedar admins and the Slack operation-driven chat-agent paths enforce the same access gate.

Regular authenticated users can currently assign the new internal entitlement to arbitrary accounts, and denied Slack users can bypass the new runChatAgent check through direct agent_prompt operation dispatch.

Files Needing Attention: apps/server/src/trpc/routes/admin.ts, apps/server/src/mastra/routeHandlers/slack/slack-bot-chat.ts, apps/server/src/mastra/operations/operation-registry.ts

Security Review

The new entitlement mutation is exposed through authentication-only privateProcedure while accepting an arbitrary target user, allowing regular authenticated users to assign an intended Cedar-admin-only entitlement. How this was verified: The mutation was traced from caller-controlled userId through privateProcedure to the authoritative agent_settings write, while `cedarAd

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/app/(routes)/playground/components/UserSettingsEditor.tsxno production surface mapped
  • apps/mail/app/(routes)/playground/user-management.tsxno production surface mapped
  • apps/mail/modules/cedar-os/__tests__/chatComponents/agentAccess.test.tsno production surface mapped
  • apps/mail/modules/cedar-os/src/cedar-os-components/chatComponents/agentAccess.tsno production surface mapped
  • apps/server/src/lib/schemas.tsno production surface mapped
  • apps/server/src/mastra/routeHandlers/imessage/imessage-bot-chat.tsno production surface mapped
  • apps/server/src/mastra/routeHandlers/slack/slack-bot-chat.tsno production surface mapped
  • apps/server/src/mastra/routeHandlers/sms/sms-bot-chat.tsno production surface mapped
  • apps/server/src/mastra/workflows/chat/chat-workflow.tsno production surface mapped
  • apps/server/src/services/users/user-settings.tsno production surface mapped
  • apps/server/src/trpc/routes/admin.tsno production surface mapped
  • apps/server/src/trpc/routes/settings.tsno production surface mapped