Repository source: docs/plans/archive/approved_members_identity_publication_step4_implementation_summary.md
Approved Members Identity Publication Step 4 Implementation Summary
Stage 1 - Private-mode-safe identity existence checks
Changes:
Exposed the approved-members-only state to rendered pages through the existing layout data.
Prevented browser identity setup from calling the protected general profile lookup while private mode is active.
Kept the identity prepare/finalize contract as the authoritative duplicate check.
Verification:
php -l src/ForumRewrite/View/TemplateRenderer.phppassed.php -l src/ForumRewrite/Application.phppassed.node --check public/assets/browser_signing.jspassed.php tests/run.php FeatureFlagEvaluatorTestpassed all tests.Private dev-server smoke rendered
data-approved-members-only="1"; unauthenticated own-profile request returned 404.
Notes:
This stage does not yet complete the prepared identity observed for fingerprint
d0ee...; Stage 2 addresses automatic finalization and recovery.
Stage 2 - Automatic lobby identity publication
Changes:
Loaded the existing browser identity-publication service on the Lobby page.
Made Lobby automatically publish any saved browser keypair before attempting authentication.
Reused the existing prepare/finalize flow so new identities are created and existing identities are handled by the canonical duplicate response.
Verification:
php -l src/ForumRewrite/Application.phppassed.node --check public/assets/private_site_auth.jspassed.node --check public/assets/browser_signing.jspassed.php tests/run.php BrowserSigningNormalizationTestpassed all tests.Private dev-server smoke rendered both browser identity and private-auth scripts on Lobby; unauthenticated profile access remained 404.
Notes:
The user-facing flow no longer requires manually opening Account to publish a keypair already saved in browser storage.
Stage 3 - Approval inheritance and authenticated access
Changes:
Confirmed the existing approval-derived profile state remains the authority after identity publication.
Added a regression check that an approved authenticated session can open its own profile and the full board.
Verification:
php tests/run.php LocalAppSmokeTest::testApprovedPrivateSessionCanViewOwnProfileAndBoardpassed.The test confirmed the approved fixture identity sees
This is your profile.and the Board page under private mode.
Notes:
Approval may be seeded before or after identity publication because it is resolved when the profile/read model is synchronized.
Stage 4 - Private lobby route boundary
Changes:
Fixed private-mode root handling so only a plain root/threads request redirects to Lobby.
Root RSS requests and other query variants now remain inaccessible and return 404.
Added a route-matrix regression check covering Lobby, Account, content, profile API, backup, and RSS access.
Verification:
php -l src/ForumRewrite/Application.phppassed.php tests/run.php LocalAppSmokeTest::testPrivateLobbyOnlyExposesLobbyAccountAndAuthenticationSurfacespassed.
Notes:
The private web-server rewrite still must route non-asset requests through the application when enabled in production.
Stage 5 - Regression coverage and operator documentation
Changes:
Documented one-shot Lobby publication and authentication behavior in the README and production runbook.
Documented that manual Account linking is a recovery path rather than the normal user flow.
Verification:
php tests/run.php FeatureFlagEvaluatorTestpassed all tests.php tests/run.php BrowserSigningNormalizationTestpassed all tests.php tests/run.php LocalAppSmokeTest::testApprovedPrivateSessionCanViewOwnProfileAndBoardpassed.php tests/run.php LocalAppSmokeTest::testPrivateLobbyOnlyExposesLobbyAccountAndAuthenticationSurfacespassed.PHP and JavaScript syntax checks passed for the changed runtime files.
Notes:
The complete legacy suite remains outside this focused verification because it has pre-existing unrelated failures; no production cutover should occur until those failures are triaged separately.
Stage 6 - Browser authentication and own-profile recovery
Changes:
Fixed the verified existing-identity path so presentation-free identity checks no longer dereference a null Account-page root before authentication starts.
Imported the signature verifier into the application namespace;
/api/authenticate_identitypreviously failed with a 503 before it could verify any signature.Made Account key generation and private-key restoration authenticate immediately after publication instead of exposing an own-profile link backed only by local browser state.
Added a server-rendered authenticated identity marker so pending users reload once to receive session-aware Lobby/Account content without entering an authentication loop.
Exposed authentication failures on Lobby/Account and in the browser console, and regenerated the PHP session ID after successful signature verification.
Verification:
php tests/run.php PrivateSiteAuthTest BrowserSigningNormalizationTest LocalAppSmokeTest::testApprovedPrivateSessionCanViewOwnProfileAndBoard LocalAppSmokeTest::testPrivateAuthenticationEndpointReachesSignatureVerifier LocalAppSmokeTest::testPrivateLobbyOnlyExposesLobbyAccountAndAuthenticationSurfacespassed.php tests/run.php FeatureFlagEvaluatorTestpassed.JavaScript and PHP syntax checks passed for all changed runtime and test files.
Isolated Chromium smoke: a newly generated unapproved identity published automatically, completed challenge authentication with one PHP session, re-rendered Account once, and opened its own profile with HTTP 200.
Isolated Chromium smoke: a newly generated identity with a pre-existing approval seed published automatically, authenticated with a real detached signature, entered the Board, and opened its own profile with
This is your profile.
Notes:
The two reproduced root causes were independent: a null-root browser exception suppressed before challenge creation, followed by a missing PHP class import that returned 503 after the browser path was repaired.
All browser writes and approval seeds used an isolated temporary repository and database; the active local repository was not modified.
Stage 7 - Lobby-only navigation
Changes:
Made the shared navigation derive its private-site menu from the server-authenticated viewer profile.
Anonymous Lobby users now see only Lobby and Account; authenticated pending users additionally see only their own Profile link.
Approved users retain the normal Board, About, Users, Tools, and Account navigation.
Applied the restricted navigation to private-mode message/404 pages as well as Lobby and Account.
Verification:
php tests/run.php LocalAppSmokeTest::testPrivateLobbyOnlyExposesLobbyAccountAndAuthenticationSurfaces LocalAppSmokeTest::testPendingPrivateSessionNavigationOnlyShowsLobbyOwnProfileAndAccount LocalAppSmokeTest::testApprovedPrivateSessionCanViewOwnProfileAndBoardpassed.PHP syntax checks passed for the renderer, application, and focused smoke tests.
Live dev-server HTML for anonymous Lobby and Account contained only Lobby and Account navigation links.
Notes:
The own-profile navigation link is emitted only from the authenticated server profile, never directly from the browser identity hint or localStorage.
Stage 8 - Static content access boundary
Changes:
Restricted the development router and Apache rewrite bypass to existing
/assets/*files andfavicon.icoonly.Routed all content, API, download, lock-file, and generated-artifact requests through the PHP front controller regardless of whether the private flag comes from the deployment environment or the instance feature-flags record.
Preserved public-instance static HTML acceleration through the front controller's existing eligible-artifact path.
Updated deployment documentation to describe the secure routing model and removed the obsolete requirement that Apache independently observe the private feature flag.
Verification:
php tests/run.php WebServerRoutingTest LocalAppSmokeTest::testPrivateLobbyOnlyExposesLobbyAccountAndAuthenticationSurfacespassed.php tests/run.php LocalAppSmokeTest::testFrontControllerServesStaticArtifactForAnonymousEligibleRoute LocalAppSmokeTest::testFrontControllerBypassesStaticArtifactWhenCookieIsPresent LocalAppSmokeTest::testFrontControllerBuildsMissingArtifactAfterEligibleAnonymousFallbackpassed.Private live server returned 404 for
/index.html,/posts/reply-001.html, a physical/.locks/*path, and canonical protected content;/assets/site.cssand/favicon.icoremained 200.Separate public-mode live server returned 200 for canonical
/and/posts/reply-001, 404 for direct/index.htmland/posts/reply-001.html, and 200 for/assets/site.css.PHP syntax and scoped whitespace checks passed.
Notes:
Public static HTML hits now incur the front-controller PHP entry cost so a mutable site-level privacy flag remains authoritative; content rendering still uses the prebuilt artifact when eligible.
Stage 9 - Feature-flag test isolation
Changes:
Added
FORUM_APPROVED_MEMBERS_ONLYto the feature-flag test environment cleanup list.Prevented the environment-override test from leaving private mode enabled for every subsequent test in the shared PHP test process.
Restored the prior
$_SESSIONvalue after private-session smoke tests so later authorization tests cannot inherit an approved identity.Updated the approved Account-page regression to require the direct own-profile link now shown outside the advanced area.
Repaired five older smoke-test setup/expectation defects exposed after the leaked private state was removed: temporary template roots, current public-key presentation, read-model initialization, SQLite viewer CSS loading, and isolated static-routing roots.
Verification:
php tests/run.php LocalAppSmokeTestpassed all 77 local application smoke tests.php tests/run.phppassed the complete test suite.PHP syntax and scoped whitespace checks passed for all changed test files.
Notes:
The leaked flag and authenticated session produced a misleading cascade of route, write API, static artifact, read-model, and authorization failures; those downstream failures were not independent private-site regressions.
Stage 10 - Site-scoped approval tooling and live session diagnostics
Changes:
Made approval CLI defaults honor
FORUM_SITE_ID, matching the web server's site-scoped repository and read-model paths.Centralized the default site-scoped database path alongside the existing repository-path helper.
Added CLI-server-only private-session diagnostics for each application request, including the request, session ID, authenticated identity, resolved profile, approval result, repository, and database without logging key material or challenges.
Seeded the reported D0EE identity in the actual Chouse repository and rebuilt
state/cache/post_index_chouse.sqlite3.
Verification:
Focused site-profile, local-state-path, approval-command, and private-session tests passed.
A controlled authenticated request to the active Chouse server returned HTTP 200 for the Board and the D0EE profile rendered
Approved: yes.php tests/run.phppassed the complete test suite.PHP syntax and scoped whitespace checks passed for all changed runtime and test files.
Notes:
The original
./v3 approval seed ...command ran withoutFORUM_SITE_ID=chouse, so it inspected the default Zenmemes repository. The Chouse server independently usedstate/local_repository_chouseandstate/cache/post_index_chouse.sqlite3, where the identity existed but had no approval seed.