Repository source: docs/plans/archive/session_reauthentication_step4_implementation_summary.md
Session Reauthentication: Step 4 Implementation Summary
Stage 1 - Safe return targets
Changes:
Added the shared
ResumeTargetnormalizer for relative path-and-query return destinations.Added focused coverage for valid destinations, discarded fragments, and unsafe-target fallback.
Verification:
php tests/run.php ResumeTargetTest— passed (3 tests).
Notes:
The server deliberately drops fragments; a later in-page navigation guard can retain them before navigation.
Stage 2 - Recoverable protected HTML requests
Changes:
Added the shared Reconnecting page for expired, safe protected HTML GET requests.
Preserved explicit Lobby/approval behavior for known pending or signed-out identities and explicit failures for APIs, downloads, RSS, and writes.
Added smoke coverage for Board, thread, profile, and query-string resume targets.
Verification:
php tests/run.php LocalAppSmokeTest::testClearingIdentityRevokesApprovedPrivateSession LocalAppSmokeTest::testPrivateLobbyOnlyExposesLobbyAccountAndAuthenticationSurfaces LocalAppSmokeTest::testPendingPrivateSessionNavigationOnlyShowsLobbyOwnProfileAndAccount ResumeTargetTest— passed (6 tests).
Notes:
The broader
LocalAppSmokeTestrun still has three pre-existingfetchActivity()arity failures unrelated to this stage.
Stage 3 - Return-aware browser authentication
Changes:
Extended private-site authentication with validated explicit and page-provided return destinations.
Replaced the recovery history entry after approved authentication and retained actionable missing-key and pending-approval behavior.
Added browser-script coverage for returning to a deep query-string destination.
Verification:
php tests/run.php PrivateSiteAuthTest— passed (5 tests).node --check public/assets/private_site_auth.js— passed.
Notes:
The existing invitation destination remains the fallback when no resume destination is configured.
Stage 4 - In-page navigation recovery
Changes:
Added the read-only
/api/auth_statuscontract and loaded a shared navigation guard for approved-member pages.The guard checks the session before same-origin protected navigation, authenticates once when needed, preserves fragments, and sends unavailable-key recovery to Account.
Prevented automatic authentication from running on ordinary approved pages merely because the shared scripts are loaded.
Verification:
node --check public/assets/private_site_auth.jsandnode --check public/assets/auth_navigation.js— passed.php tests/run.php AuthNavigationTest PrivateSiteAuthTest LocalAppSmokeTest::testApprovedPrivateSessionCanViewOwnProfileAndBoard LocalAppSmokeTest::testClearingIdentityRevokesApprovedPrivateSession— passed (9 tests).
Notes:
One tab suppresses duplicate clicks while authentication is in flight; parallel tabs retain the existing server-side challenge retry behavior.
Stage 5 - Persistent low-friction sign-in policy
Changes:
Made the PHP viewer-session cookie persistent for 400 days, the common browser retention ceiling, so ordinary browser restarts retain the session identifier.
Documented that the saved browser key, plus automatic recovery when PHP state is cleared, provides the no-user-facing-timeout policy.
Did not add a new feature flag or approval-revocation behavior; both are outside this cycle's implementation scope.
Verification:
php tests/run.php LocalAppSmokeTest::testPrivateViewerSessionCookiePersistsAcrossBrowserRestart LocalAppSmokeTest::testApprovedPrivateSessionCanViewOwnProfileAndBoard LocalAppSmokeTest::testClearingIdentityRevokesApprovedPrivateSession ResumeTargetTest PrivateSiteAuthTest AuthNavigationTest— passed (13 tests).node --check public/assets/private_site_auth.jsandnode --check public/assets/auth_navigation.js— passed.
Notes:
Browser and server-session storage may still discard state; the browser key restores approved access without a manual sign-in.
No aggregate recovery telemetry was added because the application has no privacy-preserving telemetry sink; adding one should be a separate observability decision.