CedarCopilot wants to merge 1 commit into staging from fix/agent-instructions-doc-admin-view
Live on prod, no production signal yet
Verification reached its 130s outer budget before the verifier returned. Libra is keeping this intent verifying until the next check.
Only 5 prod OTEL spans matching GET /api/doc-events reached Libra since the deploy, below the 20-span floor for calling a change verified. Nothing is failing; there is not yet enough traffic to confirm it.
Libra found 11 production surfaces on prod but could not judge any of them yet. 3 surfaces had under 20 requests, so Libra has not judged them; 6 surfaces had no requests at all. Libra checks hourly for 3 days after each deploy.
Karim (Adapt Insurance, org admin) reported that Jacob's agent instructions weren't showing when he viewed Jacob's agent , the tab rendered blank with no error.
Root cause: the org-admin targetUserId admin-view prop reaches every trpc.agent.* call in the agent workspace, but the instructions tab's actual content is rendered through a separate primitive, <Document> (the shared Y.js collaborative editor), which had no targetUserId concept at all. Its documents.getDoc fetch ran under the admin's own session id, the server correctly rejected it as a cross-user read (row.userId !== userId on a user/-scoped doc), and the rejection was swallowed into a console.error , AgentInstructionsSection never wired an onProviderError handler , so the editor just bound to a permanently empty Y.Doc().
Document/DocumentProps (apps/mail/modules/documents/document.tsx) gains a targetUserId prop, forwarded into both the initial getDoc seed fetch and refreshFromServer().AgentInstructionsSection forwards its own targetUserId prop into <Document> instead of dropping it./api/doc-events (apps/server/src/http/app.ts) , the live-update SSE channel , had the identical shape of gap: a user/-scoped doc's live stream only allowed the doc's own owner or Cedar staff. Even with the read fixed, an admin's session would 403 on live remote updates. Routed the user/ branch through assertActorAllowed (the same authority documents.getDoc already uses) instead of a flat isCedarStaff check.files.applyUpdate (the write path) needed no change , it already derives the document's scope from the row itself via assertAuthorizedScope, not from a client-supplied id, so org-admin writes were already correctly authorized.pnpm --filter @zero/server run types , cleanpnpm --filter @zero/mail run types , cleandocument.test.tsx: targetUserId forwarded on both the initial seed and refreshFromServerpnpm --filter @zero/mail exec jest tests/modules/documents tests/modules/agents tests/modules/company/brainExplorerSelection.test.tsx tests/modules/files/brain-explorer.test.tsx tests/modules/brain , 44 suites / 332 tests passpnpm --filter @zero/server exec vitest run src/trpc/routes/__tests__/agent-router-org-admin.test.ts , 10/10 passpnpm dlx oxlint@1.78.0 --deny-warnings on changed files , cleanpnpm deps:check , no violationsš¤ Generated with Claude Code
https://claude.ai/code/session_01SfYKPYHXdMgrPLuKhXvWed
This PR carries administered-user scope into the shared collaborative document editor and aligns its live-event authorization with document reads.
targetUserId through initial and manual document refresh requests.The implementation appears safe to merge, with a non-blocking request to add regression coverage for the changed live-event authorization branch.
The document read path independently authorizes the target and validates persisted ownership, while the SSE path derives its target from the stored row and uses the shared authorization authority; the remaining concern is test coverage rather than an established access-control defect.
Files Needing Attention: apps/server/src/http/app.ts
| Filename | Overview |
|---|---|
| apps/mail/modules/agents/components/AgentInstructionsSection.tsx | Propagates the existing administered-user scope into the shared document editor. |
| apps/m |
| Surface | Requests | Errors | p95 | Users | Verdict |
|---|---|---|---|---|---|
| /api/trpc/admin.documents.writeGuarded | 0 ā 9 | 0 ā 0 (0%) | not measured ā 2288 ms | 0 | Insufficient traffic 9 requests, under the 20 Libra needs |
| POST /api/trpc/admin.documents.writeGuarded | 0 ā 6 | 0 ā 0 (0%) | not measured ā 2288 ms | 0 | Insufficient traffic 6 requests, under the 20 Libra needs |
| execute_tool read-document | 3 ā 1 | 0 ā 0 (0%) | 228 ms ā 131 ms | 0 | Insufficient traffic 1 request, under the 20 Libra needs |
| execute_tool write-document | 1 ā 0 | 0 ā 0 (0%) | 410 ms ā not measured | 0 | No traffic No requests recorded since this deploy. |
| execute_tool list-documents | 2 ā 0 | 0 ā 0 (0%) | 179 ms ā not measured | 0 | No traffic No requests recorded since this deploy. |
| /api/trpc/documents.getDoc | 0 ā 0 | 0 ā 0 (0%) | not measured | 0 | No traffic No requests recorded since this deploy. |
| POST /api/trpc/documents.getDoc | 0 ā 0 | 0 ā 0 (0%) | not measured | 0 | No traffic No requests recorded since this deploy. |
| /api/trpc/admin.documents.listForUser | 0 ā 0 | 0 ā 0 (0%) | not measured | 0 | No traffic No requests recorded since this deploy. |
| /api/trpc/admin.documents.listOrgPlaybookDocs | 0 ā 0 | 0 ā 0 (0%) | not measured | 0 | No traffic No requests recorded since this deploy. |
| documents.getDoc | no baseline ā 0 | no baseline ā 0 (0%) | not measured | not counted | Unavailable ClickHouse reads are unavailable, so Libra could not measure this surface. |
| /api/doc-events | no baseline ā 0 | no baseline ā 0 (0%) | not measured | not counted | Unavailable ClickHouse reads are unavailable, so Libra could not measure this surface. |