Validation: westside-admin#15 — hooks.server.ts admin role gate
Ticket
forgejo_admin/westside-admin#15 (PR #20, merged). Implements the per-request `handle` hook that reads the encrypted session cookie, validates the JWT against the JWKS, populates event.locals.user, and enforces the admin realm role.Environment
- URL:
https://westside-admin.tail5b443a.ts.net - Cluster image SHA at validation:
63e708dc(after #25 cookie-size fix and #27 azp-acceptance fix) - Test user:
draneylucas@gmail.com(realm-roles includeadmin)
Checks
| # | Criterion | How to Verify | Result | Evidence |
|---|---|---|---|---|
| 1 | Anonymous request to / 302s to /auth/login?redirect=/ | curl unauthenticated GET / | PASS | Live curl: status 302, Location: /auth/login?redirect=%2F |
| 2 | Valid session cookie + admin role passes through | Full SSO round-trip → GET / with cookies | PASS | GET / returned 200 with <code><h1>westside-admin</h1></code>; Playwright headless Chromium also confirmed (no redirect loop) |
| 3 | /health bypasses auth gate (k8s probes) | Pod readinessProbe hits /health unauthenticated | PASS | Pod has been Ready for 76s+ post-roll; readinessProbe hits /health and got 200 |
| 4 | /auth/* bypasses auth gate | GET /auth/login (no cookie) returns 302 to Keycloak (not to itself) | PASS | Live trace shows /auth/login → Keycloak /authorize, no recursive /auth/login |
| 5 | tampered/expired/wrong-key cookie treated as anonymous | Implicit: previously-broken state had this exact behavior — wrong-aud rejection routed to anonymous redirect path (logged in #26's repro) | PASS | Bug #26 reproduced this code path: hook caught JwtVerificationError, deleted cookie, 302 to /auth/login. No 5xx ever observed. |
| 6 | cookie attributes correct (HttpOnly+Secure+SameSite=Lax+Path=/) | Inspect Set-Cookie on /auth/callback response | PASS | Live curl captured: <code>HttpOnly; Secure; SameSite=Lax; Path=/</code> on the session cookie |
Verdict
PASS — gate works for the validated user (admin role). The missing-admin path renders the (unauthorized) 403 group, validated separately under
validation-17-2026-05-03.Discovered Issues
Two surfaced during this validation pass: (1) cookie size exceeded browser limit — fixed in #24/PR#25; (2) JWT aud claim mismatch — fixed in #26/PR#27. Both were latent defects in code that statically passed QA but failed under live runtime conditions. Both now resolved.