__mocks__test: aadded crm testsOct 16, 2025, 2:03 PMclient-providers.tsxfeat(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 AMquery-provider.tsxfix(threads): a thread marked done stays gone, whatever writes the list Round 1 treated the optimistic removal as an edit and repaired the one window it could name -- a listThreads response issued inside the archive round-trip -- by re-applying the removal once, the instant the mutation settled. That assumed a 227-380ms round-trip. Staging measures mail.markDone at up to 7381ms, and all three resurrections prod ever recorded landed 15.7-18.2s after the click, every one a fetch-response: seconds after the one-shot repair had already run, with nothing left to oppose them. So the removal becomes an invariant instead of an edit. While a thread is guarded, any write to a mail.listThreads query that reintroduces it is repaired immediately -- late fetch response, IndexedDB restore, side-inbox prefetch and fetchNextPage alike -- so we no longer have to name the guilty write. The guard is time-boxed at 60s; markActive, undo and mutation rollback all release first, so a legitimate return still lands. Suppressions now report to the server, not PostHog. The previous round's diagnostic was PostHog-only and the browser reporting the bug sends PostHog nothing -- 66 archives on staging produced zero client events -- so the fix could never be verified. mail.reportListSuppression writes a structured log readable in CloudWatch. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 24, 2026, 3:51 PMserver-providers.tsxchore: take Autumn billing out until we actually bill Nothing in the product charges anyone, but the Autumn provider still wrapped the entire app — and its error boundary sat above every route, so any render error anywhere below it got swallowed and reported as "billing unavailable" while the whole tree silently remounted. Real bugs were hiding behind a billing message. Removes the provider, the /autumn route, the customer-delete side effects in account deletion, and AUTUMN_SECRET_KEY from the runtime contract. useBilling stays as a no-op stub so the billing-aware UI keeps compiling and renders its "no subscription" branches; restore the Autumn-backed implementation to turn billing back on. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 13, 2026, 11:04 PMsession-provider.tsxfix: add session retry escape hatch and tighten auth cookie detection Transient session errors show a login link and redirect after 30s; escapeXml quotes apostrophes; privateProcedure logs session_token cookie presence. Co-authored-by: Cursor <<email>>Jun 1, 2026, 11:36 PM