Skip to content

feat(dashboard): redesign consumer key management UX - #69

Merged
jmlago merged 2 commits into
mainfrom
feat/dashboard-key-ux
Jul 2, 2026
Merged

feat(dashboard): redesign consumer key management UX#69
jmlago merged 2 commits into
mainfrom
feat/dashboard-key-ux

Conversation

@MuncleUscles

@MuncleUscles MuncleUscles commented Jul 2, 2026

Copy link
Copy Markdown
Member

What

Reworks the consumer-key management UI, which was a single drawer doing four jobs (settings, reveal, create/rotate, revoke) with four duplicate "Consumer" text inputs and raw "Grace seconds" jargon.

  • Two-step "New consumer key" dialog — one field (who is this key for?) → key shown once with a copy-now warning, "Copy key" and "Copy setup blurb" actions.
  • Drawer scoped to the clicked row — consumer name/status/routes in the header, no editable consumer inputs anywhere.
  • Keys list — one row per key (sha prefix, created date, status/expiry pill) with per-row Rotate / Revoke (uses the row's prefix, no hand-pasting) and Reveal only where the raw key is recoverable.
  • Rotation is an action on an existing key; grace period is a select (24 h default / 1 h / 7 d / immediately) instead of a raw seconds field.
  • Settings (status, allowed routes, rate/burst) collapse into a fold, opened when the drawer is launched in settings mode.

Backend

New admin-guarded GET /dashboard/api/keys/list?consumer=... returning hash-only per-key metadata: sha256_prefix, status, created_at, expires_at, replaced_at, revoked_at, recoverable. No raw key material. Existing create/reveal/revoke endpoints unchanged.

Tests

pytest tests -q: 462 passed, 2 skipped, 1 failed — the failure is the pre-existing test_antseed_node.py Node module-resolution issue, unrelated to this change. Dashboard suite: 66/66, including 4 new tests for the list endpoint (auth required, metadata without raw keys, recoverable flag, consumer validation).

Summary by CodeRabbit

  • New Features

    • Added a streamlined dashboard drawer for managing consumer API keys, including viewing key status, creating new keys, rotating, revoking, and saving settings.
    • Added a secure key listing view that shows key metadata and whether a key can be recovered, without exposing raw key values.
  • Bug Fixes

    • Updated key recovery flow to restore only a single recoverable key at a time.
    • Improved logout/reset behavior so key-management fields are fully cleared.

Split key creation into a focused two-step dialog (name -> key shown
once with copy key / setup blurb). Scope the consumer drawer to the
clicked row: keys render as a list with per-row rotate/revoke (and
reveal only for recoverable keys), grace period is a human-readable
select instead of raw seconds, and settings collapse into a fold.
Removes the four duplicate consumer inputs and the permanent legacy
reveal section.

Adds GET /dashboard/api/keys/list?consumer=... returning hash-only
per-key metadata (prefix, status, timestamps, recoverable flag).
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@MuncleUscles, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3c7e29d1-3b84-4fe4-a0f8-18eacb29d3e1

📥 Commits

Reviewing files that changed from the base of the PR and between 1a0fb9b and 50cf3bc.

📒 Files selected for processing (2)
  • auth_proxy.py
  • tests/test_auth_proxy_dashboard_full.py
📝 Walkthrough

Walkthrough

Adds an admin-only endpoint GET /dashboard/api/keys/list returning per-consumer key metadata with a recoverable flag (no raw keys), refactors the dashboard UI into a drawer-based key management flow replacing the old bulk reveal UI, and adds/updates corresponding tests.

Changes

Dashboard Key Management

Layer / File(s) Summary
List-keys admin endpoint
auth_proxy.py
New dashboard_list_keys route returns per-key status/timestamp metadata and a recoverable flag derived from CALLER_KEYS, without exposing raw keys.
Drawer HTML and CSS
auth_proxy.py
Embedded CSS expanded for the keys drawer, key-ready panel, and new-key dialog; drawer HTML restructured with keys list, key-ready panel, new-key dialog, and simplified settings.
Drawer JS wiring and key actions
auth_proxy.py
Replaces revealKeys() bulk flow with revealKey(prefix), adds showKeyReady() and dialog/create/rotate/revoke/save functions calling backend endpoints, and binds new DOM event handlers.
Dashboard tests
tests/test_auth_proxy_dashboard_full.py
New tests cover admin auth, metadata-only responses, recoverable flagging, and consumer validation for the list-keys endpoint; existing HTML/logout assertions updated for drawer wording and cleared fields.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant DrawerJS as Drawer JS
  participant DashboardAPI as dashboard_list_keys
  participant CALLER_KEYS

  User->>DrawerJS: open consumer drawer
  DrawerJS->>DashboardAPI: GET /dashboard/api/keys/list?consumer=X
  DashboardAPI->>CALLER_KEYS: check plaintext key per sha256_prefix
  CALLER_KEYS-->>DashboardAPI: recoverable true/false
  DashboardAPI-->>DrawerJS: key metadata list
  DrawerJS->>User: render keys list
  User->>DrawerJS: click revealKey(prefix)
  DrawerJS->>DashboardAPI: request raw key (only if recoverable)
  DashboardAPI-->>DrawerJS: plaintext key
  DrawerJS->>User: showKeyReady()
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: a dashboard UX redesign for consumer key management.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dashboard-key-ux

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.

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

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 `@auth_proxy.py`:
- Line 4093: The rotate action is using the consumer-wide flow rather than a
specific key, so the “Rotate this key” control is misleading. Update
`rotateKey(prefix)` and the `/dashboard/api/keys` request path to either accept
and send a key identifier for row-specific rotation, or change the UI
label/handler so it clearly reflects consumer-scoped rotation. Use the existing
`rotateKey` function, `drawerConsumer`, and the `POST /dashboard/api/keys` call
to keep the behavior and labeling consistent.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d7f10f57-1f1f-4959-a77a-fc9c8fdc883e

📥 Commits

Reviewing files that changed from the base of the PR and between 49827a9 and 1a0fb9b.

📒 Files selected for processing (2)
  • auth_proxy.py
  • tests/test_auth_proxy_dashboard_full.py

Comment thread auth_proxy.py Outdated
POST /dashboard/api/keys now accepts an optional sha256_prefix with
rotate=true: only the matching active key gets expires_at/replaced_at,
instead of every active key of the consumer. Unknown prefix returns 404
key_not_found; malformed prefix 400. rotate=true without a prefix keeps
the legacy rotate-all behavior.

The drawer's per-row Rotate button passes its row's prefix, so 'Rotate
this key' is now accurate, and is hidden on keys already rotated out
(expires_at pending). Flagged by CodeRabbit on PR #69.
@jmlago
jmlago merged commit 95562b6 into main Jul 2, 2026
1 check passed
MuncleUscles added a commit that referenced this pull request Aug 6, 2026
The repo had no pre-merge checks. notify-ci.yml fires on push to main — after
the merge button — and only dispatches to the private CI repo; PR checks were
CodeRabbit alone, and branch protection required a review but zero status
checks. tests/test_antseed_node.py was consequently red for a month across
#63/#68/#69/#70/#71 and every one merged.

Three jobs:
- tests: pytest against a UTF8 Postgres service (SQL_ASCII makes psycopg return
  TEXT as bytes, which silently voids settings overrides), submodules checked
  out so the engine-backed tests are real, node present for the sidecar suite.
- core-tests: the Lua policy core's unit + golden conformance vectors.
- images: build both images, then smoke the artifact.

The image smoke is the one that would have caught #95. A green suite proves the
REPO is consistent and says nothing about what COPY put in the image — which is
exactly how a control.js requiring ./ids.js shipped without it, died at import,
and took every wallet endpoint down with a 502. scripts/check_sidecar_modules.js
resolves (never executes) each shipped module's local imports inside the built
image; verified to reproduce that failure against the old COPY list.
jmlago pushed a commit that referenced this pull request Aug 7, 2026
…#96)

* ci: gate merges on tests, core conformance and a built-image smoke

The repo had no pre-merge checks. notify-ci.yml fires on push to main — after
the merge button — and only dispatches to the private CI repo; PR checks were
CodeRabbit alone, and branch protection required a review but zero status
checks. tests/test_antseed_node.py was consequently red for a month across
#63/#68/#69/#70/#71 and every one merged.

Three jobs:
- tests: pytest against a UTF8 Postgres service (SQL_ASCII makes psycopg return
  TEXT as bytes, which silently voids settings overrides), submodules checked
  out so the engine-backed tests are real, node present for the sidecar suite.
- core-tests: the Lua policy core's unit + golden conformance vectors.
- images: build both images, then smoke the artifact.

The image smoke is the one that would have caught #95. A green suite proves the
REPO is consistent and says nothing about what COPY put in the image — which is
exactly how a control.js requiring ./ids.js shipped without it, died at import,
and took every wallet endpoint down with a 502. scripts/check_sidecar_modules.js
resolves (never executes) each shipped module's local imports inside the built
image; verified to reproduce that failure against the old COPY list.

* ci: give the image smoke a database and fail fast on a dead container

The router opens a host-store pool at startup, so booting it without Postgres
proved only that it can fail to connect. Adds a postgres service to the images
job and runs the container with --network host so it can reach it (a bridged
container cannot see the runner's localhost).

Also drops the '|| true' after docker run: a container that fails to start must
fail the job immediately, not fall through to a curl loop that reports the same
thing sixty seconds later.
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.

2 participants