Repository navigation
Surface Keycloak admin/login events in the EAIStack Audit Log view (read-only) #63
Description
Context
Follow-up to #40 (admin user-management surface). #40 ships the minimum bar: docs/USER_MANAGEMENT.md plus a deep link from EAIStack's admin nav to the Keycloak admin console, and turns on Keycloak's own Admin Events and Login Events (Realm Settings → Events in the Keycloak console) so user/role changes and auth events are captured natively, in Keycloak's own store.
That leaves a real but smaller gap: an admin working inside EAIStack's own Audit Log screen (GET /api/settings/audit, issue #45) sees EAIStack's own security-relevant config changes (retention.update, guardrail.config_update, etc.) but nothing from Keycloak's admin/login events — those live in a separate console, under a separate login. Correlating "an admin disabled a user" with "a retention window changed around the same time" requires switching between two UIs.
Why this is polish, not new functionality
No new capability is added — the underlying audit data already exists and is already viewable (in Keycloak's own console, once #40 turns on Admin/Login Events). This issue is purely about where an admin can see it: adding a read-only view inside EAIStack so they don't have to switch consoles. Nothing here changes what is recorded or who can act on it.
Design direction (already scoped during #40's planning)
Two shapes were considered; live proxy is the recommended one — do not build the alternative without revisiting this reasoning:
- A. Live read-only proxy (recommended): a new admin-gated endpoint calls Keycloak's Admin REST API (
GET /admin/realms/{realm}/admin-eventsand/events) on demand and renders the result in a new tab/section of the existing Audit Log screen. No local storage of Keycloak's events — EAIStack reads, never owns, this data. Requires a Keycloak service-account client role grant (view-eventsonrealm-management— read-only, smaller trust surface than Admin user-management surface (Keycloak integration, no in-app onboarding/offboarding today) #40 avoided by not building the full user-editor) and a repository-free backend service following the existingprovider_probe_service.pyidiom (outboundhttpxcall, folded into a result type, no new DB table). - B. Ingest/mirror into
audit_logs(rejected for now): a poller or Keycloak event-listener webhook copies Keycloak events into EAIStack's ownaudit_logstable. Rejected because it weakens the single-source-of-truth boundary (a second, potentially stale copy of Keycloak's own record), needs de-dup/backfill/pagination handling, and fails silently (a dead poller leaves an audit gap that's only discovered later — a bad failure mode specifically for an audit trail). Revisit only if a real operational need for a unified single-table view emerges that outweighs these costs.
Scope (if picked up)
- Grant
eaistack-api's service account theview-eventsrealm-management client role ininfra/keycloak/realm-import.json(alongside whatever Admin user-management surface (Keycloak integration, no in-app onboarding/offboarding today) #40 already added there, if anything). - New backend service (no repository, no local table) calling Keycloak's Admin REST API for admin-events and events, admin-gated via
require_admin. - New read-only endpoint(s), e.g.
GET /api/settings/keycloak-events. - Frontend: a "Keycloak Events" tab/section on the existing Audit Log screen (
frontend/src/components/AuditLog.tsx), reusing its existing table/list presentation rather than inventing a new one. - Docs: note in
docs/AUDIT_EVENTS.mdthat this is a read-only view of Keycloak's own event store, not part of theaudit_logstable/append-only guarantee.
Non-goals
- No writes to Keycloak's event store, no acknowledgment/dismissal UI.
- No mirroring/duplication into
audit_logs(see rejected option B above). - No filtering/search UI beyond what ships in v1 — add later if needed, same "add query params, not a new repository method" principle as
docs/AUDIT_EVENTS.mdalready states for the existing audit endpoint.
Definition of Done
-
eaistack-apiservice account hasview-events(read-only) granted. - New endpoint(s) admin-gated via
require_admin, unit-tested against a mocked Keycloak HTTP response. - Frontend tab/section added to the Audit Log screen, component-tested.
-
docs/AUDIT_EVENTS.mdupdated to describe this view and its relationship (or lack of one) to theaudit_logstable. - Standard merge gate from
AGENTS.md's Definition of Done applies in full. - RBAC call-out per
AGENTS.md's TDD Discipline step 0: this is an admin feature, gated byrequire_admin, no user-facing surface.
Activity
Admin User Management deep link to Keycloak console (issue #40) (#65)