Skip to content

Server 2.0.0-alpha.4: recover an account with its 12-word phrase - #13

Merged
usermaneGermane merged 1 commit into
mainfrom
v3-recovery
Nov 12, 2026
Merged

usermaneGermane merged 1 commit into
mainfrom
v3-recovery

Conversation

@usermaneGermane

Copy link
Copy Markdown
Owner

SecretSpace 3, phase 5, server side: an account can be recovered with its 12-word phrase. Server version 2.0.0-alpha.4 (a test version; Latest stays as it is).

What changes

  • GET /v2/recovery/<name> (no login): the account's keyset under its recovery phrase, for a device that does not have the account. It opens only with the phrase (128 random bits). For a name with no account a made-up copy comes back (same size and header, the same on every ask), so names cannot be probed.
  • POST /v2/recovery (no login): the device proves it opened the keyset with a value derived from the account's own keys (recovery_proof, stored here only as a hash, like the Login Key), and sends the same keys under a new password and a new phrase. Every session of the account ends. Wrong proofs count with wrong logins.
  • PUT /v2/me/recovery-proof: an account made before this sets its proof once, at its next sync; it cannot be replaced afterwards.
  • PUT /v2/me/recovery: a new phrase, from a session.
  • Sign-up takes recovery_proof; /v2/me says can_recover; /health lists "recovery"; logins.log gets account_recovered, recovery_failed and recovery_phrase_changed lines.

What does not change

  • The 2.x routes. Accounts made with earlier 2.0 alphas keep working.

Tests

  • New tests/test_server_v2_recovery.py: 106 tests over real HTTP. Every refused recovery is also checked to have changed nothing on disk.
  • 19 deliberately broken guards were each caught (one needed two tests added first).
  • Full suite green locally.

server/passman_server.py is the same file in SecretSpace-Server-Linux and SecretSpace-Server-Windows.

🤖 Generated with Claude Code

https://claude.ai/code/session_011ojnyVg7ccsR3pZ64s7aRH

SecretSpace 3, phase 5.

- GET /v2/recovery/<name> (no login): the account's keyset under its
  recovery phrase, for a device that does not have the account. It opens
  only with the phrase. For a name with no account a made-up copy is
  returned (same size and header, the same on every ask), so names cannot
  be probed.
- POST /v2/recovery (no login): the device proves it opened the keyset with
  a value derived from the account's own keys (recovery_proof, stored here
  only as a hash) and sends the same keys under a new password and a new
  phrase. Every session of the account ends. Wrong proofs count with wrong
  logins.
- PUT /v2/me/recovery-proof: an account made before this sets its proof
  once, at its next sync. PUT /v2/me/recovery: a new phrase from a session.
- Sign-up takes recovery_proof; /v2/me says can_recover; /health lists
  "recovery"; logins.log gets account_recovered, recovery_failed and
  recovery_phrase_changed lines.

2.x routes unchanged; accounts made with earlier 2.0 alphas keep working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011ojnyVg7ccsR3pZ64s7aRH
@usermaneGermane
usermaneGermane merged commit 5215212 into main Nov 12, 2026
3 checks passed
@usermaneGermane
usermaneGermane deleted the v3-recovery branch November 12, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant