AUTH4D-22 console operations screens

The developer console’s project overview, Users, Sessions and Audit log sections are implemented in apps/console/src/features/operations. The fixed route table still mounts features/{project-overview,users,sessions,audit-log}/index.tsx; each of those now re-exports its screen from features/operations. The screens call the AUTH4D-19 management routes through the console BFF (/api/management/tenants/{tenantId}/...). They never call the API directly and never see a token.

BFF allow-list

apps/console/worker/app.ts MANAGEMENT_PATH now also proxies these paths, using the same cookie session, bearer injection and same-origin check on writes as before:

Path below /api/management/tenants/{ten_…} Methods used by the console
/overview, /audit-events GET
/users, /users/{usr_…} GET
/users/{usr_…}/sessions GET
/users/{usr_…}/{disable,enable,deletion} POST {}
/users/{usr_…}/sessions/revoke POST {}
/sessions GET
/sessions/{ses_…}/revoke POST {}

Every other path under /api/management/ still returns 404 without reaching the API.

Screens

Route Content
/projects/{id} Counts from GET /overview and the 8 most recent audit events
/projects/{id}/users?q&status&provider User search (exact email or user ID), status and provider filters, keyset pages
/projects/{id}/users?user={usr_…} User detail: summary, identities, sessions and lifecycle actions
/projects/{id}/sessions?status&user_id&client_id Project sessions with per-session revocation
/projects/{id}/audit-log?event&outcome&actor_id&target_type&target_id&since&until Filtered audit events with a details dialog
  • Tenant context. Filters live in the query string of the selected project’s URL, so they survive reloads and links. Every request path is built from the selected project’s ID. The project switcher links to the section path without a query, so filters never carry over to another project. Screens remount per project and abort in-flight requests, so a slow response from the previous project is never shown. Audit dates are calendar days in UTC, sent as inclusive since/until bounds (T00:00:00.000Z to T23:59:59.999Z).
  • Permissions. owner sees the action controls. member gets a read-only notice and no action controls. The API’s 403 insufficient_role is still handled if it is returned.
  • Confirmation. Every change opens a modal confirmation dialog: disable, re-enable, revoke all sessions, revoke one session and request deletion. Deletion also requires typing delete. On failure the dialog stays open and shows the error and request ID. Specific messages are shown for insufficient_role, deletion_pending and session_state_unavailable. On success the dialog closes, a dismissible status message reports the result (for example the count of revoked sessions), and the data reloads.
  • Revocation delay. Each revoking action, and the Sessions screen, explains that refresh and new sign-ins stop at once, but already-issued access tokens stay valid for up to 5 minutes.
  • Safe formatting. API strings are rendered only as React text, never as HTML. Control and format characters (including bidi overrides) are stripped, and long values are truncated. Audit metadata is shown as a key/value list. Nested objects are shown as “Structured value (not shown)”, never as raw JSON.
  • Empty and error states. Each list has separate empty states for “nothing yet” and “no matches”. Errors show the request ID and a Try again button. Filters stay usable while a list is failing. Invalid filter input is rejected in the browser before any request is sent.

Tests

  • tests/e2e/auth4d-22.operations.spec.ts contains 8 Playwright tests with a mocked BFF and per-tenant state. It covers overview counts and safe event details, user search and pagination, user detail and session revocation, the disable, re-enable and deletion dialogs, read-only viewers, audit filters across project switches, stale responses discarded on switch, and empty/error states. It also checks that nothing is written to browser storage and that no injected markup runs. Run with pnpm exec playwright test -c apps/console/src/features/operations/playwright.config.ts (port 5186, build output apps/console/.wrangler/ui-test-dist-auth4d-22).
  • tests/integration/auth4d-22.console-operations-proxy.test.ts has 3 Vitest tests for the BFF allow-list: it proxies the new paths with the bearer, rejects cross-origin writes and refuses any other path. Run with pnpm --filter @auth4/integration exec vitest run --config vitest.config.ts auth4d-22.

Source: docs/api-spec/auth4d-22.md