Skip to content

feat(auth): separate environment administration permissions - #9786

Open
juliusmarminge wants to merge 8 commits into
t3code/auth-pairing-scopesfrom
t3code/auth-environment-scopes
Open

feat(auth): separate environment administration permissions#9786
juliusmarminge wants to merge 8 commits into
t3code/auth-pairing-scopesfrom
t3code/auth-environment-scopes

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 4, 2026

Copy link
Copy Markdown
Member

Provider setup, settings changes and server maintenance all shared orchestration:operate. Parts of Connections also required access administration to configure an environment. A workspace operator could not be granted these capabilities independently.

Adds three scopes:

  • settings:write for environment settings and keybindings.
  • providers:manage for provider configuration, sign-in, installation, updates and reset credits.
  • environment:maintain for server updates, process signals, resource collector recovery and host power controls.

Settings patches require permission for every domain they change, including settings:write for model pricing overrides. Web, desktop and mobile use the selected environment's grant for controls and check it again before writes. Shared settings sync includes only writable environments. Access and relay administration remain separate, and local preferences stay editable.

New Standard and Administrative grants include these scopes. Existing paired clients keep their grants and must pair again to receive the new permissions. Reconnecting does not expand access.

Validation: 93 focused web tests and the mobile TypeScript check passed. Targeted formatting and diff checks passed. RPC tests cover individual settings/provider grants, mixed patches and denied maintenance actions.

Pairing controls, captured from this layer’s base and head with the same viewport and default selection:

Before After
Before: pairing permissions After: environment permissions

Model: GPT-6. Harness: Codex.

Note

Add settings:write, providers:manage, and environment:maintain environment scopes

  • Splits the broad orchestration:operate permission into three dedicated environment scopes across contracts, server RPC authorization, and both web/mobile clients.
  • Reclassifies server RPC required scopes in RpcAuthorization.ts: provider updates/auth/install to providers:manage, server updates/telemetry retry/process signaling/host power to environment:maintain, and keybinding/settings updates to settings:write.
  • Adds requiredScopesForServerSettingsPatch in settings.ts so mixed server-settings patches can require both settings:write and providers:manage depending on the fields present.
  • Updates web and mobile UI components to synchronously check the new scopes via useEnvironmentScope/readEnvironmentScope helpers before enabling controls and dispatching commands; unauthorized controls are disabled or inert.
  • ServerUpdateAction checks a new advertised serverUpdateScope on the auth descriptor, falling back to orchestration:operate for older servers.
  • Behavioral Change: existing pairings granted only orchestration:operate will not have the new scopes; users must re-pair to receive settings:write, providers:manage, and environment:maintain. Older servers without auth.serverUpdateScope still fall back to orchestration:operate for server updates.

Macroscope summarized 5f1623b.


Note

High Risk
Authorization behavior changes across RPC, HTTP, and all clients; legacy grants will lose access to formerly bundled operations until re-paired with new scopes.

Overview
Splits what used to ride on orchestration:operate into settings:write, providers:manage, and environment:maintain. The server maps RPCs and HTTP token scopes to these grants, serverUpdateSettings checks requiredScopesForServerSettingsPatch so mixed patches need every domain they touch, and the auth descriptor advertises serverUpdateScope for self-update.

Web, mobile, and desktop clients drop implicit admin bypasses in favor of useEnvironmentScope / readEnvironmentScope, with controls disabled and writes re-checked before mutations. Notable UX: read-only sessions can still view settings (auto-settle on mobile, T3 Connect when relay read is missing), pairing only offers scopes the current grant can delegate, and provider/server maintenance actions show explicit “cannot manage” messaging.

Existing paired clients keep their old scope sets until they pair again; orchestration:operate alone no longer covers settings, providers, or maintenance.

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Sep 4, 2026
@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 13.6 KiB 15.1 KiB
Codex Thread snapshot wire 7.0 KiB 7.3 KiB
Codex Live turn WebSocket wire 6.6 KiB 7.8 KiB
Codex Live turn WebSocket decoded 57.1 KiB 66.4 KiB
Codex Live turn messages 10 21
Claude Total thread wire 13.5 KiB 15.1 KiB
Claude Thread snapshot wire 7.0 KiB 7.3 KiB
Claude Live turn WebSocket wire 6.5 KiB 7.8 KiB
Claude Live turn WebSocket decoded 57.8 KiB 66.4 KiB
Claude Live turn messages 8 21

Baseline: unavailable · PR result: 5f1623b · 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: 113.8 KiB
  • Claude decoded thread snapshot: 114.5 KiB

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

Comment thread apps/web/src/components/settings/ProviderInstanceCard.tsx
Comment thread apps/web/src/components/settings/ConnectionsSettings.tsx
Comment thread apps/web/src/components/settings/ConnectionsSettings.tsx Outdated
Comment thread apps/web/src/hooks/useSettings.ts
@juliusmarminge juliusmarminge changed the title feat(auth): separate environment administration scopes feat(auth): separate environment administration permissions Sep 4, 2026
@juliusmarminge
juliusmarminge marked this pull request as ready for review September 4, 2026 21:20

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON, but a cloud agent failed to start.

Reviewed by Cursor Bugbot for commit ee2b738. Configure here.

Comment thread apps/mobile/src/features/settings/SettingsRouteScreen.tsx 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 is a broad, auth-sensitive permission redesign that changes default pairing grants and authorization for settings, providers, maintenance, access, relay, and process operations across server, web, and mobile. It also carries unresolved keybinding correctness risks, including a stale-edit rejection scenario and incomplete duplicate-rule removal.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarminge force-pushed the t3code/auth-environment-scopes branch from ee2b738 to 5a020b3 Compare September 4, 2026 21:36
Comment thread apps/server/src/auth/RpcAuthorization.ts
Comment thread apps/web/src/components/settings/EnvironmentIconPicker.tsx
Comment thread apps/web/src/components/settings/ConnectionsSettings.tsx
Comment thread apps/web/src/components/settings/ProviderSettingsPanel.tsx
Comment thread apps/web/src/components/settings/DiagnosticsSettings.tsx Outdated
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-environment-scopes branch from 25f5cbd to 5f1623b Compare September 4, 2026 22:59
}
if (previousTarget) {
return mapAtomCommandResult(
await removeKeybinding({ environmentId, input: previousTarget }),

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.

🟡 Medium components/ChatView.tsx:3599

Deleting a script removes only one shortcut rule, so duplicate bindings for the same command remain persisted and still dispatch the deleted script's command. previousTarget represents only the last match returned by keybindingValueForCommand; enumerate and remove every persisted rule for input.keybindingCommand instead.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/ChatView.tsx around line 3599:

Deleting a script removes only one shortcut rule, so duplicate bindings for the same command remain persisted and still dispatch the deleted script's command. `previousTarget` represents only the last match returned by `keybindingValueForCommand`; enumerate and remove every persisted rule for `input.keybindingCommand` instead.

Comment on lines +3542 to +3544
input.keybinding !== undefined &&
(input.keybinding?.trim() || null) !== previousKeybinding &&
(!isDeletingScript || readEnvironmentScope(environmentId, AuthSettingsWriteScope));

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.

🟠 High components/ChatView.tsx:3542

Editing a script without AuthSettingsWriteScope is rejected as an unauthorized keybinding change when another client changes the shortcut after the dialog opens, even though the user never edited the disabled keybinding field. changesKeybinding compares the stale dialog value with the current previousKeybinding; gate this detection on keybinding write access (while preserving the existing script update).

       const changesKeybinding =
         isElectron &&
+        readEnvironmentScope(environmentId, AuthSettingsWriteScope) &&
         input.keybinding !== undefined &&
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/ChatView.tsx around lines 3542-3544:

Editing a script without `AuthSettingsWriteScope` is rejected as an unauthorized keybinding change when another client changes the shortcut after the dialog opens, even though the user never edited the disabled keybinding field. `changesKeybinding` compares the stale dialog value with the current `previousKeybinding`; gate this detection on keybinding write access (while preserving the existing script update).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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