Skip to main content

Admin UI

Covara ships a built-in admin dashboard served at /__covara/ui. It's disabled by default — enable it by passing adminUI to createCovara.

const app = createCovara({
adminUI: {
title: "My App Admin",
metricsCollector,
security: {
mode: isProduction() ? "production" : "development",
auth: { disabled: !isProduction() },
},
dataExplorer: { enabled: true, readOnly: false, maxLimit: 100, excludeFields: { users: ["passwordHash"] } },
kvInspector: { enabled: true, kv: getGlobalKV(), readOnly: false },
userManager: { /* listUsers, getUser, createUser, updateUser, deleteUser */ },
sessionManager: { /* listSessions, revokeSession, ... */ },
},
});

adminUI: true enables it with defaults; an object configures the panels below.

Panels

PanelWhat it shows
DashboardOverview: request/error stats, subscription counts, health.
ResourcesEvery registered resource, its columns, config, and generated endpoints.
Data explorerBrowse/filter/edit rows per resource (read-only or read-write), with excluded fields. Bypasses resource auth scopes.
API explorerTry endpoints interactively. Runs as the verified admin and bypasses resource auth scopes.
Filter testerBuild and validate RSQL filters against a resource.
RequestsLive request metrics (recent, slow, by path).
SubscriptionsActive SSE subscriptions.
ChangelogRecent changelog entries.
TasksBackground task queue, status, DLQ.
UsersManage users (via userManager callbacks).
SessionsList and revoke sessions (via sessionManager).
KV inspectorInspect the KV store.
Errors / auditError log and admin audit entries.

Security

security: {
mode: "development" | "staging" | "production",
auth: { disabled: !isProduction() },
}

In development you can leave auth disabled for convenience; in production, protect it (the UI gates on the configured auth and serves its own self-only CSP regardless of your global security headers). dataExplorer.readOnly and kvInspector.readOnly let you expose a safe read-only view in staging/production.

Scope bypass

Both the Data explorer and the API explorer bypass the per-resource auth scopes so an admin sees and edits every row, not just their own. The Data explorer queries the database directly. The API explorer forwards the request to the real resource endpoints with a non-secret marker header (x-covara-admin-bypass); the resource layer then re-verifies that the forwarded request's authenticated user is an admin before honoring it. "Admin" is decided by the same security config that gates the UI (requireRole / authorization / authorize, or the admin apiKey) — no separate credential.

Because the marker carries no secret, a leaked or guessed marker is useless to a non-admin: the request still runs under normal scope enforcement. Bypass also requires that an admin predicate is registered (it is, whenever you mount the admin UI via createCovara); standalone useResource mounts never bypass. Every bypassed API-explorer request is recorded in the admin audit log (api_explorer_execute). Locking down the UI's auth in production therefore also locks down scope bypass.

An admin can also opt into the bypass on a direct API call by sending the x-covara-admin-bypass: 1 header — it only takes effect for users the admin predicate accepts, and is audited. With apiKey admin auth the marker is honored when the request carries that key; with role/authorize-based auth it is honored when the authenticated user passes the same check.

User impersonation

Where scope bypass lets an admin see everything, impersonation is the inverse: it runs requests as a specific user, under that user's per-operation auth scopes — a "see (and act) exactly as they would" tool. Click Impersonate on a user in the Users panel and a global amber badge ("Impersonating …") appears across the API Explorer, Filter Tester, and Data Explorer; the on the badge clears it. Near filter inputs a contextual badge shows the scope that user's request would carry (e.g. appending filter userId==123), resolved from the resource's auth config for the relevant operation.

Impersonation is full read-write — mutations execute and are attributed to the impersonated user — so use it deliberately; every impersonated request is recorded in the admin audit log (impersonate_execute / data_explorer_list) carrying both the real admin id and the impersonated user id.

Security model (mirrors scope bypass): the API Explorer forwards a non-secret marker header x-covara-impersonate: <userId>. The resource layer honors it only when the forwarded request's real authenticated user passes the admin predicate, then swaps the effective user to the target for scope resolution and write attribution. A leaked/forged marker from a non-admin is inert. Impersonation replaces scope bypass and never stacks with it — impersonating an admin grants only that admin's scope, never full bypass. Impersonation requires the admin UI's userManager to be configured (so the target user can be loaded); without it, impersonation is inert.

Wiring live data

The UI reads from the same metrics collector and KV your app uses. Pass a metricsCollector (from createMetricsCollector) so the Requests/Dashboard panels show real traffic, and getGlobalKV() to the KV inspector. The userManager/sessionManager callbacks bridge the Users/Sessions panels to your tables and auth adapter — see the example app for a complete wiring.

Health endpoints

createCovara also mounts /healthz and /readyz (configurable via the health option). See Health checks.