Skip to content

fix(selectors): rebind Copilot principals for nested domain use cases - #8397

Merged
icecrasher321 merged 2 commits into
stagingfrom
rvt-sandbox-to-uat-push-error
Sep 29, 2026
Merged

icecrasher321 merged 2 commits into
stagingfrom
rvt-sandbox-to-uat-push-error

Conversation

@icecrasher321

Copy link
Copy Markdown
Collaborator

Summary

Chat reported 404 "Workspace not found" when previewing a fork push or pull (sim workspaces push-preview / pull-preview), even though the user was an admin of both workspaces and direct reads of each succeeded.

Root cause: the fork sync preview re-validates saved dependent values (for example a Table block's conflict column or a Knowledge block's document) through selectors. Selectors backed by another domain (knowledge.documents, table.columns, table.outputColumns, sim.workflows, workspace.sandboxes, mcp.tools) forwarded the Copilot principal, admitted under the sim:selectors audience, straight into use cases that only accept their own audience (sim:knowledge, sim:tables, ...). The refusal is a DelegatedWorkspaceAuthorizationError, which the v2 surface conceals as a 404, so Chat saw a missing workspace. Session callers (the in-app sync view) were unaffected. The same bug broke those pickers for Chat everywhere (sim selectors list), not just in fork previews.

Fix:

  • bindCopilotWorkspaceOperation (the existing nested-operation helper used by workflow lint and tool inspection) can now also project the single resource a nested call reaches onto the derived principal. This matches how the executor and Chat MCP paths already mint ({ credentialId } for a managed connection, { mcpServerId } for a shared server). It only adds scope: a grant already narrowed to one resource is never moved to another.
  • New nestedSelectorPrincipal in lib/selectors/server/types.ts wraps it with the selector source audience (SELECTOR_DELEGATION_AUDIENCE, now a named constant). Every internal and MCP selector that calls another domain's use case goes through it. Session-only selectors are unchanged.
  • Managed MCP connections: the mcp.tools managed branch now names the connection, so Chat reaches the credential-group rule. That rule deliberately denies Chat on credentials without an OAuth binding (pinned in credential-groups/application/authorization.test.ts), so the result is now its honest 403 "Credential Group credential access denied" instead of the concealed 404. This PR does not change that policy.

Type of Change

  • Bug fix

Testing

  • fork-sync.integration.ts: new scenario drives a push preview through the same in-process CLI transport Chat uses (createScopedCliTransport + withWorkspaceInvocationScope), with a mapped table and a saved conflict-column value. Before the fix it returns {"error":{"code":"NOT_FOUND","message":"Workspace not found"}}; with the fix it returns 200 with the field validated against the destination.
  • selectors/__integration__/copilot-nested-selectors.integration.ts: POST /api/v2/selectors/list for mcp.tools on a real managed MCP connection through the Chat transport. Before the fix it returns 404 "Selector scope not found"; with the fix it returns the credential-group 403.
  • copilot-workspace-invocation.test.ts: a grant scoped to one credential cannot be re-bound to another (security boundary).
  • Each guard was reverted separately to confirm its test goes red: the table rebinding (404 again), the managed connection scope (404 again), and the scope-conflict check (the unit test no longer throws).
  • bun run type-check, bun run check:audits, Biome, and unit tests across lib/core/application, lib/selectors, lib/workflows, lib/mcp, lib/credentials, lib/credential-groups, ee/workspace-forking and lib/mothership/agent-cli all pass. (One agent-cli/services.test.ts case timed out at 10s under full parallel load and passes in isolation. It covers list_workspaces, not selectors.)

Reviewers: the security-relevant piece is narrowResourceScope in lib/core/application/copilot-workspace-invocation.ts.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

🤖 Generated with Claude Code

Selectors backed by another domain (knowledge documents, table columns,
workflows, sandboxes, MCP tools) forwarded the Copilot principal admitted
under the selector audience into use cases that accept only their own
audience. The refusal is a DelegatedWorkspaceAuthorizationError, which the
v2 surface conceals as 404, so Chat saw "Workspace not found" on workspaces
the user administers. Fork sync previews hit it whenever a saved dependent
value (a table conflict column, a knowledge document) needed validation.

Selectors now rebind through bindCopilotWorkspaceOperation, which can also
project the single resource a nested call reaches, as the executor and Chat
MCP paths do when they mint. A grant already narrowed to one resource is
never moved to another. Managed MCP connections now reach their
credential-group rule and return its 403 instead of the concealed 404.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Sep 29, 2026 2:44am UTC

Request Review

@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[High risk] Rebinds Copilot principals across nested domain operations.

The PR appears safe to merge; no outstanding findings or new actionable issues were identified.

Summary

The PR rebinds admitted Copilot selector calls to the audience of the domain they read, and names the target resource for table and MCP reads. It adds regression coverage for fork push previews, managed MCP selection, and conflicting resource scopes.

  • Session principals continue through unchanged.
  • Managed MCP selection now reaches the credential-group authorization decision rather than failing at the audience boundary.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  C[Copilot CLI request] --> S[Selector admission]
  S --> N[Bind nested audience and target resource]
  N --> A[Owning domain authorization]
  A --> R[Selector result or refusal]
Loading

Reviews (2) · Last reviewed commit: "fix(selectors): scope table selector rea..."

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 9 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/sim/lib/selectors/server/internal.ts Outdated
Tables honor resourceScope.tableId, so the nested read names the table it
reads, as the MCP selector names its server or connection.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

@greptile

@icecrasher321

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@icecrasher321 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai 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.

No issues found across 9 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@icecrasher321
icecrasher321 merged commit 46e9b5b into staging Sep 29, 2026
32 checks passed
@icecrasher321
icecrasher321 deleted the rvt-sandbox-to-uat-push-error branch September 29, 2026 02:56

This branch was previously deployed

1 inactive deployment
Preview — a0ba9134 Deployed Sep 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant