Skip to content

[codex] Fix API key rights editing#2391

Merged
riderx merged 5 commits into
mainfrom
codex/fix-apikey-rights-edit
Jun 3, 2026
Merged

[codex] Fix API key rights editing#2391
riderx merged 5 commits into
mainfrom
codex/fix-apikey-rights-edit

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented Jun 2, 2026

Summary (AI generated)

  • Added API key rights editing to the API Keys page edit flow.
  • Extended PUT /apikey to validate and replace API key RBAC bindings atomically.
  • Added backend and Playwright coverage for editing API key role bindings.
  • Included the requested screenshot of the edit-rights modal.

API key edit rights modal

Motivation (AI generated)

API key edit actions only supported name and expiration updates, so users could create API keys with rights but could not later adjust those rights from the API Keys page. The frontend now opens the same rights controls for editing, and the backend now safely replaces bindings after checking the caller can manage all affected organizations.

Business Impact (AI generated)

This restores expected API key management for customers and reduces support friction when teams need to rotate or tighten API key access without deleting and recreating keys.

Test Plan (AI generated)

  • bun lint
  • bun lint:backend
  • bun typecheck
  • bun run supabase:with-env -- bunx vitest run tests/apikeys.test.ts -t "updates api key role bindings"
  • bun run test:front -- playwright/e2e/apikeys.spec.ts
  • bun run test:front -- playwright/e2e/__tmp_apikey_screenshot.spec.ts for the PR screenshot capture, then removed the temporary spec before commit.

Generated with AI

Summary by CodeRabbit

  • New Features

    • Edit existing API keys via a unified dialog; change name, expiration, organization role scopes, and application bindings with immediate UI updates.
  • Backend

    • API now accepts and applies binding updates in PUT requests, enforcing permissions and returning clear conflict/errors.
  • Tests

    • Added e2e and integration tests verifying API key edit flows and persistence.
  • Localization

    • Added English labels: "Edit" and "Edit API key".

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Warning

Review limit reached

@riderx, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 1 minute and 2 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c95d0a66-00d4-4561-9ad2-24860cd275d4

📥 Commits

Reviewing files that changed from the base of the PR and between 364c188 and 63ddad8.

📒 Files selected for processing (2)
  • playwright/e2e/apikeys.spec.ts
  • src/pages/ApiKeys.vue
📝 Walkthrough

Walkthrough

Backend PUT now accepts optional RBAC binding updates and can transactionally replace an API key’s role_bindings with permission checks; frontend adds an edit workflow and unified modal that hydrates bindings via a shared builder; tests and i18n keys added; route typing extended.

Changes

API Key Edit Feature

Layer / File(s) Summary
Backend API key binding update logic
supabase/functions/_backend/public/apikey/put.ts
Parses optional bindings in PUT, validates and enriches bindings, implements replaceApiKeyBindings() to atomically replace role_bindings with per-org permission checks, adjusts expiration/field validation, and maps conflicts/errors.
Frontend form types and binding helpers
src/pages/ApiKeys.vue
Adds ApiKeyBindingInput type, editingApiKey and per-org role state, imports nextTick, refactors binding construction into buildApiKeyBindingsFromForm(), and makes create flow use the helper.
Edit workflow: load, populate, validate, update
src/pages/ApiKeys.vue
Wires Edit row action to editApiKey() to hydrate modal state (excluding system org-reader), implements updateApiKey() to validate selections and submit PUT with bindings, updates in-memory keys and name caches, and adjusts watchers for edit hydration.
Dialog handling and template consolidation
src/pages/ApiKeys.vue
Unifies add and edit modal teleport content, adds showAddNewKeyModal() / showEditKeyModal() helpers, hides secure-hashed checkbox while editing, and removes the standalone change-name modal.
Tests and localization
messages/en.json, playwright/e2e/apikeys.spec.ts, tests/apikeys.test.ts
Adds i18n keys for "Edit" and "Edit API key", a Playwright E2E test that edits a key's rights and asserts UI updates and toast, and a server-side test that verifies PUT replaces role_bindings in the database.
Route type definitions update
src/route-map.d.ts
Replaces TypesConfig.ParamParsers with _ParamParsers and extends _RouteFileInfoMap entries with pathParamNames (literal unions or never).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Cap-go/capgo#2332: Prior RBAC-focused refactor of src/pages/ApiKeys.vue and binding construction that this change builds upon.

Suggested labels

codex

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description includes a summary, motivation, business impact, test plan with specific commands executed, and a screenshot demonstrating the feature. However, the description template requires checklist items to be explicitly checked off, which are missing from the provided description. Complete the checklist section by checking off applicable boxes (code style, documentation updates, E2E test coverage, manual testing steps) to fully align with the template requirements.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main change: adding API key rights editing functionality. It is concise, specific, and directly relates to the primary objective of the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented Jun 2, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing codex/fix-apikey-rights-edit (63ddad8) with main (f8d3328)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@riderx riderx marked this pull request as ready for review June 2, 2026 14:54
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai coderabbitai Bot added the codex label Jun 2, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
supabase/functions/_backend/public/apikey/put.ts (1)

301-321: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Make the PUT path atomic across metadata and binding changes.

Lines 301-321 commit updateData before replaceApiKeyBindings() does its permission checks and transactional rewrite. If the binding step later fails or returns 403, the request errors but the name/expiration change is already persisted. Move the apikeys row update into the same pg transaction as the binding replacement, or pre-validate all binding auth before updating the row.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/public/apikey/put.ts` around lines 301 - 321, The
update currently writes updateData via supabase.from('apikeys').update(...)
before calling replaceApiKeyBindings(...), which can leave metadata changes
persisted if binding replacement fails; fix by making the metadata update and
binding replacements atomic: either move the apikeys update into the same
Postgres transaction used by replaceApiKeyBindings (extend replaceApiKeyBindings
to accept a transaction/pg client and perform the .update(...) inside that
transaction), or pre-validate binding permissions by reusing the same checks
replaceApiKeyBindings uses (call its permission/validation logic first) and only
then call supabase.from('apikeys').update(...); ensure you use existingApikey.id
and auth.userId for the update and propagate any errors back as quickError on
failure.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/ApiKeys.vue`:
- Around line 996-1021: The buildApiKeyBindingsFromForm function currently
applies a single selectedOrgRole to every org in selectedOrgsForCreation, which
overwrites per-org roles (see editableOrgBindings usage elsewhere); fix by
detecting mixed org roles and either (A) prevent/save by blocking edits when
editableOrgBindings contains more than one distinct role (show a
validation/error and disable save), or (B) change the form state to model org
role per org (replace selectedOrgRole with a mapping like selectedOrgRolesById
and use that mapping when building bindings) so buildApiKeyBindingsFromForm
pushes the correct role_name for each org instead of reusing one role for all.

In `@tests/apikeys.test.ts`:
- Around line 296-337: Wrap the API key creation, update and assertions in a
try/finally block so the cleanup DELETE call always runs: after creating the key
(createResponse/createData from the POST to /apikey) perform the update and all
expects inside try, and move the final fetch DELETE call that uses createData.id
into the finally block; ensure you still assert status codes and supabase checks
(getSupabaseClient().from('role_bindings') etc.) inside the try, and change the
test declaration to use it.concurrent(...) so the test is safe to run in
parallel.

---

Outside diff comments:
In `@supabase/functions/_backend/public/apikey/put.ts`:
- Around line 301-321: The update currently writes updateData via
supabase.from('apikeys').update(...) before calling replaceApiKeyBindings(...),
which can leave metadata changes persisted if binding replacement fails; fix by
making the metadata update and binding replacements atomic: either move the
apikeys update into the same Postgres transaction used by replaceApiKeyBindings
(extend replaceApiKeyBindings to accept a transaction/pg client and perform the
.update(...) inside that transaction), or pre-validate binding permissions by
reusing the same checks replaceApiKeyBindings uses (call its
permission/validation logic first) and only then call
supabase.from('apikeys').update(...); ensure you use existingApikey.id and
auth.userId for the update and propagate any errors back as quickError on
failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7f817b59-4279-4c59-8ef3-9c8447c61366

📥 Commits

Reviewing files that changed from the base of the PR and between ff7ce3e and 8620fa9.

⛔ Files ignored due to path filters (1)
  • .github/pr-screenshots/apikey-edit-rights.png is excluded by !**/*.png
📒 Files selected for processing (6)
  • messages/en.json
  • playwright/e2e/apikeys.spec.ts
  • src/pages/ApiKeys.vue
  • src/route-map.d.ts
  • supabase/functions/_backend/public/apikey/put.ts
  • tests/apikeys.test.ts

Comment thread src/pages/ApiKeys.vue
Comment thread tests/apikeys.test.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/public/apikey/put.ts`:
- Around line 327-347: When bindings are updated but other fields are not,
updatedApikey remains the partial existingApikey; change the logic so that after
calling replaceApiKeyBindings (when hasBindingUpdates is true) you always
re-fetch the apikey row from supabase (same query used in the hasUpdates branch)
and assign it to updatedApikey, instead of only doing that when hasUpdates is
true—use the existing supabase .from('apikeys').select().eq('id',
existingApikey.id).eq('user_id', auth.userId').single() flow and preserve the
existing error handling (quickError) so the response contains the full apikey
fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 01912d52-b536-46da-b97f-02f390a9ae10

📥 Commits

Reviewing files that changed from the base of the PR and between 8620fa9 and aad5f81.

📒 Files selected for processing (3)
  • src/pages/ApiKeys.vue
  • supabase/functions/_backend/public/apikey/put.ts
  • tests/apikeys.test.ts

Comment thread supabase/functions/_backend/public/apikey/put.ts
…ts-edit

# Conflicts:
#	playwright/e2e/apikeys.spec.ts
#	src/pages/ApiKeys.vue
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 2, 2026

@riderx riderx merged commit 4ac1f9a into main Jun 3, 2026
42 checks passed
@riderx riderx deleted the codex/fix-apikey-rights-edit branch June 3, 2026 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant