CedarCopilot wants to merge 4 commits into staging from feat/slack-trigger-sources
Live on prod, no production signal yet
Strict CloudWatch fallback saw 3,233 success-shaped log lines matching pipeline, analytics, quota, aop, but no tied operation was present, so Libra is not calling this working.
Strict CloudWatch fallback found 91 recent prod failure log lines for [UpdateExternalCrmWorkflow] Driver update failed (Step updateOpportunityField failed: HTTP 400: [{\), but the same failure had 83 log lines in the comparable pre-deploy baseline. Libra is not blaming this PR.
Strict CloudWatch fallback saw 7,079 success-shaped log lines matching /<id>.sql, /<id>.sql, applyconfigchangetool, sherlock_system_knowledge, playbook-anatomy, but no tied operation was present, so Libra is not calling this working.
Strict CloudWatch fallback found 2 recent prod failure log lines for [backfillSlackChannelHistory] Backfill failed (Failed query: insert into \), but the same failure had 7 log lines in the comparable pre-deploy baseline. Libra is not blaming this PR intent without a.
Libra has verdicts on 0 of 4 tracked behaviors on prod; 4 are still being checked. Libra checks hourly for 3 days after each deploy.
0047 and 0048 were applied by hand on 2026-08-24 (single prod/staging database), in one
transaction, verified. Do not re-run them , and a reviewer does not need to. Both use
IF NOT EXISTS, so a later drizzle-kit migrate is a harmless no-op, but Drizzle's journal
does not know they ran.
This PR also edits 0047_playbook_webhook.sql, which someone else authored. That is
deliberate and safe: it had never been applied on any database, because it could not be ,
see below.
Two independent reasons, which is likely why it was abandoned:
playbook_webhook table did not exist in production.0047 declared org_id as text against organizations.id (uuid).
Postgres refuses that FK: "Key columns "org_id" and "id" are of incompatible types: text
and uuid." Proved in a rolled-back transaction. Every other org FK in the schema is uuid.The unit tests stayed green throughout, because the dispatch test mocked
runPlaybookSectionExecution , the only step that could have failed loudly. Five passing
tests over a feature that could not run at all. This PR replaces that mock.
A webhook row gains a source , what fires it. http is the original behaviour and the
default for every existing row. slack_channel is fired by Cedar's own Slack ingest, reaching
the same queue, dispatch and blocks. One entrance more, not a second machine; playbook
compilation learns nothing about Slack.
Three behaviours worth reviewing closely:
topLevelOnly defaults on. The self-post filter catches Cedar's bot, not a human
replying beneath the agent's own post , which would otherwise re-fire it forever.A webhook could previously only be minted from the playbook editor. Extracting the rules into
playbook-webhook-registration.ts is what surfaced the authz hole: ownership was checked in
the tRPC route only, so config-write could register a webhook against another user's AOP.
| Surface | Before | After |
|---|---|---|
cedar-cli | no webhook command | create · list · enable · disable · test |
config-write | no webhook change type | manage_playbook_webhook |
| tRPC | create only | + listPlaybookWebhooks, testFirePlaybookWebhook |
| playbook-authoring / anatomy | webhook absent | full recipe + trigger reference |
| Sherlock | nothing | 10-step failure ladder |
| account-setup | nothing | channel-triggered agent recipe |
cedar-cli webhook test --id <id> --text "…" fires through the real dispatch path and
waits, printing which agents ran. outcome: null means nothing ran, which almost always means
no <trigger> block references the row.
PlaybookWebhookQueue , a persistently failing dispatch retried, then vanished.crm.ts:553 documents this exact trap).types 0 errors · deps:check clean, 1535 modules · 758 tests / 44 files passing
(services/playbook, services/integrations/slack, skills/account-config).
Constraints were exercised against live Postgres in a rolled-back
Libra has not measured any production surfaces for this change yet.