Skip to content

feat(auth): separate source control write permissions - #9787

Merged
juliusmarminge merged 43 commits into
t3code/auth-environment-scopesfrom
t3code/auth-source-control-scope
Oct 7, 2026
Merged

juliusmarminge merged 43 commits into
t3code/auth-environment-scopesfrom
t3code/auth-source-control-scope

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

Task-operation access also permitted direct Git and pull-request mutations. Add source-control:write for cloning, pushing, changing branches, and PR writes, with matching web, desktop, and mobile controls. Repository reads and PR resolution retain orchestration:read.

Actions check the target environment again after confirmations, navigation, and async work. PR title, description, and comment editors disable Save after revocation while retaining local text; multi-step comment/close operations recheck each write. Bulk actions check every actual write target. PR checkout handoff rechecks source-control access before creating a local draft or navigating. Attaching PR context to an existing composer remains a local action.

PR checkout preparation now shows returned permission denials and other failures in the dialog's existing error area. Starting a valid retry clears the message; interruptions remain quiet. Closing and reopening continues to reset the dialog.

Preparing a PR worktree with a thread also requires orchestration:operate for its setup work. Ordinary commits and pushes require source-control access; persisted thread/project metadata checks task permission separately. Deleting a thread remains independent of Git and terminal permissions, while explicit worktree removal checks source-control access. Local draft navigation and future-worktree base selection retain their existing behavior.

Git controls fall back to loaded thread details when an archived thread has no active-list entry, preserving its persisted branch context. The mobile branch/worktree row describes browsing when either permission needed to change the thread's branch is missing.

Mobile branch and worktree forms retain their inputs after a denial or failure and close after the Git action and any required task-metadata update succeed. A metadata failure can follow a successful Git mutation; the form stays open in that case. Bulk Settle is disabled when no selected threads are eligible to settle, and a retained menu callback preserves selection if its original eligible targets have since settled or disappeared.

The scope is included in new default grants and is independently selectable when pairing. Existing credentials retain their recorded scopes.

Focused checkout, Git, and PR regressions cover denied and permitted requests, permission changes during multi-step operations, editor revocation, and independent task/Git grants. At 82749030, the integrated web run passed 46 Git-control/thread-permission cases as part of 162 cases across four files. The mobile subtitle change passed formatting and scoped lint.

The later PR-handoff preflight received independent source review and scoped lint. After the final test-type correction, 36 thread-permission tests and the integrated web typecheck passed at 6a9376f5. These tests do not directly exercise the PR panel's handoff callback; that UI path was not rerun end to end.

The mobile Git hook and sheet tests produced 12 failures and 10 passes before the completion fix; all 22 passed afterward and again within the 28 mobile cases at the integrated a685c585 revision. Web and mobile typechecks passed both at the owning 538b0c98 layer and that integrated revision. The Settle callback received source review. Lint for the integrated follow-up files reported zero errors and 24 existing warnings; formatting passed.

The checkout-feedback tests produced three failures and 27 passes before the fix; all 30 passed afterward. At the integrated 273e55af revision, eight dialog tests and 22 shared source-control action tests passed in separate focused runs. Web typechecks passed at both the owning 91bc6843 layer and the integrated revision. The two changed files passed formatting and lint with zero warnings or errors. This dialog follow-up was not rerun end to end in a real client.

Earlier-revision pairing UI, captured before the final stack integration:

Before After
Before: pairing permissions After: source-control permissions

The restricted-connection browser pass at 6a9376f5 confirmed the Git write toolbar was unavailable. The captured toolbar uses the same fixture as the task-scope comparison in #9786; it does not extend the handoff coverage described above.

On September 5, 2026, a real iOS Simulator run submitted Other to create a branch that already existed. The before branch flow closed the form. In the verified 273e55af run, the same failure kept NEW BRANCH open and Other intact; Git HEAD, branch refs, and working-tree status were unchanged. The run reused the signed simulator app, and the running Hermes completion guard was verified before the after capture. This was not a new native compile or a manual permission-revocation race test.

The before caption identifies the branch flow from 6a9376f5. That capture used a cached Hermes bundle; the Git-flow files match across 82749030 through that revision.

Before: branch flow from 6a9376f5 After: verified 273e55af
Before: Git failure closes the branch form After: Git failure retains the branch form and Other input
12-second before recording 12-second after recording

Both recordings are continuous excerpts of the original simulator captures, with no overlays or reconstructions.

Model: GPT 6 Astra. Harness: Codex.


Note

High Risk
Changes authorization for core git, clone, and PR mutation RPCs and threads permission through web/mobile/desktop; mis-scoped tokens or missed UI guards could block workflows or allow unintended mutations.

Overview
Introduces source-control:write as the scope for mutating git and hosted source control, while orchestration:operate stays focused on projects and thread/orchestration changes (e.g. registering a project, updating a thread’s branch/worktree).

Server: WebSocket RPC mapping in RpcAuthorization.ts moves clone/publish, VCS pull/checkout/branch/worktree, stacked git actions, and most PR write RPCs to AuthSourceControlWriteScope; PR resolution stays read-scoped. Worktree PR prep with a thread id additionally requires operate scope in ws.ts. HTTP token grants allow the new scope.

Clients: Web, mobile, and shared hooks gate add/clone project flows (clone needs both SC write + operate), git menus/sheets, branch pickers, PR thread dialog (worktree vs local), sidebar thread actions, and useSelectedThreadGitActions—with readEnvironmentScope at submit time so revoked grants don’t leave partial side effects. UI disables actions and shows connection-specific hints; read-only paths like opening PRs remain available.

Tests: New/expanded coverage for permission rechecks on retained callbacks, clone-without-disk-leak, and server integration for scoped WS calls.

Reviewed by Cursor Bugbot for commit e687b3aa132a4bfe7e52bab29f55ad2a78698b84. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add separate source-control write scope for Git and pull-request mutations

  • Introduces a new source-control write permission scope distinct from orchestration operate, governing commits, pushes, branch changes, cloning, worktree removal, and pull-request changes across web, mobile, and server
  • Gates thread mutations (archive, pin, settle, snooze, delete, rename, reorder) behind orchestration operate scope; local-only actions like mark-unread, copy, and branch creation for drafts remain exempt
  • Migrates pull-request comment, reaction, label, review, and update commands from the generic atom command hook to the source-control command hook; thread metadata commands move to the orchestration command hook
  • Server-side enforcement in ws.ts requires source-control write for clone, push, and pull-request comment RPCs, and requires orchestration operate for worktree-mode pull-request thread preparation
  • Behavioral Change: thread deletion no longer closes terminal history; worktree cleanup on deletion is only offered when session lookup reports both authentication and source-control write scope; orphaned worktrees may remain if the session lookup fails. Mutations attempted without the required scope now return EnvironmentAuthorizationError. Existing pairing configurations and connections without the new scope will find all source-control mutations disabled or rejected.

Macroscope summarized 7af76ac.

Summary by CodeRabbit

  • New Features

    • Added environment-specific permission controls for source-control changes, project creation, cloning, thread operations, branch management, commits, pull requests, and worktrees.
    • Read-only actions remain available where permitted, while unavailable controls are disabled with explanatory messages.
    • Added a separate source-control write permission for connection and pairing-link setup.
  • Bug Fixes

    • Permissions are rechecked when actions are submitted, preventing revoked access from triggering changes.
    • Failed Git operations no longer clear inputs or close dialogs prematurely.
  • Documentation

    • Clarified source-control write permissions and separate task-operation permissions for remote access.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 4, 2026
@juliusmarminge juliusmarminge changed the title t3code/auth source control scope feat(auth): separate source control write permissions Sep 4, 2026
Comment thread packages/contracts/src/auth.ts
@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 4.9 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.8 KiB — 29.3 KiB ✅
Codex Live turn messages — 1 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.2 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: 2ce5a88 · Source CI: success

Scenario and decoded snapshot size

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

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch from 7b1d2a9 to 29f2d0c Compare September 4, 2026 21:18
@juliusmarminge
juliusmarminge marked this pull request as ready for review September 4, 2026 21:20
Comment thread apps/web/src/components/GitActionsControl.tsx Outdated
Comment thread apps/web/src/hooks/useThreadActions.ts Outdated
Comment thread apps/server/src/auth/RpcAuthorization.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces and enforces a new source-control authorization scope across server RPCs, shared runtime, web, and mobile clients, including Git, cloning, worktree, and pull-request mutations. It also changes standard permission defaults, so the security-sensitive runtime and default-grant changes require human review.

Not approved because:

  • Per-PR cost limit exceeded (workspace setting). Approvability relies on correctness review in order to determine eligibility

No code changes detected at 2ce5a88. Prior analysis still applies.

Review your spending limits in Billing settings, or comment @macroscope-app review this PR to bypass the limit and review now. You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch from 29f2d0c to cfd3827 Compare September 4, 2026 21:36
@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Sep 4, 2026
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch from cfd3827 to 976c793 Compare September 4, 2026 21:38
Comment thread apps/web/src/hooks/useThreadActions.ts

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread apps/web/src/hooks/useThreadActions.ts Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch from 976c793 to 3a230f5 Compare September 4, 2026 21:48
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch 2 times, most recently from 74090e2 to 9c21ca5 Compare September 4, 2026 23:52
Comment thread apps/mobile/src/features/projects/AddProjectScreen.tsx Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch from 9c21ca5 to 7be7cbd Compare September 5, 2026 00:08
Comment thread apps/web/src/components/GitActionsControl.tsx Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch from 491dcbf to 4203d64 Compare September 5, 2026 00:24
Comment thread apps/server/src/auth/RpcAuthorization.ts Outdated
Comment thread apps/web/src/components/BranchToolbarBranchSelector.tsx
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-source-control-scope branch from 97dccdb to 40521d0 Compare September 5, 2026 02:52
juliusmarminge and others added 27 commits October 6, 2026 20:09
A failed session lookup only means worktree cleanup cannot be offered;
it no longer blocks deleting the thread. Branch actions chosen after the
grant is lost now explain the no-op, mobile refreshes the worktree state
after a denied metadata update, and the docs state that task worktrees
are created with orchestration:operate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Worktree cleanup after a deleted thread reports itself in a toast rather
than failing the deletion, so the revocation regression asserts that no
removal is requested and the user is told.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant