Repository source: docs/plans/archive/identity_bootstrap_signature_recovery_step4_implementation_summary.md
Identity Bootstrap Signature Recovery: Step 4 Implementation Summary
Stage 1 - Bounded bootstrap recovery
Changes:
Preserved identity-bootstrap API failures as safe technical details.
Added one fresh retry for
signature_verification_failed, alongside the existing transient key-inspection retry.Kept the existing Account recovery message after a second failure.
Verification:
node --check public/assets/browser_signing.js— passed.php tests/run.php BrowserSigningNormalizationTest::testReadyIdentityRetriesBootstrapSignatureVerificationFailure BrowserSigningNormalizationTest::testReadyIdentityStopsAfterSecondBootstrapSignatureVerificationFailure— passed.
Notes:
The retry occurs before any identity publication marker is stored.
Stage 2 - Shared protected-action readiness
Changes:
Added the canonical
ensureActionIdentityreadiness contract over the existing browser identity flow.Routed compose identity preparation through that contract and exposed it to other protected-action surfaces.
Verification:
node --check public/assets/browser_signing.js— passed.php tests/run.php BrowserSigningNormalizationTest::testActionIdentityReadinessUsesTheSharedRecoveryPath BrowserSigningNormalizationTest::testReadyIdentityRetriesBootstrapSignatureVerificationFailure BrowserSigningNormalizationTest::testReadyIdentityStopsAfterSecondBootstrapSignatureVerificationFailure— passed.
Notes:
The default preserves the established lightweight action-readiness behavior; callers can explicitly request full publication verification when needed.
Stage 3 - Protected-action continuation
Changes:
Routed approvals, reactions, invitation issuance, and invitation redemption through the shared readiness gate.
Kept compose on that gate and retained each action's existing once-only submission controls.
Verification:
node --check public/assets/browser_signing.js public/assets/thread_reactions.js public/assets/invite_issuance.js public/assets/invite_redemption.js— passed.php tests/run.php BrowserSigningNormalizationTest::testApprovalSigningPreparesSignsAndFinalizesCanonicalApproval BrowserSigningNormalizationTest::testSignedThreadSubmitPreparesSignsAndFinalizes BrowserSigningNormalizationTest::testThreadReactionBootstrapsIdentityBeforeApplyingLike BrowserSigningNormalizationTest::testPostReactionLikeUsesLikeFeedbackCopy— passed.
Notes:
Direct signing actions now wait for readiness before preparing their action, so recovery completes before any protected write is attempted.
Stage 4 - Safe verification diagnostics
Changes:
Added an operator log entry when identity-bootstrap signature verification fails.
The diagnostic records only the failure status, expected and reported public fingerprints, and parsed GnuPG status-code names.
It deliberately excludes armored keys, detached signatures, user IDs, and raw GnuPG output.
Verification:
php tests/run.php IdentityBootstrapDiagnosticsTest::testDiagnosticKeepsOnlySafeVerificationMetadata— passed.
Notes:
Client-visible API errors remain unchanged; the diagnostic is emitted only through the server error log.
Stage 5 - Regression verification
Changes:
No production code or schema changes were needed in this stage; the focused recovery, protected-action, verifier, and diagnostic coverage from Stages 1–4 provides the regression suite.
Verification:
node --check public/assets/browser_signing.js public/assets/thread_reactions.js public/assets/invite_issuance.js public/assets/invite_redemption.js— passed.php tests/run.php BrowserSigningNormalizationTest PrivateSiteAuthTest OpenPgpKeyInspectorTest IdentityBootstrapDiagnosticsTest— passed.php tests/run.php WriteApiSmokeTest::testLinkIdentityUsesPublicKeyUserIdForUsernameAndInvalidatesProfileArtifact WriteApiSmokeTest::testLinkIdentityAutoCreatesHiddenBootstrapPostWhenNoBootstrapPostIdIsProvided WriteApiSmokeTest::testCreatePreparedPostVerifiesDetachedSignatureAndCommitsSignatureFile WriteApiSmokeTest::testCreatePreparedPostRejectsInvalidDetachedSignatureWithoutWritingFiles WriteApiSmokeTest::testLinkIdentityUsesIncrementalReadModelUpdateWhenDatabaseIsWarm WriteApiSmokeTest::testLinkIdentityWithNewBootstrapUsesIncrementalReadModelUpdateWhenDatabaseIsWarm WriteApiSmokeTest::testApprovedLikeTagAddsScoreAndDoesNotDoubleCountForSameIdentity WriteApiSmokeTest::testFinalizePreparedApprovalVerifiesSignatureBeforeCreatingApproval— passed.A full
php tests/run.phpattempt identified existing failures outside this feature inLocalAppSmokeTestactivity rendering andLazyComposeSigningTest; the relevant recovery tests above remained green.
Notes:
A browser session with a newly created OpenPGP key and a protected write still needs production-like manual confirmation before deployment; this workspace has no authenticated browser session to perform it.