Skip to content

feat(credential-groups): add resource access policies - #6892

Open
TheodoreSpeaks wants to merge 5 commits into
feat/workspace-principalfrom
feat/credential-group-resource-policies
Open

feat(credential-groups): add resource access policies#6892
TheodoreSpeaks wants to merge 5 commits into
feat/workspace-principalfrom
feat/credential-group-resource-policies

Conversation

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator

Summary

  • Add versioned allow-only resource policies for Credential Groups
  • Keep actor-only credential access as the built-in default
  • Let admins grant all-credential access to deployed workflows, workspace roles, and Access Control Groups
  • Add an Access UI for managing explicit grants
  • Preserve deployment authority through nested workflow execution

Stacked on #6891.

Type of Change

  • New feature

Testing

  • 159 focused Credential Group and resource-policy tests
  • Sim and database TypeScript checks
  • bun run lint
  • bun run check:audits
  • bun run check:migrations origin/staging
  • Block registry stability check

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)

Screenshots/Videos

Not included.

@vercel

vercel Bot commented Aug 20, 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 Aug 21, 2026 5:15am

Request Review

@cursor

cursor Bot commented Aug 20, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Touches credential-use authorization, internal delegation tokens, and nested workflow identity. Incorrect grant matching or stale deployment binding could leak managed OAuth credentials.

Overview
Admins can grant whole-group credential use on Credential Groups via allow-only resource policies, while actor-only enrollment access remains the default.

Adds a generic resource_policy store, evaluator, and optimistic admin API. Grants can target deployed workflows, workspace roles, Access Control Groups, users, or external identities. The HTTP/UI surface only accepts subjects (not caller-supplied effects/actions); stored grants always mean credential_groups.credentials.use.

Internal executor delegation now carries current workflow authority (draft vs active deploymentVersionId) separately from the root run, so workflow grants match only the currently executing deployed version. Nested child runs and the deployed-state API require that version id.

Settings gain an Access tab to add/remove those grants with revision-based updates.

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

@TheodoreSpeaks
TheodoreSpeaks force-pushed the feat/credential-group-resource-policies branch from 9995853 to 0c9fb23 Compare August 20, 2026 18:12
@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds versioned allow-only access policies for Credential Groups and propagates deployed-workflow authority through nested execution.

  • Adds policy persistence, optimistic revisions, contracts, management operations, and admin access APIs.
  • Adds an Access settings tab for workflow, workspace-role, and Access Control Group grants.
  • Carries current workflow and deployment-version authority through internal delegation and nested workflow execution.
  • Adds focused authorization, persistence, route, contract, and executor tests.

Confidence Score: 5/5

The PR appears safe to merge because no eligible blocking failure remains in the follow-up review.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/sim/lib/resource-policies/authorization.ts Evaluates allow-only policy subjects against canonical workspace and delegated workflow execution context.
apps/sim/lib/resource-policies/repository.ts Persists one policy per resource using atomic optimistic-revision inserts and updates.
apps/sim/lib/credential-groups/application/manage-access.ts Adds authorized read and replacement-update operations for Credential Group access grants.
apps/sim/lib/auth/internal-delegation.ts Binds delegated current-workflow authority to canonical workspace and deployment state.
apps/sim/executor/handlers/workflow/workflow-handler.ts Propagates draft or deployed child-workflow authority through nested execution.
apps/sim/ee/credential-groups/components/credential-group-access.tsx Adds the administrative UI for listing, adding, and removing explicit access grants.
packages/db/migrations/0298_sparkling_hemingway.sql Introduces resource-policy persistence and uniqueness constraints aligned with the schema.

Sequence Diagram

sequenceDiagram
  participant Admin as Workspace Admin
  participant API as Credential Group Access API
  participant Policy as Resource Policy Store
  participant Exec as Workflow Executor
  participant Auth as Delegation Binding
  participant Cred as Credential Resolver

  Admin->>API: PUT explicit grants + expected revision
  API->>Policy: Validate subjects and replace policy
  Policy-->>API: New revision and grants
  Exec->>Auth: Delegated principal + current workflow authority
  Auth->>Auth: Bind workspace and deployment version
  Exec->>Cred: Request managed credential
  Cred->>Policy: Evaluate actor default and explicit grants
  Policy-->>Cred: Allow or deny credential use
Loading

Reviews (3): Last reviewed commit: "test(resource-policies): cover actor gra..." | Re-trigger Greptile

? workflows.isPending
: subjectType === 'access_control_group'
? permissionConfig.isPending || permissionGroups.isPending
: false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ACG dropdown stays loading without org

Medium Severity

targetOptionsPending treats permissionGroups.isPending as loading, but usePermissionGroups stays disabled when organizationId is missing. In TanStack Query v5 a disabled query with no data remains isPending forever, so Access Control Group mode keeps a disabled “Loading access control groups...” field after config has loaded for a workspace with no organization instead of showing an empty state.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit eebc37f. Configure here.

@TheodoreSpeaks
TheodoreSpeaks force-pushed the feat/credential-group-resource-policies branch from aaea6ae to 52e3168 Compare August 21, 2026 00:17
@TheodoreSpeaks
TheodoreSpeaks force-pushed the feat/credential-group-resource-policies branch 2 times, most recently from 95eafd9 to 9d5f513 Compare August 21, 2026 01:41
@TheodoreSpeaks
TheodoreSpeaks force-pushed the feat/credential-group-resource-policies branch 2 times, most recently from c2d891e to 64f547f Compare August 21, 2026 01:53
ALTER TABLE "resource_policy" ADD CONSTRAINT "resource_policy_created_by_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "resource_policy" ADD CONSTRAINT "resource_policy_updated_by_user_id_fk" FOREIGN KEY ("updated_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "resource_policy_resource_unique" ON "resource_policy" USING btree ("resource_type","resource_id");--> statement-breakpoint
CREATE INDEX "resource_policy_workspace_id_idx" ON "resource_policy" USING btree ("workspace_id");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Orphan policies after group delete

Low Severity

Deleting a Credential Group removes the group row but leaves any resource_policy for that group. There is no foreign key from resource_policy.resource_id to credential_group, and deleteCredentialGroupSettings never deletes the policy, so access documents become permanent orphans after delete.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 64f547f. Configure here.

throw new OrchestrationError('conflict', error.message)
}
throw error
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicate grants become server errors

Low Severity

updateCredentialGroupAccessBodySchema accepts duplicate subjects or grant ids, and only parseResourcePolicyDocument rejects them later. That failure is a raw Zod/Error rather than an OrchestrationError, so the access route maps it to a generic 500 instead of a validation response.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 64f547f. Configure here.

@TheodoreSpeaks
TheodoreSpeaks force-pushed the feat/credential-group-resource-policies branch from 64f547f to eccb03a Compare August 21, 2026 04:47
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

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

✅ Bugbot reviewed your changes and found no new issues!

3 issues from previous reviews remain unresolved.

Fix All in Cursor

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit eccb03a. Configure here.

@TheodoreSpeaks
TheodoreSpeaks force-pushed the feat/credential-group-resource-policies branch from eccb03a to ede2aba Compare August 21, 2026 05:07
@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@greptile

@TheodoreSpeaks

Copy link
Copy Markdown
Collaborator Author

@cursor review

@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 high effort and found 2 potential issues.

There are 5 total unresolved issues (including 3 from previous reviews).

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 ede2aba. Configure here.

queryClient.invalidateQueries({
queryKey: credentialGroupKeys.access(variables.workspaceId, variables.groupId),
}),
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale revision on rapid access edits

Medium Severity

useUpdateCredentialGroupAccess only invalidates the access query after settle and never writes the mutation response into the cache. saveGrants keeps sending expectedRevision from the last fetched policy, so a second remove or add that starts before refetch finishes uses a stale revision and hits a conflict even though the first save succeeded.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ede2aba. Configure here.

)
.max(100),
})
.strict()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicate grants return server error

Low Severity

updateCredentialGroupAccessBodySchema accepts duplicate subjects, while parseResourcePolicyDocument later rejects them. That failure is a plain Zod error rather than an orchestration validation error, so the access route surfaces it as an unhandled 500 instead of a client-visible 400.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ede2aba. Configure here.

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