Skip to content

F2.E — Admin WebUI: keys management page #32

@HXYerror

Description

@HXYerror

Part of #23. Depends on F1.D, F2.B, F2.C, F2.D.

Background

Operators need a UI to create / label / scope / revoke keys without writing SQL.

Goal

/admin/keys page lets admin-tier users CRUD keys; client-tier users get 403.

Tasks

  • List view (/admin/keys): id, label, tier, allowed_models, debug_enabled, last_used (NULL until F3.A telemetry rows exist), created_at, revoked status. Paginate at 50/page.
  • Create form (/admin/keys/new):
    • Fields: label (required), tier (admin/client), allowed_models (multiselect from config aliases), rate_limit_override (number, blank = use default; cap enforced server-side per F2.B), debug_enabled (admin-only checkbox with confirmation modal — see below)
    • On submit: insert row, audit-log the action
    • Render plaintext key once in a flash banner with copy-to-clipboard button + "I have copied this" gate before allowing navigation away
    • Reload of the page never re-shows the plaintext
  • Debug toggle confirmation modal (per security S7): when debug_enabled is checked OR toggled on, show explicit text: "Prompts and responses for this key will be persisted in plaintext at ~/.local/share/copilot-api/traces/. Retention: days. Auto-disables in 24h unless renewed. Continue?". Require explicit re-confirmation.
  • TTL on debug: setting debug_enabled=true automatically schedules an auto-disable 24h later (in-process timer + a debug_expires_at column or check); operator can renew. Audit-log every toggle.
  • Revoke action: POST /admin/keys/:id/revoke → soft-delete via revoked_at = now. Audit-log.
  • Edit scope: PATCH /admin/keys/:id/scope. Tier is immutable post-create. Audit-log.
  • Active debug banner: when ANY key has debug_enabled=true, show a warning banner across all admin pages with the count and a "review" link (per security S7)
  • CSRF tokens on all mutating forms; defense-in-depth Origin check (handled by F1.D middleware)
  • Tests: paginated list with 1000 keys < 100 ms, plaintext key non-replayable after page leave, debug toggle requires confirmation, revocation propagates to next request

Acceptance criteria

  • Creating a key returns a one-time view; reload never shows it again
  • Revoked key fails next request with 401 (integration test)
  • Debug toggle without confirmation modal is impossible (test)
  • All mutations appear in audit log

File pointers

  • New: src/admin/keys/{list,new,detail}.tsx, src/admin/keys/route.ts, src/services/debug-ttl-sweeper.ts
  • Touch: src/admin/layout.tsx, src/lib/migrations/005_debug_expires.sql

Dependencies

Depends on F1.D, F2.B, F2.C, F2.D.

Metadata

Metadata

Assignees

No one assigned

    Labels

    admin-uiAdmin WebUIauthAuthentication / authorization

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions