feat(auth): separate filesystem read and write permissions - #9788
juliusmarminge wants to merge 35 commits into
Conversation
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
c80d93e to
3b96a67
Compare
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This is a broad authentication and filesystem-permission change spanning server authorization and web/mobile file operations, including new default grants and revocation behavior. The security boundary and changed product defaults require human review. Not approved because:
Review your spending limits in Billing settings, or comment |
3b96a67 to
fb4489d
Compare
fb4489d to
d7df773
Compare
bfb151c to
eec5dfb
Compare
38e8814 to
4b73b2d
Compare
4b73b2d to
bef54b1
Compare
bef54b1 to
c1d166f
Compare
The same resolveFilesystemReadAccess block was inlined in four files. Using the existing useFilesystemReadAccess hook drops the copies and stops useAssetUrls and the read-only editor banner from treating a pending grant as a denial. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The rebase left the fixture's frame tracker declared twice, a loading state on a removed icon, and the media hook private while its test drives it directly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Direct workspace reads and edits shared task permissions, while local diffs required
review:write. Addfilesystem:readfor browsing, searching, previews, and local diffs, andfilesystem:writefor edits and saved plans. Both remain in the Standard preset; new grants retirereview:writewhile old credentials remain decodable.Host workspace/media URLs require file-read access when minted. Web, desktop, and mobile menus wait for a known grant from the source environment, then recheck after native selection and URL minting. Copying paths or URLs, uploaded attachments, and local or external media keep their existing behavior. Explicit asset refresh retains server authorization during grant loading.
Revocation hides cached search results and stops pending autosaves. Unsaved edits survive closing and reopening previews, React effect replay, and grant changes; an older editor's completed write cannot clear a newer draft's pending state. Typed project paths still work with task permission alone, while directory browsing requires file access. Mobile Review explains denied local-diff access instead of reporting an empty worktree.
Existing credentials keep their recorded scopes and need a fresh grant to add filesystem access. These scopes govern direct client actions; they do not sandbox providers or terminal commands.
Earlier focused media, search, save, and Review suites passed with coverage for initial grant loading, revocation during async work, draft recovery, and unaffected nonhost media. Web, mobile, and shared scoped typechecks passed during stack verification. The media below records those earlier client checks.
An existing race in the highlighting test fixture left frame callbacks running after its global stubs were removed, causing a
cancelAnimationFrameexception in CI. The fixture now tracks and cancels pending frame handles after worker termination and before restoring globals. Controlled callback ordering reproduced the failure with the old fixture and passed with the fix; all seven tests using real workers passed at the integrated a685c585 revision. Web and mobile typechecks passed there. Lint for the integrated follow-up files reported zero errors and 24 existing warnings; formatting passed.Earlier-revision pairing UI:
Earlier iPhone E2E used the same dirty worktree with file access granted and denied. These captures predate final integration:
Model: GPT 6 Astra. Harness: Codex.
Note
High Risk
Changes authentication scope requirements and authorization for file reads, writes, diffs, and asset URLs across server and all clients; misconfiguration or stale grants can block core workspace features.
Overview
Introduces
filesystem:readandfilesystem:writeas first-class OAuth grant scopes and wires them through server RPC authorization, replacing orchestration/review scopes for direct host file operations and local diff preview.review:writeis retired for new token requests; host workspace/media asset minting now requiresfilesystem:read, while attachments keep existing rules.Web, mobile, and desktop clients gate browsing, file trees, previews, composer path search, asset URLs, media menus, and git/worktree review sections on
resolveFilesystemReadAccess, showing loading/denial states instead of firing unauthorized queries or leaking cached host diffs. Losingfilesystem:writestops autosave and keeps unsaved drafts across closed previews until write access returns; plan save and file editor UI reflect read-only mode.Pairing/token flows and CLI scope flags now use the unified
AuthGrantScopeset; server tests cover scoped WS file read/write and asset URL behavior.Reviewed by Cursor Bugbot for commit f6761daa8547a8a0e07f1d8aa2f7c6f0b0c3aea9. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Separate filesystem
readandwritescopes across server, web, and mobileresolveFilesystemReadAccessresolver in filesystem.ts that distinguishes pending, denied, and granted states from catalog, connection, and session dataorchestration:read/review-writetofilesystem:read/filesystem:write;assetsCreateUrlin ws.ts now requiresfilesystem:readfor workspace-file and media-file resourcesfilesystem:writeis revoked, drafts stay pending, and auto-recover once write access returnsfilesystem:read/filesystem:writeinstead ofreview-writeRPC_REQUIRED_SCOPESreassignment removesreview-write; existing sessions or pairing tokens that relied onreview-writefor file/diff access must now be grantedfilesystem:readorfilesystem:writeMacroscope summarized 7d9a81c.
Summary by CodeRabbit