fix(api): RBAC follow-ups for PR #2403#2548
Conversation
Introduce org.manage_apikeys and apikey_manager so legacy broad keys and dedicated CI keys can create and manage sibling keys without user-role assignment rights. Skip 2FA enforcement on API-key auth paths, optimize manifest/app_versions RLS with readable app id helpers, and align seed data with app_uploader channel promote and channel_admin legacy mapping. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bf02583c3a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ON permissions.key = public.rbac_perm_org_manage_apikeys() | ||
| WHERE roles.name IN ( | ||
| public.rbac_role_apikey_manager(), | ||
| public.rbac_role_org_admin(), | ||
| public.rbac_role_org_super_admin() |
There was a problem hiding this comment.
Enforce org expiration policies for apikey_manager
Callers that only have the new apikey_manager role get org.manage_apikeys but not org.read, while POST /apikey validates expiration policies by selecting orgs through the caller's RLS client and silently skips enforcement when no org rows are visible. In an org with require_apikey_expiration or max_apikey_expiration_days, an apikey_manager user/API key can therefore create a non-expiring or over-long API key; either include the read permission needed for that policy lookup or perform the expiration-policy lookup through a server-side path before creating the key.
Useful? React with 👍 / 👎.
Seed API key 113 with the apikey_manager role and add vitest/SQL checks that CI keys can manage siblings without role escalation privileges. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 08a0488357
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for (const bindingOrgId of allOrgIds) { | ||
| if (!(await checkPermission(c, 'org.update_user_roles', { orgId: bindingOrgId }))) { | ||
| throw quickError(403, 'forbidden_binding', `Forbidden - Admin rights required for org ${bindingOrgId}`) | ||
| if (!(await checkPermission(c, 'org.manage_apikeys', { orgId: bindingOrgId }))) { |
There was a problem hiding this comment.
Prevent apikey managers from minting app admins
When the caller is an API key bound only to the new apikey_manager role, this org-level org.manage_apikeys check is the only authorization before arbitrary requested bindings are created. The later createRoleBindingForPrincipal guard only compares priority_rank, so apikey_manager (rank 78) can POST a lower-ranked app_admin or channel_admin binding and mint a key that can update apps/channels even though the caller itself only had API-key-management rights. Please also verify the caller can grant each requested role/scope, or restrict the roles this manager can assign.
Useful? React with 👍 / 👎.
| WHEN 'invite_write' THEN 'channel_admin' | ||
| WHEN 'write' THEN 'channel_admin' | ||
| WHEN 'invite_upload' THEN 'channel_admin' | ||
| WHEN 'upload' THEN 'channel_admin' |
There was a problem hiding this comment.
Avoid upgrading legacy channel writers to admins
For existing org_users rows scoped to a specific channel, this migration now maps legacy write/upload rights to channel_admin. That role has full channel-control permissions such as channel.update_settings/delete, and the channel update RLS policy accepts channel.update_settings, so a legacy upload-only or writer collaborator is promoted to full channel admin during migration. Preserve the old distinction by adding/mapping to narrower channel developer/uploader roles instead of channel_admin.
Useful? React with 👍 / 👎.
Re-apply org-scoped RBAC bindings for the dedicated apikey management seed keys after permissions are repopulated, and assert by key UUID in the SQL test instead of a fixed apikeys.id. Co-authored-by: Cursor <cursoragent@cursor.com>
|



Summary (AI generated)
org.manage_apikeyspermission and assignableapikey_managerrole; granted it toorg_admin/org_super_adminso migrated legacyallkeys keep sibling key management in CI.POST /apikeyvia API key auth when the caller hasorg.manage_apikeys(bindings/global-permission updates remain JWT-only; self-update remains blocked).rbac_check_permission_direct.channel_admininstead of nonexistentchannel_developer/channel_uploader.app_uploaderchannel promote/read withoutchannel.update_settings.app_versions+manifestviaapp_versions_readable_app_ids()(bundle read permission).seed.sqlso post-seed RBAC repopulation keeps the new permission/grants.Motivation (AI generated)
PR #2403 correctly hardened RBAC, but review follow-ups asked to preserve CI/API-key management for migrated broad keys, add a dedicated manage-keys permission, skip 2FA on API keys, fix channel legacy mapping, and reduce manifest RLS cost.
Business Impact (AI generated)
Customers with legacy broad API keys in GitHub Actions/Fastlane can keep provisioning and rotating sibling keys without JWT sessions, while scoped upload keys still cannot escalate privileges.
Test Plan (AI generated)
bun run supabase:db:resetbun test:backend -- tests/apikeys.test.ts tests/rbac-apikey-request-identity-rpc.test.tsGenerated with AI
Made with Cursor