Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

fix(agents): agent instructions doc doesn't load for org admin in teammate's workspace

merged#2762CedarCopilot

CedarCopilot wants to merge 1 commit into staging from fix/agent-instructions-doc-admin-view

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Sep 11, 2026, 12:29 PM
  2. Merged
    Sep 11, 2026, 12:42 PM
  3. Live on prod
    Sep 11, 2026, 12:42 PM
  4. Observed 38 hours, 11 surfaces, 16 requests
    Sep 11, 2026, 12:42 PM
  5. Pipelines steady after this deploy
    Sep 11, 2026, 12:42 PM
  6. Sep 11, 2026, 2:17 PM
  7. Unobserved

    Live on prod, no production signal yet

    Sep 13, 2026, 2:33 AM

Behaviors Libra is checking

When an organization admin or owner views a teammate's agent instructions, the editor fetches and refreshes the teammate-scoped document content instead of querying as the admin's own user.Inconclusivelow confidence

Verification reached its 130s outer budget before the verifier returned. Libra is keeping this intent verifying until the next check.

prod, checked Sep 13, 2026, 1:35 AM
Authorized organization admins and owners can subscribe to and receive live updates for a teammate's user document or playbook while it is open.Inconclusivelow confidence

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.

prod, checked Sep 13, 2026, 2:33 AM

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.

Summary

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().

Changes

  • 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.

Test plan

  • pnpm --filter @zero/server run types , clean
  • pnpm --filter @zero/mail run types , clean
  • New regression tests in document.test.tsx: targetUserId forwarded on both the initial seed and refreshFromServer
  • pnpm --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 pass
  • pnpm --filter @zero/server exec vitest run src/trpc/routes/__tests__/agent-router-org-admin.test.ts , 10/10 pass
  • pnpm dlx oxlint@1.78.0 --deny-warnings on changed files , clean
  • pnpm deps:check , no violations

šŸ¤– Generated with Claude Code

https://claude.ai/code/session_01SfYKPYHXdMgrPLuKhXvWed

Greptile Summary

This PR carries administered-user scope into the shared collaborative document editor and aligns its live-event authorization with document reads.

  • Forwards targetUserId through initial and manual document refresh requests.
  • Passes the agent workspace's administered user into the instructions document.
  • Allows authorized organization administrators to subscribe to a teammate's user-scoped document events.
  • Adds client regression coverage for both document-fetch paths; the HTTP authorization branch still lacks focused route coverage.

Confidence Score: 4/5

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

Important Files Changed

FilenameOverview
apps/mail/modules/agents/components/AgentInstructionsSection.tsxPropagates the existing administered-user scope into the shared document editor.
apps/m
Show production surfaces and changed-file mapping

Production surfaces

SurfaceRequestsErrorsp95UsersVerdict
/api/trpc/admin.documents.writeGuarded0 → 90 → 0 (0%)not measured → 2288 ms0Insufficient traffic
9 requests, under the 20 Libra needs
POST /api/trpc/admin.documents.writeGuarded0 → 60 → 0 (0%)not measured → 2288 ms0Insufficient traffic
6 requests, under the 20 Libra needs
execute_tool read-document3 → 10 → 0 (0%)228 ms → 131 ms0Insufficient traffic
1 request, under the 20 Libra needs
execute_tool write-document1 → 00 → 0 (0%)410 ms → not measured0No traffic
No requests recorded since this deploy.
execute_tool list-documents2 → 00 → 0 (0%)179 ms → not measured0No traffic
No requests recorded since this deploy.
/api/trpc/documents.getDoc0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
POST /api/trpc/documents.getDoc0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
/api/trpc/admin.documents.listForUser0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
/api/trpc/admin.documents.listOrgPlaybookDocs0 → 00 → 0 (0%)not measured0No traffic
No requests recorded since this deploy.
documents.getDocno baseline → 0no baseline → 0 (0%)not measurednot countedUnavailable
ClickHouse reads are unavailable, so Libra could not measure this surface.
/api/doc-eventsno baseline → 0no baseline → 0 (0%)not measurednot countedUnavailable
ClickHouse reads are unavailable, so Libra could not measure this surface.

Changed files → surfaces

  • apps/mail/modules/documents/document.tsx/api/trpc/admin.documents.writeGuardedPOST /api/trpc/admin.documents.writeGuardedexecute_tool read-documentexecute_tool write-documentexecute_tool list-documents/api/trpc/documents.getDoc+3
  • apps/mail/modules/agents/components/AgentInstructionsSection.tsxno production surface mapped
  • apps/mail/tests/modules/documents/document.test.tsxno production surface mapped
  • apps/server/src/http/app.tsno production surface mapped