componentsMerge origin/staging into fix/dm-container-kind 22 conflicted files. Most were unions — two sides adding different imports, exports, wiki entries or allowed-import patterns. Four were competing designs, resolved on evidence rather than preference: * New chat (LeftSidebarContent) — staging. `fbca03d0d` (Aug 30) makes a new chat the DRAFT chat, with no thread id to mint; it retires this branch's Aug 26 `goHomeToNewChat` + `findOpenEmptyChat` reuse by name, solving the same pile-up more fundamentally. * `permissions:` -> allowedSkills (playbook-execution-triggers) — HEAD. Staging threads `subagent.permissions` into `allowedSkills`; its OWN comments say that value is never enforced ("nothing sets this key today", automation-agent.ts: "a scoping feature that has never been enforced"). `77ecfb397` audited the data before deleting it: of 768 subagent docs, 21 declare the key, 19 are no-ops, and the 2 with real values name four skills that do not exist — wiring it on would have broken both agents and changed nothing for the rest. Staging's parsedByRefId restructure is kept; only the dead feed is dropped. * Before-meeting preps (calendar-events) — composed. This branch's `selectBeforeMeetingConfigs` (shared with the prep-status read model so the "wrong stage" chip cannot contradict the code that skipped it) plus staging's meeting-moved re-arm. Staging's inline stage filter is dropped: identical semantics, and the loop below already reads `schedulableConfigs`. * Settings/general — composed. This branch's form-kit row layout plus staging's 2FA card, ported onto SettingsSection. Staging's Cache card is the pre-kit copy of a section this page already carries. Agent tool scoping was two independently-built narrowings of one permission surface (`narrowSkillToolsToAgentScope` here, `withoutTools(deniedToolIds)` on staging); both are restrictions, so both are applied. MCP connections was the same shape: staging's extracted `createMcpConnection` owns the write, extended to carry this branch's `requiresAgentGrant` and setup-time tool policy. Fallout the tests caught, all cross-cutting rather than in any conflict: `optionColor` moved to components/ui/option-picker (board still imported the old path); `encryptCredential` dropped from an import line still used by updateMcpConnection; the drafter rename left a stale slug in EXPECTED_FOLDER; and staging's new remind test matched two options once this branch's "at 8am" suggestion existed. pnpm run autofix:local green: oxlint, deps:check, 3741 Jest, 9671 Vitest. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Sep 1, 2026, 1:56 AMhooksfeat(permissions): one authority for every access decision Consolidates every "may this caller act on this data" decision onto a single function, and closes eleven instances of one bug class found along the way. ## The authority services/auth/authorize.ts returns a VERDICT, never a role. There is deliberately no isOrgAdmin on the return type, so no call site can branch on one, and changing the permission model is a change to the DEFAULT_POLICY table rather than a sweep through the codebase. Policy is a frozen constant keyed (resource, scope); a missing key fails closed. resolvePolicy(orgId) is the seam for per-org policy later, so this ships with ZERO schema changes. Replaces canActOnTarget, resolveOrgMembership, userIsOrgAdmin, an inline same-org check in listTasksTool, and eleven `if (!isOrgAdmin)` sites that each re-derived the rule. One of them computed it on the wrong user. ## Holes closed All the same shape: a caller-supplied identifier resolving to another user's data below the gate. applyConfigChangeTool userId input, write readConnectionSettings userId input, read writeDocumentTool org-linked playbook path redirect listDocumentsTool same, ungated, plus displayDocumentTool configureStrategistTool bare aopId, no check at all getSentEmailsTool userId input, verbatim sent/drafted bodies aopAgents.listForAop subagent docs to any authenticated caller agent-action-queue 5 routes, incl. delete and replay (destructive) custom-field-management ownerId resolved from the verdict, then ignored overview-instance org-scope write with no tenant comparison admin router ~45 procedures + 14 sub-routers, cross-tenant Two were destructive, three were cross-tenant writes, one was introduced by an earlier fix in this same change set and caught by a later sweep. ## Feature Org admins can administer a teammate's playbook and configuration. targetUserId is uniform across the tool layer, the tRPC layer gained the org-admin path, and the frontend gained a scoped provider and member picker that never renders one person's data labelled as another's. ## Enforcement Five guards keyed on the LIVE REGISTRY, not hand-written lists, each with an anti-vacuity floor and each proven by planting the violation: no bare userId inputs on any registered tool every targetUserId file reaches the authority every mutating action is administrable or documented self-only role reads confined to the authority (depcruise rule + source scan) redirect sites consult the authority about the RESOLVED target ## Notes - agentExecutionEnabled is Cedar-staff-only, enforced in the single writer. Stronger than SELF, so deliberately not a policy row. - playbook:org and document:org are ANY_MEMBER, matching today's behaviour. 57 of 73 orgs have no admin; tightening is one cell once they do. - Fixes two org-role gates that read undefined on every request and so refused everyone, including statistics.getOrgOverview. - config-write split: apply-change moved to connection-write. 17,615 -> 10,142 bytes against the connector's silent-drop ceiling. Verified: server 799 files / 9,310 tests; mail 316 suites / 2,959 tests; types and deps:check clean. End-to-end against the production Cedar org with a temporary non-staff account, 42 assertions across member/admin/viewer, since staff accounts cannot exercise the org-grant branch. Account deleted and org state verified identical to its pre-test backup. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Sep 1, 2026, 8:01 AMthemefeat(agents,meetings): collapse the connection list into a ring, and split the meetings tab further WIP on the agent config surfaces and the meetings tab, committed so the branch can take origin/staging. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 30, 2026, 3:43 PM