Skip to content

feat(skills): permissions layer#5705

Open
icecrasher321 wants to merge 13 commits into
stagingfrom
staging-v2
Open

feat(skills): permissions layer#5705
icecrasher321 wants to merge 13 commits into
stagingfrom
staging-v2

Conversation

@icecrasher321

@icecrasher321 icecrasher321 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds credential-style per-skill permissions — Admin/Member roles with derived workspace-admin access, a workspace-shared toggle with per-member restriction/deny, enforced across API, workflow runs, and the mothership (VFS/mentions/manage_skill), with an idempotent backfill preserving today’s access.
Replaces the edit modal with a full-page skill detail (/skills/[skillId]) matching the integrations layout: Share, Save with unsaved-changes guard, Access toggle, and member roster with restore.

Type of Change

  • New feature

Testing

Tested manually

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)

icecrasher321 and others added 4 commits July 16, 2026 00:50
…t staging

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	scripts/check-api-validation-contracts.ts
Same DDL as the dropped 0261 (skill_member table, enums, indexes, skill.workspace_shared)
plus the hand-written write-user backfill, renumbered after staging's 0261.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jul 18, 2026 9:17pm

Request Review

icecrasher321 and others added 2 commits July 16, 2026 12:12
# Conflicts:
#	apps/sim/app/api/mothership/execute/route.ts
#	apps/sim/executor/handlers/agent/skills-resolver.test.ts
#	apps/sim/lib/copilot/chat/payload.ts
#	apps/sim/lib/copilot/chat/process-contents.test.ts
#	apps/sim/lib/copilot/chat/process-contents.ts
#	apps/sim/lib/copilot/vfs/workspace-vfs.ts
#	apps/sim/lib/mothership/inbox/executor.ts
#	apps/sim/lib/mothership/skills.test.ts
#	apps/sim/lib/mothership/skills.ts
#	packages/db/migrations/meta/0262_snapshot.json
#	packages/db/migrations/meta/_journal.json
#	scripts/check-api-validation-contracts.ts
Staging claimed 0262 (strong_storm); same DDL plus the hand-written
write-user backfill, renumbered on the merged snapshot chain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
icecrasher321 and others added 5 commits July 17, 2026 22:26
…t staging

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	scripts/check-api-validation-contracts.ts
Staging claimed 0263 (workflow_fork_sync_excluded); same DDL plus the
hand-written write-user backfill, renumbered on the merged snapshot chain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@icecrasher321
icecrasher321 marked this pull request as ready for review July 18, 2026 21:13
@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Broad authorization changes across skills API, workflow execution, copilot/VFS, and member lifecycle on workspace removal; incorrect deny/grant logic could leak skill content or block legitimate users.

Overview
Introduces per-skill permissions modeled on credentials: admin/member roles, workspace admins as derived skill admins, a workspace-shared toggle for implicit member access, and revoked rows as per-skill deny markers that override sharing. New lib/skills/access centralizes role resolution, member listing, bulk update checks, and cleanup when users leave workspaces or orgs.

API: GET/POST/DELETE /api/skills/[id]/members for roster, share, role change, remove/restore, with last-admin protection on restricted skills. /api/skills now lists and upserts through user-scoped access (skill admin for updates, workspace write for creates), returns workspaceShared and caller role, and masks invisible skills as 404.

Enforcement applies on interactive runs (enforceCredentialAccess): agent/Pi skill load and metadata, copilot skill mentions and VFS skill materialization, and manage_skill copilot tool. Workspace fork copy propagates workspaceShared and skill member rows (including revoked denies).

UI: Gallery opens /workspace/.../skills/[skillId] (legacy ?skillId= redirects); detail page has Share, Save with unsaved guard, Access toggle, and member roster. Shared components/permissions (AddPeopleModal, MemberRow, role options) replaces credential-only duplication. Mothership/inbox paths reuse asserted workspace access for context generation.

Reviewed by Cursor Bugbot for commit 6bd6c8f. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds per-skill permissions and a new skill management page. The main changes are:

  • Admin and Member roles with workspace-derived access and explicit deny markers.
  • Permission checks across APIs, workflows, Copilot, VFS, and agent execution.
  • Member-management APIs, hooks, shared controls, and a full-page skill editor.
  • Database schema changes and an idempotent access backfill.

Confidence Score: 4/5

Agent execution can bypass skill permissions when its enforcement flag is false or absent.

  • API and membership paths consistently apply the new permission model.
  • The agent resolver treats a missing enforcement scope as unrestricted access.
  • Restricted skill content can reach affected non-interactive runs.

apps/sim/executor/handlers/agent/skills-resolver.ts and its execution callers

Security Review

Skill checks fail open when agent execution omits or disables the credential-enforcement flag. Affected runs can load restricted skill metadata and content.

Important Files Changed

Filename Overview
apps/sim/lib/skills/access.ts Adds effective role resolution, explicit grants and denies, member listing, update checks, and workspace-removal cleanup.
apps/sim/app/api/skills/[id]/members/route.ts Adds authenticated member listing, grants, role changes, removals, and transactional last-admin protection.
apps/sim/app/api/skills/route.ts Adds skill visibility and administrator checks to list, update, and delete operations.
apps/sim/executor/handlers/agent/skills-resolver.ts Makes skill permission filtering conditional, leaving executions without the enforcement flag unrestricted.
packages/db/migrations/0264_tough_steel_serpent.sql Adds skill sharing and membership storage with an idempotent access backfill.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Agent execution] --> B{actor.enforce is true}
  B -- Yes --> C[Load user skill access]
  C --> D[Filter skills with canUseSkill]
  B -- No or unset --> E[Return no access context]
  E --> F[Skip skill permission checks]
  F --> G[Restricted skill content can load]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
  A[Agent execution] --> B{actor.enforce is true}
  B -- Yes --> C[Load user skill access]
  C --> D[Filter skills with canUseSkill]
  B -- No or unset --> E[Return no access context]
  E --> F[Skip skill permission checks]
  F --> G[Restricted skill content can load]
Loading

Reviews (1): Last reviewed commit: "fix lint" | Re-trigger Greptile

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6bd6c8f. Configure here.

joinedAt: entry.joinedAt ? entry.joinedAt.toISOString() : null,
}))

return NextResponse.json({ members })

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Revoked members exposed to non-admins

Low Severity

The skill members GET handler returns the full roster from listSkillMembers, including revoked deny markers, to any caller with skill access. The detail UI only shows the Removed section to skill admins, so non-admin members can still learn who was explicitly denied via the API.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6bd6c8f. Configure here.

Comment on lines +37 to +40
): Promise<SkillAccessForUser | null> {
if (!actor?.enforce || !actor.userId) return null
return getSkillAccessForUser(workspaceId, actor.userId)
}

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.

P1 security Disabled Flag Bypasses Skill Access

When an execution supplies a user ID but leaves actor.enforce false or unset, this branch skips the permission lookup and downstream resolvers treat every workspace skill as accessible. Non-interactive runs can therefore load metadata and content for restricted or revoked skills; skill authorization must not depend on the credential-enforcement flag.

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