improvement(access-control): wire tool and model permissions into copilot editing - #7080
Conversation
…ilot editing Permission groups already supported a per-tool denylist (deniedTools) and model restrictions, but only the canvas honored them. The copilot edit path gated on block type alone, so Sim could build workflows using tools and models the user was not allowed to run — the executor refused them at run time instead. Enforce both at authoring time, and stop advertising what the viewer cannot use.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Greptile SummaryThe PR applies workspace tool and model permissions consistently across Copilot editing and capability discovery.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/permission-groups/model-access.ts | Defines the shared model gate and now follows the required absolute-import convention. |
| apps/sim/lib/permission-groups/operation-access.ts | Centralizes normalized tool permission decisions for editing, execution, and discovery. |
| apps/sim/lib/copilot/integration-tool-projection.ts | Projects integration tools through deployment, integration, and per-tool permission gates. |
| apps/sim/lib/copilot/chat/payload.ts | Uses the shared projection and keys schema caching by the effective permission policy. |
| apps/sim/lib/workflows/editing/operations.ts | Wires tool and model permission checks into workflow-edit operations. |
| apps/sim/lib/workflows/editing/builders.ts | Filters disallowed tool and model values while constructing edited blocks. |
| apps/sim/lib/copilot/vfs/serializers.ts | Restricts serialized Copilot metadata to operations available to the viewer. |
| apps/sim/lib/copilot/tools/server/blocks/get-blocks-metadata-tool.ts | Applies permission-aware integration and operation projection to block metadata. |
| apps/docs/openapi-v2-workflows.json | Adds the model-not-allowed skipped-item reason to the generated workflow API schema. |
| packages/sim-cli/src/generated/v2-api.ts | Synchronizes the generated CLI types with the updated skipped-item contract. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Permission-group config] --> B[Shared tool and model gates]
B --> C[Copilot discovery projection]
B --> D[Workflow edit validation]
C --> E[VFS and metadata]
C --> F[Integration tool schemas]
D --> G[Persisted permitted workflow]
D --> H[Skipped-item response]
Reviews (4): Last reviewed commit: "fix(access-control): key the copilot sch..." | Re-trigger Greptile
|
On the deferred schema cache ( The cache key is Three things make that acceptable:
If we want the window closed, the right fix is caching |
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
The VFS stamped every integration schema from the shared static map before the per-viewer loop re-authored the permitted subset, so a denied operation's schema stayed published. Skip the shared copy for integration paths; the viewer loop is the only projection that knows the denylist. Block metadata resolved denied operations from the catalog's `operation.toolId`, which the projection fills only from `tools.config.tool` — a block whose operation ids are its tool ids left it undefined and read as fully permitted. Resolve through the shared operation gate instead.
The deferred integration-tool schemas now depend on the viewer's permission group, but the cache key encoded only identity and block visibility, so an admin's change to deniedTools took effect only when the entry expired. Resolve the config before the key and add a gate signature alongside the existing visibility signature, mirroring how block visibility already keys the same cache. The read moves out of the cached section rather than being added: what the entry caches is a user-tool schema per exposed integration tool, which dominates it.
|
Reconsidered the schema-cache point and fixed it in 9438339 — my earlier reasoning was wrong on the cost. I had argued that keying on policy would mean a DB read per payload build, defeating the cache. That mis-weighed what the cache is actually for: the expensive part of the entry is a user-tool schema built per exposed integration tool, not the permission lookup. Moving the config read out of the cached section and in front of the key keeps essentially all of the benefit, and the file already establishes exactly this pattern — So the key now carries an Added a test that denies a tool between two builds for the same viewer and surface, so only the policy component of the key can force the rebuild — verified it fails when that component is removed. |
Summary
deniedTools) and model restrictions, but only the canvas honored them — the copilot edit path gated on block type alone, so Sim could build workflows using tools and models the user is not allowed to run. The executor refused them at run time instead, so the workflow died on first run.list_integration_tools, the deferred callable-tool payload, andget_blocks_metadata— behind one sharedprojectIntegrationToolsForViewer.filterExposedIntegrationToolsnow requires both gates so a new surface cannot apply a partial one.createToolAccessGate/createModelAccessGateas the single place a denylist becomes a decision, shared by the client hook and every server path so the two cannot drift on what a tool id means.model_not_allowedskipped-item type; regenerated the v2 OpenAPI spec and CLI API.No behavior change for a workspace without a permission group: both gates return a shared allow-all singleton, the denied-operation pass is skipped, and the VFS hands through its process-global schema cache untouched.
Type of Change
Testing
Tested manually. 21 new tests, each verified to fail when its gate is disabled. Full suite green (28,583 passing),
bun run lintclean, all 33 audits pass includingcheck:api-validation:strict,check:client-boundary, andcheck:openapi.Checklist