Skip to content

feat!: add role bindings, groups, and audit log for RBAC - #4535

Open
kmendell wants to merge 45 commits into
breaking/v3from
feat/rbac-v3
Open

kmendell wants to merge 45 commits into
breaking/v3from
feat/rbac-v3

Conversation

@kmendell

@kmendell kmendell commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Checklist

  • This PR is not opened from my fork’s main branch
  • All new user-facing strings are translated via Paraglide (m.*())

What This PR Implements

Replaces the user role assignment RBAC with role bindings, groups, resource scopes, delegation, and an audit log.

  • Admin is now the * wildcard. Built-in roles are defined in code.
  • Role bindings replace user role assignments. A binding has a user or group subject, a global or environment scope, and an optional resource selector (labels, compose projects, owner, name globs).
  • OIDC claims map to groups (OIDC_GROUP_MAPPINGS) instead of roles.
  • Role, binding, group, and OIDC mapping changes can be delegated. Callers can only grant permissions, scopes, and selectors they hold.
  • Container, project, image, volume, network, and swarm service lists and actions filter by scope. Out-of-scope resources return 404.
  • The manager forwards caller permissions to agents in X-Arcane-Authz.
  • A new audit log records RBAC changes and permission denials, with export and a retention job.

Fixes:

Changes Made

  • Authorization: pkg/authz adds scopes, delegation, and permission forwarding. The permission catalog and built-in roles are rewritten.
  • Role bindings: new role/children/binding child. /roles/bindings replaces /users/{id}/roles.
  • Groups: new group domain with members and OIDC group sync.
  • Resource scopes: label, project, owner, and name checks in the container, project, image, volume, network, and swarm services. WebSocket log and stats streams check the same scopes.
  • Audit log: new audit domain with denial logging, export, and a retention job.
  • Migrations: 095 (bindings, groups, OIDC group mappings, and migration of the old tables), 096 (audit logs), and 097 (project owner), for SQLite and Postgres.
  • CLI: admin bindings, admin groups, admin audit, and auth me --effective. admin roles assign and admin roles assignments are removed.
  • Frontend: updated for the new role model and the generated permission constants, with new strings in frontend/messages/en.json.
  • Docs: three new pages and updated existing pages, in the website repo as a separate docs: commit.

Testing Done

  • New and updated tests cover authz, role/children/binding, group, audit, the container, project, image, volume, network, and swarm services, database, and the CLI admin commands.
  • Not run locally for this write-up. Tests and lint are left to CI.

AI Tool Used (if applicable)

Additional Context

Breaking changes

  • user_role_assignments and oidc_role_mappings migrate to role_bindings, groups, group_members, and oidc_group_mappings. Downgrade drops manual group memberships.
  • GET and PUT /users/{id}/roles are removed. Use /roles/bindings.
  • OIDC_ROLE_MAPPINGS is replaced by OIDC_GROUP_MAPPINGS (claim=GroupName).
  • A custom role holding every permission is no longer admin. Only * grants admin.
  • images:push is removed.
  • Agents must upgrade together with the manager, because of X-Arcane-Authz.
  • Arcane-created resources get the com.getarcaneapp.arcane.owner label.
  • CLI admin roles assign and admin roles assignments are replaced by admin bindings and admin groups.

Disclaimer Greptiles Reviews use AI, make sure to check over its work.

To better help train Greptile on our codebase, if the comment is useful and valid Like the comment, if its not helpful or invalid Dislike

To have Greptile Re-Review the changes, mention greptileai.

RetriggerView in GreptileConfidence Score: 5/5

The reviewed changes appear safe to merge; the migration no longer assigns users to unverified groups.

Summary

This PR replaces role assignments with bindings and groups, adds delegated access management, and records audit events.

  • Permissions now follow callers across environments and agents.
  • Users and groups receive roles through scoped bindings.
  • Arcane records RBAC changes and permission denials as audit events.
  • The frontend and CLI use bindings, groups, and effective permissions.

Reviews (31) · Last reviewed commit: "feat!: add role bindings, groups, and au..." · Reviewed by Greptile

@kmendell
kmendell requested a review from a team as a code owner October 22, 2026 02:46
@kmendell kmendell changed the title feat!: add role bindings, groups, and audit log for RBAC v3 feat!: add role bindings, groups, and audit log for RBAC Oct 22, 2026
@kmendell

kmendell commented Oct 22, 2026 •

Copy link
Copy Markdown
Member Author

⛔ Snyk checks have failed. 2 issues have been found so far.

Status Scan Engine Critical High Medium Low Total (2)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues
⛔ Code Security 0 2 0 0 2 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Comment thread frontend/src/lib/permissions.generated.ts
Comment thread frontend/src/lib/permissions.generated.ts
@graphite-app

graphite-app Bot commented Oct 22, 2026

Copy link
Copy Markdown

Graphite Automations

"Warn authors when publishing large PRs" took an action on this PR • (10/22/26)

1 teammate was notified to this PR based on Kyle Mendell's automation.

Comment thread backend/resources/migrations/sqlite/097_rbac_v3.sql Outdated
Comment thread backend/pkg/authz/forward.go Outdated
Comment thread backend/pkg/authz/catalog.go Outdated
Comment thread backend/internal/container/service.go Outdated
Comment thread backend/internal/image/handler.go Outdated
Comment thread backend/internal/auth/service.go Outdated
Comment thread backend/internal/volume/children/backup/children/restore/service.go Outdated
Comment thread frontend/src/lib/components/role-bindings/binding-sheet.svelte Outdated
Comment thread frontend/src/routes/(app)/settings/groups/[id]/+page.ts Outdated
Comment thread backend/api/api.go Outdated
Comment thread backend/internal/settings/handler.go Outdated
Comment thread backend/pkg/authz/context.go
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread backend/internal/federated/module.go
Comment thread frontend/src/lib/services/group-service.ts Outdated
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread backend/internal/federated/module.go
Comment thread backend/pkg/authz/permission_set.go Outdated
Comment thread backend/resources/migrations/sqlite/100_rbac_v3.sql Outdated
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread backend/pkg/authz/permission_set.go
Comment thread backend/internal/container/service.go Outdated
Comment thread backend/internal/group/service.go Outdated
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread backend/pkg/authz/permission_set.go Outdated
Comment thread backend/internal/role/children/binding/service.go Outdated
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread backend/pkg/authz/catalog.go Outdated
Comment thread backend/internal/group/service.go
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread backend/pkg/projects/custom_labels.go Outdated
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread backend/internal/volume/children/backup/children/policies/service.go Outdated
Comment thread frontend/src/lib/components/role-editor/permission-picker.svelte
Comment thread backend/internal/group/service.go Outdated
@kmendell

Copy link
Copy Markdown
Member Author

@greptileai review

- Replace gradient icon circles with a shared compact status banner
- Show current and latest image versions as diff rows with copyable digests
- Show auth method and last-check time in a meta line
- Widen the image update popover to xl
- Add image_update_checked_at and remove unused update message keys
- Fail a running upgrade job on startup when the manager version or digest changed outside the job
- Run the manager self-upgrade trigger in the background and return pending_restart from the flow task
- Move digest-pinned names that the containerd image store returns in RepoTags into RepoDigests
- Apply the split to both the image list and image detail responses
- Document RepoTags as tag references only in types/image.go
- Remove horizontal padding from the settings page wrapper
- Reduce top padding to pt-3, increasing to md:pt-5
- Keep responsive bottom padding (pb-5, sm:pb-10)
- Page image vulnerability scan items in SQL, backed by new index migration 097
- Build project status and pending update counts from one container snapshot
- Fetch containers and networks concurrently in the network list
- Route read-only transactions to the SQLite reader pool
- Exclude projects that already have a backup sync from the backup project list (edit mode keeps all projects)
- Auto-select the only repository, and the only branch when the default is missing
- Submit the selected repository and project IDs with the form
- Environment score moves 60% of the way from the image average toward the riskiest image
- Known-exploited floor rises 4 per running image with a fixable KEV, adds 10 once one is past its CISA due date, capped at 95
- Risk snapshots store peak score and per-image exploited counts; migration 098 replaces exploited_running
- Bump scoring version to 4
- Remove the separate types module release workflow and just recipe; release.yml now tags types/ alongside the other modules
- Wait up to DefaultTunnelAcquireTimeout for an active tunnel before reporting the agent offline
- Redial a dropped healthy session after 100-250ms of jitter instead of the full backoff
- Enable HTTP/2 send and ping timeouts on the manager server to detect dead peers
- Raise yamux max frame size to 1 MiB and extend idle timeouts to reduce tunnel churn
- Serve notification settings at /api/notifications/settings instead of /api/environments/{id}/notifications/settings
- Route notification test sends through the manager's local target; agents no longer proxy these endpoints
- Move the providers UI from the environment page to Settings > Notifications, gated by notifications:manage
- Drop the environment argument from the CLI admin notifications commands and clitypes helpers
- Replace per-user role assignments with role bindings and add group membership
- Record audit entries for API key create, update, and delete
- Gate container, project, and service log WebSockets on their read permissions
- Scope the containers stats stream per subject when the caller is not unrestricted
- Require the diagnostics permission for pprof instead of the admin-only gate
- Add a hidden `permissions-ts` command that generates the frontend permission constants
@kmendell
kmendell force-pushed the breaking/v3 branch 4 times, most recently from 81d1074 to ecd7562 Compare October 29, 2026 00:58

This branch has not been deployed

No deployments
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