Skip to content

feat(auth-keys): rename a label across all keys - #94

Draft
weselben wants to merge 1 commit into
mainfrom
feat/api-key-label-rename
Draft

feat(auth-keys): rename a label across all keys#94
weselben wants to merge 1 commit into
mainfrom
feat/api-key-label-rename

Conversation

@weselben

@weselben weselben commented Sep 8, 2026

Copy link
Copy Markdown
Owner

TL;DR

Renaming a label meant editing every API key that carries it, one by one —
tedious and error-prone with many keys. A new PUT /admin/auth-keys/labels/rename
endpoint renames one label on every in-scope key in one call, and the dashboard
API Keys page gains a Label Management section with per-label key counts and a
rename dialog.

Files to review (14, +524 / -0):

File Why
internal/admin/handler_authkeys.go (start here) RenameAuthKeyLabel handler: scope filter, exact label match, per-key UpdateLabels reuse.
internal/admin/handler_authkeys_test.go Tests: global rename, scoped isolation, merge with existing label, input validation, 503.
internal/admin/routes.go Route registration: PUT /admin/auth-keys/labels/rename.
internal/admin/routes_test.go Route list updated.
web/dashboard/src/pages/auth-keys/AuthKeyLabelManager.svelte (new) Label Management section: label chips with key counts and rename buttons.
web/dashboard/src/pages/auth-keys/AuthKeyLabelRenameDialog.svelte (new) Rename dialog showing the affected key count.
web/dashboard/src/pages/auth-keys/authKeys.svelte.js labelRename state and the submit action calling the new endpoint.
web/dashboard/src/pages/auth-keys/authKeysLogic.js distinctAuthKeyLabels pure function.
web/dashboard/src/pages/auth-keys/AuthKeysPage.svelte Mounts the section and dialog.
web/dashboard/messages/{en,de,pl,zh-CN}.json New strings for all four locales.
web/dashboard/tests/auth-keys.test.js Unit tests for distinctAuthKeyLabels.

How

  • The handler lists cached key views, skips keys outside the caller's scope,
    and replaces the exact label match via the existing per-key UpdateLabels
    service path. No store interface change.
  • Renaming onto a label a key already has merges the two (de-duplicated).
    Key material, authentication, and key validity never change — labels are
    metadata only.
  • from == to and empty values return 400. A label with no matches returns
    renamed: 0, not an error.

Reviewer notes

  • Scope behavior: scoped credentials rename only inside their subtree, matching the per-key label endpoints.
  • Concurrency: a key deleted between listing and updating is skipped, not counted.
  • API shape: PUT /admin/auth-keys/labels/rename body {"from": "team-a", "to": "team-b"}{"from": "...", "to": "...", "renamed": 3}.
  • Focus area: scope filtering in RenameAuthKeyLabel — reuse of the per-key update path is deliberate.

Tests

  • go test ./... — all packages pass, including the new handler tests.
  • make test-dashboard — 643 pass (new distinctAuthKeyLabels tests included).
  • Not covered: cross-database store behavior (handler reuses the existing, already-tested per-key update path).

This PR description was generated with AI assistance.

Add PUT /admin/auth-keys/labels/rename, which renames one label on every
in-scope key that carries it (merging with an existing label), plus a Label
Management section on the dashboard API Keys page with per-label key counts
and a rename dialog. Labels are metadata only: key material, authentication,
and key validity are never touched.
@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@weselben weselben left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Review of feat(auth-keys): rename a label across all keys.

Hard-rule validation passed. go test ./... green, make test-dashboard green (643), svelte-check clean.

Findings: 0 red, 2 yellow, 1 blue. The two yellow items are inline.

  • 🔵 docs: docs/features/labelling.mdx documents create and edit of API key labels only. The new mass-rename section and the PUT /admin/auth-keys/labels/rename endpoint are missing there and from the endpoint list in docs/advanced/admin-endpoints.mdx. Add a rename section.

Verdict is yours — this is a comment-only review.

scope := requestScope(c)
ctx := c.Request().Context()
renamed := 0
for _, view := range h.authKeys.ListViews() {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🟡 risk: TOCTOU between the ListViews() snapshot and the full-replace UpdateLabels. A concurrent per-key label edit that lands in that window is silently overwritten. Same shape as the existing full-replace endpoints, but the batch loop widens the window to N keys. No fix required beyond awareness; consider a per-key version check or CAS if the store supports one.

// The key disappeared between listing and updating; skip it.
continue
}
return handleError(c, authKeyWriteError(err))

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🟡 risk: the rename loop is non-atomic. A mid-loop UpdateLabels failure returns an error after earlier keys were already renamed, and the error response says nothing about how far it got. The rename is idempotent, so a retry converges — document this in the handler comment, or return the renamed count even on failure.

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