CedarCopilot wants to merge 7 commits into staging from feat/config-inbox-task-groups
Live on prod, no production signal yet
Strict CloudWatch fallback found 28 recent prod failure log lines for [UpdateExternalCrmWorkflow] Driver update failed (Step updateOpportunityField failed: HTTP 400: [{\), but the same failure had 16 log lines in the comparable pre-deploy baseline. Libra is not blaming this PR.
Strict CloudWatch fallback found 2 recent prod failure log lines for mirror.upsertEmailThread failed (write CONNECTION_CLOSED aws-1-us-east-2.pooler.supabase.com:6543), but the same failure had 1 log lines in the comparable pre-deploy baseline. Libra is not blaming this PR.
Strict CloudWatch fallback found no success or completion log lines matching /tool-call-observability.ts, applyconfigchangetool, readconnectionsettingstool, configtool, workspacewritetool in the last 24h.
Libra has verdicts on 0 of 3 tracked behaviors on prod; 3 are still being checked. Libra checks hourly for 3 days after each deploy.
Adds three configuration surfaces to Cedar's chat/MCP config service, plus task→group reassignment:
apply-changeapply-changeservices/task-groups/manage-task-groups.ts (ownership guard + Gmail-label side-effects); the tRPC route delegates.manage_task_group ConfigChange variant: op: create | update | delete | reorder.apply-changeupdate_inbox_settings , layout scalars (inboxLayout, importantSignal, inboxOrder).manage_inbox , split CRUD, delegating to inbox-definitions.ts. accountId resolved server-side.systems-write toolPR #2623 shipped the credential vault and org-shared MCP with a complete resolve path, but writes reachable only from tRPC and the settings UI. An agent could use a credential and not store one, so onboarding a customer's Xero or internal API was still a human clicking through Settings. This adds the write half.
Three variants: manage_credential_entry, manage_mcp_connection, update_mcp_connection_settings.
A fourth tool, not actions on config-write. That tool's rendered inputSchema sits 385 bytes under the claude.ai connector's silent-drop ceiling (measured; budget enforced by tool-inputschema-size.test.ts). These variants are several KB, and going over makes the whole config write surface vanish from tools/list with no error anywhere. Same split, and same reason, as workspace-write.
Closes a gap in #2623 while extracting. services/integrations/mcp/manage-mcp-connections.ts comes out of the tRPC route (single writer, as manage-task-groups.ts already is here). The manual/API-key path never stamped scope, so a bearer-token MCP server could not be org-shared even though an OAuth one could. The read side needed nothing , selectMcpConnections already resolves user-over-org.
inboxes, task_groups and credentials sections on read-settings. The credentials section returns CredentialEntrySummary, which cannot carry a secret by construction (field NAMES only; needsAttentionReason is a classification code).
Nullable taskGroupId on the update-task surface (null = Misc), with the ownership check and Gmail relabel from taskGroups.moveTaskToGroup.
Results name FIELDS, never values. That asymmetry is what lets systems-write be reachable over external MCP at playbook:write rather than taking config-read.get-credentials' in-app-only treatment , that action returns raw tokens; this one only accepts them. Headless account setup is the driving use case and in-app would lock it out.
scope: 'org' never takes an organizationId from the caller: it is resolved from their own membership and gated on userIsOrgAdmin (the same rule credential-vault's orgAdminProcedure applies on the tRPC path , verified equivalent, both read user.organizationRole).
Redaction is at mcp/external/tool-call-observability.ts, not in the tool. Found by driving the real /mcp endpoint: a redaction inside applyConfigChangeTool left the approval card clean while Axiom recorded "authorizationHeader":"Bearer sk-live-…" in full, because that wrapper reads the arguments before any tool body runs. It feeds two sinks (telemetry inputPreview, and the chat/Slack intent sink). utils/redact-secrets.ts is therefore tool-agnostic, keyed on field name, and recursive , the leaked field was two levels down at arguments.change.authorizationHeader , so it covers every tool now and later. The handler still receives the real values.
Staging shipped #2622's user-authored-task guard, whose rationale quotes the reporter: *
Libra has not measured any production surfaces for this change yet.