fix(GRO-2358): wire signOut() at higher layer for no-access screen #72

Merged
Flea Flicker merged 1 commits from feature/2357-p1-logout-on-no-access into dev 2026-06-11 14:24:46 +00:00
Member

Summary

Fixes GRO-2358 — P1 restoration of logout on the "Portal access not configured" screen.

The "Portal access not configured" card (rendered when an Authentik SSO user has no matching client row) used an inline fetch("/api/auth/sign-out", ...) rather than the shared signOut() exported by lib/auth-client. AdminLayout already uses the shared handler, so the no-access screen was a divergence that could trap a user on an authenticated surface with a broken exit.

Changes

  • src/portal/CustomerPortal.tsx — Add a stable handleSignOut callback that calls the canonical signOut() from lib/auth-client and always navigates to /login (even on transient auth-server failure). Use it from the no-access card's "Sign out" button. The handler is the SAME function AdminLayout uses, so the "same logout handler reachable from any authenticated route" AC is satisfied without adding a new chrome element.
  • src/__tests__/portal.test.tsx — Two new tests:
    • calls the shared signOut() handler and navigates to /login from the no-access screen (GRO-2358) — drives the no-access card from / and verifies the shared signOut spy fires once plus a /login navigation.
    • reaches the same shared signOut() on a deep-link no-access screen (GRO-2358) — repeats the assertion from /appointments so a stale or deep link into a portal the user has no access to also reaches the escape hatch.
  • UAT_PLAYBOOK.md §5.25.6 updated to document the shared-handler invariant; new §5.25.6b covers the deep-link case.

Acceptance criteria

  • Logout button on "Portal access not configured" ends the session and returns to /login.
  • The same logout handler is reachable from another authenticated surface (deep-link /appointments no-access test; AdminLayout admin chrome uses the same exported signOut).
  • No new dependencies. No new copy. No new routes. (Handler reuses the existing "Sign out" copy.)
  • Existing logout behavior on authenticated-portal screens unchanged (only the no-access card's handler was swapped; no chrome changes).

Verification

  • pnpm test — 183/183 pass (22/22 in portal.test.tsx).
  • pnpm typecheck — clean.
  • pnpm lint — clean (3 pre-existing warnings, no new ones).
## Summary Fixes [GRO-2358](/GRO/issues/GRO-2358) — P1 restoration of logout on the "Portal access not configured" screen. The "Portal access not configured" card (rendered when an Authentik SSO user has no matching client row) used an inline `fetch("/api/auth/sign-out", ...)` rather than the shared `signOut()` exported by `lib/auth-client`. `AdminLayout` already uses the shared handler, so the no-access screen was a divergence that could trap a user on an authenticated surface with a broken exit. ## Changes - **`src/portal/CustomerPortal.tsx`** — Add a stable `handleSignOut` callback that calls the canonical `signOut()` from `lib/auth-client` and always navigates to `/login` (even on transient auth-server failure). Use it from the no-access card's "Sign out" button. The handler is the SAME function `AdminLayout` uses, so the "same logout handler reachable from any authenticated route" AC is satisfied without adding a new chrome element. - **`src/__tests__/portal.test.tsx`** — Two new tests: - `calls the shared signOut() handler and navigates to /login from the no-access screen (GRO-2358)` — drives the no-access card from `/` and verifies the shared `signOut` spy fires once plus a `/login` navigation. - `reaches the same shared signOut() on a deep-link no-access screen (GRO-2358)` — repeats the assertion from `/appointments` so a stale or deep link into a portal the user has no access to also reaches the escape hatch. - **`UAT_PLAYBOOK.md`** §5.25.6 updated to document the shared-handler invariant; new §5.25.6b covers the deep-link case. ## Acceptance criteria - ✅ Logout button on "Portal access not configured" ends the session and returns to `/login`. - ✅ The same logout handler is reachable from another authenticated surface (deep-link `/appointments` no-access test; `AdminLayout` admin chrome uses the same exported `signOut`). - ✅ No new dependencies. No new copy. No new routes. (Handler reuses the existing "Sign out" copy.) - ✅ Existing logout behavior on authenticated-portal screens unchanged (only the no-access card's handler was swapped; no chrome changes). ## Verification - `pnpm test` — 183/183 pass (22/22 in `portal.test.tsx`). - `pnpm typecheck` — clean. - `pnpm lint` — clean (3 pre-existing warnings, no new ones).
Flea Flicker added 1 commit 2026-06-11 14:23:01 +00:00
fix(GRO-2358): wire signOut() at higher layer for no-access screen
CI / Test (pull_request) Successful in 21s
CI / Lint & Typecheck (pull_request) Successful in 27s
CI / Build & Push Docker Image (pull_request) Successful in 44s
e55fbed8c1
The 'Portal access not configured' screen (rendered when an Authentik SSO
user has no matching client row) used an inline fetch to /api/auth/sign-out
instead of the shared signOut() exported by lib/auth-client. AdminLayout
already uses the shared handler, so the no-access screen was a divergence
that could trap the user on an authenticated surface with a broken exit.

Wire handleSignOut at the CustomerPortal level and use it from the no-access
card. The handler:

- calls the canonical signOut() from lib/auth-client (same one AdminLayout
  uses, so 'same logout handler reachable from any authenticated route' is
  satisfied without adding a new chrome element)
- always navigates to /login, even on transient auth-server failure, so a
  network hiccup never leaves the user trapped

Tests cover the home no-access path AND a deep-link no-access path
(/appointments) — the latter guards the AC requirement that the escape
hatch works on at least one other authenticated surface that does not have
a route guard. UAT_PLAYBOOK §5.25.6 updated; new §5.25.6b documents the
deep-link case.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Flea Flicker merged commit dee7465190 into dev 2026-06-11 14:24:46 +00:00
Flea Flicker deleted branch feature/2357-p1-logout-on-no-access 2026-06-11 14:24:47 +00:00
Sign in to join this conversation.