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>