feat(base)!: a handle at password sign-up (ADR 0020, D26, D28–D30)

Every new account gets a handle, and an account without one gets its
first as it sets a password. The handle is private until its person
goes public (D5).

- `passwordSignIn.signUp` takes a handle. `passwordSignIn.checkHandle`
  says whether a sign-up could take one, only while that sign-up's
  mailed code waits (`codeExpired` otherwise), counted per code request
  (30 an hour) and per network (60) (D29). Members ask the register.
- `password.set` takes the first handle of an account without one
  (D28); `SignInWays.handle` tells the app whether there is one.
- Each checks the handle before the code is used, so a refusal leaves
  the code for another try. An existing account at the address keeps
  its own handle where it has one, and the typed handle is still
  checked, so the answer says nothing about the address.
- `first_handle.dart` holds what SimpleLogin, the keys and passwords
  share: `refusalOfNewHandle`, `insertFirstProfile`, `hasHandle`.
- halkyon_app: one `HandleField` with its `HandleCheckCubit` (asked
  300 ms after typing pauses, only about the handle typed last; the
  instance's suggestion is free without asking) (D30). The password
  setup asks for the handle between the phrase check and the code, and
  a refusal at the code sends back to it. SimpleLogin's sign-up and
  keys steps use the same field and now check as it is typed.
- The module's README and ADR 0020 (D29, D30, the built state) amended.

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 18:09:04 +02:00
commit 630965d920
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -259,6 +259,14 @@
}
}
},
"passwordHandleIntro": "A code is on its way to {address}. Meanwhile, choose your handle: others find you by it. It stays private until you publish something or fill in your profile, and can change until your first publish.",
"@passwordHandleIntro": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"passwordResendCode": "Send a new code",
"passwordTotpCode": "Code from your authenticator app",
"passwordRecoveryCode": "Recovery code",
@ -560,16 +568,17 @@
"simpleLoginCreateHint": "Choose a handle and a password; you get a recovery phrase.",
"simpleLoginHaveOne": "I already have one",
"simpleLoginHaveOneHint": "Link it again with your handle and your recovery phrase.",
"simpleLoginHandleIntro": "Others find you by your handle. It stays private until you publish something or fill in your profile, and can change until your first publish.",
"simpleLoginHandle": "Handle",
"simpleLoginHandleFree": "@{handle} is free",
"@simpleLoginHandleFree": {
"handleIntro": "Others find you by your handle. It stays private until you publish something or fill in your profile, and can change until your first publish.",
"handleLabel": "Handle",
"handleFree": "@{handle} is free",
"@handleFree": {
"placeholders": {
"handle": {
"type": "String"
}
}
},
"handleChecking": "Checking…",
"simpleLoginPasswordIntro": "Choose a password: you type it when you sign in on another device. It never leaves this device: the instance can't read it, and can't reset it without what it protects being lost.",
"simpleLoginCreate": "Create the account",
"simpleLoginUnlockTitle": "Your password",
@ -597,10 +606,10 @@
"simpleLoginTakenByAnotherPerson": "This SimpleLogin account belongs to another account here.",
"simpleLoginOtherIdentityLinked": "Your account has another SimpleLogin account already.",
"simpleLoginTooManyAttempts": "Too many sign-ins began from this network. Try again in an hour.",
"simpleLoginHandleInvalid": "A handle is 1 to 30 letters (a to z), digits or underscores.",
"simpleLoginHandleReserved": "This handle is kept for the instance.",
"simpleLoginHandleTaken": "Someone else has this handle.",
"simpleLoginTooManyHandleChecks": "Too many handles were tried. Try again in an hour.",
"handleInvalid": "A handle is 1 to 30 letters (a to z), digits or underscores.",
"handleReserved": "This handle is kept for the instance.",
"handleTaken": "Someone else has this handle.",
"handleTooManyChecks": "Too many handles were tried. Try again in an hour.",
"simpleLoginSectionTitle": "SimpleLogin",
"simpleLoginSignsYouIn": "Signs you in",
"simpleLoginAddHint": "Sign in with SimpleLogin, or with your Proton account.",