For the complete documentation index, see llms.txt. This page is also available as Markdown.

Verification — End to End

End-to-end smoke test confirming the Staff Portal API → Audit Manager integration works: a Keycloak-authenticated API call lands as a row in the cluster's audit_events table within seconds, with the f

What this page proves

Once the AuditMiddleware is wired in (see Audit Middleware) and you've completed Local Install — Staff Portal API, this page walks through the smoke test that confirms every link in the chain is alive:

curl  →  Staff Portal API (laptop)


       AuditMiddleware (records actor + outcome)

            ▼  fire-and-forget asyncio.create_task
       HTTP POST  →  Audit Manager  (port-forwarded from cluster)


       Kafka  →  Audit consumer  →  PostgreSQL  →  audit_events row

If the row appears as expected, you have full validation of: authentication propagation, middleware ordering, fire-and-forget emission, CloudEvents schema correctness, audit-manager ingest, Kafka buffering, consumer write, and PostgreSQL column promotion.

Pre-flight

Three things must already be running:

# 1. Local Postgres for staff portal (Phase 2 of local-install)
docker ps | grep pg-staff

# 2. Cluster Keycloak port-forwarded
kubectl get svc -A | grep keycloak     # confirm reachability
# In a separate terminal:
kubectl -n <ns> port-forward svc/<keycloak-svc> 8080:80

# 3. Cluster IAM port-forwarded
# In a separate terminal:
kubectl -n <ns> port-forward svc/<iam-svc> 9090:80

And one new thing for this verification:

Configure staff portal to emit

Add to ~/sp-local/.env (or wherever your .env lives):

Restart uvicorn:

The startup log should include exactly this line — that's how you know the middleware is active:

If you see AuditMiddleware disabled (...) instead, the env vars didn't take. Confirm .env is in the directory you ran uvicorn from.

Test 1 — authenticated call

Get a fresh Keycloak token (5-minute lifespan):

Hit any authenticated endpoint:

A 400 Bad Request with field-required errors is success for this test — it means auth passed, the handler ran, and (more importantly) the audit middleware fired with outcome=failure.

Wait ~3 seconds, then query the cluster's audit Postgres:

Expected row:

Column
Expected value

actor_id

Keycloak sub UUID, e.g. de7cf744-206a-4b0f-9d82-eec3a1dbb808

actor_type

user

action

get (first word of the function name get_registry_configuration)

outcome

failure (because the empty body returned 400)

name

Admin User (from JWT name claim)

username

admin (from JWT preferred_username claim)

roles

["Operations Administrator", "Technical Administrator"]

ip

127.0.0.1

api

POST /registry-config/get_registry_configuration

Test 2 — rejected anonymous call

Hit the same endpoint without a token:

Expected: 401 Unauthorized (the endpoint is permission-protected; an anonymous call gets rejected by AuthMiddleware).

Wait ~3 seconds, then query again — last row:

Expected row:

Column
Expected value

actor_id

anonymous

actor_type

anonymous

outcome

denied

ip

127.0.0.1

http_status

401

This proves the rejected-anonymous-attempt path is captured. To suppress this path, set AUDIT_ANONYMOUS_FAILURES=false in .env and restart uvicorn — repeat the curl, and you should see no new audit row for it.

Test 3 — successful anonymous call (should NOT be audited)

Hit /ping:

Expected: 200 pong — and no new audit row, because /ping is in the middleware's hard-coded skip-list.

Troubleshooting matrix

Symptom
Likely cause
Fix

Uvicorn log says AuditMiddleware disabled (...). No-op.

.env not loaded, or AUDIT_ENABLED!=true, or URL empty

Confirm cwd and the env vars; restart uvicorn

HTTP curl returns expected status, but no audit row appears

Audit-manager unreachable / port-forward died

Check curl http://localhost:8002/v1/auditmanager/health returns 200

Uvicorn logs show Audit emission failed for event ...

Audit-manager URL wrong, or it returned 503 (backpressure)

Inspect the log line; fix URL or wait for audit-manager to recover

Row appears but details.actor.name is missing

Old audit-manager image without the _compute_details fix

Confirm deployed image tag includes the fix; kubectl rollout restart deploy/audit-manager

Anonymous call audited even with AUDIT_ANONYMOUS_FAILURES=false

Setting didn't reload

Restart uvicorn after changing the env var

actor_id=anonymous for a 403 with a valid token

Audit-manager image lacks the JWT-decode-on-403 path

Confirm staff-portal-api has the latest audit_middleware.py (the JWT-decode helper). Rebuild + redeploy.

Cleaning up old test rows

If repeated experiments have left noise in audit_events, prune selectively:

Last updated

Was this helpful?