feat(base): SimpleLogin accounts' keys without SRP, signing up in one call (ADR 0020, step 3)

An account that signs in with SimpleLogin keeps its keys under a password
that signs nobody in (D19): `account_password` keeps the password's own
proof key (Ed25519, `passwordProofKey`) in place of SRP's verifier, which
becomes nullable. The migration adds the column and drops the NOT NULL,
nothing else.

- `simpleLogin.signUp(attempt, handle, setup)`: someone new whose identity
  waits under the attempt gets, in one transaction, an account
  (identified), the link, a profile with the handle and the keys; then a
  session (D18). Refused, the identity still waiting, for a setup out of
  range and a handle refused as saving a profile refuses it.
- `simpleLogin.checkHandle(attempt, handle)`: whether someone new could
  take a handle, at most 30 an hour per attempt and 60 per network.
- `simpleLogin.complete` says, for an account, whether it has its keys and
  its handle, and keeps the sign-in ten minutes under its attempt, the
  account as its caller: D20's confirmation for the changes to come.
- `keys.begin`, `keys.unlock`: the keys for a signed-in device once the
  password is proven with its proof key, for a nonce, bound to the base
  URL the device addressed; wrong proofs counted per session as ADR
  0017's.
- An authenticator is enrolled only for a password that signs in.
- Members ask the register for all of it; `RemoteRegister` and the
  instance API carry the four new operations.

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-23 21:49:44 +02:00
commit 090d901e92
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -158,6 +158,43 @@ abstract interface class AccountRegister {
UuidValue? caller,
});
/// Whether someone new whose SimpleLogin identity waits under [attempt]
/// could take [handle], the checks from [network] counted; null where they
/// could. Refusals as `checkSimpleLoginHandle`'s.
Future<ProfileRefusal?> checkSimpleLoginHandle(
Session session, {
required UuidValue attempt,
required String handle,
required String network,
});
/// Signs up someone new whose SimpleLogin identity waits under [attempt],
/// with [handle] and the keys [setup] describes: the new account's ID,
/// which the member issues its own session for. Refusals as
/// `signUpWithSimpleLogin`'s.
Future<UuidValue> signUpWithSimpleLogin(
Session session, {
required UuidValue attempt,
required String handle,
required KeysSetup setup,
});
/// The first step of [person] proving their password with its proof key
/// (an account that signs in with SimpleLogin). Refusals as
/// `beginPasswordKeyProof`'s.
Future<KeysChallenge> beginPasswordKeyProof(
Session session,
UuidValue person,
);
/// [person]'s keys for a device, once [proof] proved their password for
/// it. Refusals as `unlockKeys`'s.
Future<DeviceKeys> unlockKeys(
Session session,
UuidValue person,
KeysProof proof,
);
/// How [person] signs in: with GitHub, an email address, a password and
/// whether an authenticator is confirmed; and their warning that a session
/// was ended for its wrong proofs, if any.