feat(base): a reset of the keys without the phrase, and the keys' proof key for a password that signs in (ADR 0020, D31–D34)

An account that signs in with SimpleLogin alone, its password and its
recovery phrase both lost, asks for new keys with a SimpleLogin sign-in
(`keys.startReset`); another sign-in carries it out 72 hours later
(`keys.completeReset`, `notDue` with when before), with the same keys
rewrapped where the device still holds them (D33). No mail: every
signed-in device shows it, and any right proof of the password's or the
phrase's key, or a mend, calls it off; `keys.callOffResets` takes the
password's proof alone (D32). The row is ADR 0017's account reset of kind
`account`, so no migration; ADR 0017's reset by mail now takes only an
account whose password signs in.

An account with ADR 0017's password that added SimpleLogin had keys but
no proof key, so no new device signed in with SimpleLogin could open
them: `password.setProofKey` sets the one that same password makes, with
the owner's proof binding it (D34), and ADR 0017's new password takes it
away. Only an account that signs in with SimpleLogin alone changes
through `keys`. `simpleLogin.complete` says whether the password signs
in, whether the keys have the proof key, and when a reset takes effect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-24 21:51:00 +02:00
commit fe2ef02c92
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -160,8 +160,8 @@ void main() {
);
});
test("digests a new phrase, an authenticator's ID and a mended link's "
'attempt as devices do', () {
test("digests a new phrase, an authenticator's ID, a mended link's "
"attempt and the keys' proof key as devices do", () {
final keys = WrappedKeys(
nonce: ByteData.sublistView(Uint8List.fromList([1, 2])),
cipherText: ByteData.sublistView(Uint8List.fromList([3, 4, 5])),
@ -179,6 +179,8 @@ void main() {
);
expect(authenticatorDigest(id), device.authenticatorDigest(id.toBytes()));
expect(mendLinkDigest(id), device.mendLinkDigest(id.toBytes()));
expect(proofKeyDigest(proofKey), device.proofKeyDigest([6, 7]));
expect(proofKeyDigest(proofKey), isNot(newPhraseDigest(keys, proofKey)));
});
test('digests a new password for keys without SRP as devices do, '