docs(auth): the full reading, and the rules as they stand now (ADR 0017)
ADR 0017's "Full reading (21 Oct 2026)": each server finding and what was done (H1, M1, M2, M3, L1, L4, L5, L6, L7, L10), those accepted with their reasons (L2, L3, L8, L9), and the device's M1, the owner's proof bound to its operation and the whole base URL, still to do. "The rules as they stand" brought up to date; the module README and Learn's AGENTS.md too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
8e6625855a
commit
8ec2743bfa
1 changed files with 79 additions and 17 deletions
|
|
@ -263,8 +263,9 @@ Built on the three parts above, on the register (members forward every step thro
|
|||
- **Codes tried in a row** (`second_factor_waits.dart`, table
|
||||
`second_factor_failures`): every code tried against an account's second factor after
|
||||
a right password or phrase at sign-in or in the phrase's reset (never the owner's
|
||||
proofs while signed in) counts, per account, from every network, before it is checked, one at a time
|
||||
per account (an advisory lock), so codes sent at once get no more checked; every tenth
|
||||
proofs while signed in) counts, per account and way it came (`SecondFactorPath`:
|
||||
after the password, after the phrase, each with its own waits), from every network,
|
||||
before it is checked, one at a time per account (an advisory lock), so codes sent at once get no more checked; every tenth
|
||||
in a row begins a wait as it is counted (`codesWait`, with when), an hour, then twice
|
||||
as long each time, a day at the most, and every wait mails the account's address
|
||||
(which those calls take); a code accepted, either reset carried out, and a new
|
||||
|
|
@ -280,7 +281,12 @@ Built on the three parts above, on the register (members forward every step thro
|
|||
account's signing key, which every signed-in device keeps) and a code set a new
|
||||
password, the keys staying. A lost password without it: a mailed code asks, 72 hours
|
||||
pass (a mail at the start, a sign-in calls it off), a new code carries it out: new
|
||||
password, new keys, no authenticators.
|
||||
password, new keys, no authenticators. While the owner is held out of signing in (codes
|
||||
waiting, the address's ceiling of proofs filled), every reset not carried out is pushed
|
||||
to 72 hours after the hold-out ends (`pushOutResets`, `account_resets.dart`); a reset
|
||||
that took effect and wasn't carried out lapses a week later (`resetLapsesAfter`,
|
||||
pruned by `forgetLapsedResets`); `SignInWays` tells signed-in devices when each waiting
|
||||
reset takes effect, and `password.callOffResets` calls them off for the owner's proof.
|
||||
- **Changing while signed in:** `password.change` takes the owner's proof (the old
|
||||
password's SRP proof for a `password.beginChange` challenge, and a TOTP or recovery
|
||||
code) and the same keys wrapped under the new password; `password.setRecoveryKeys`
|
||||
|
|
@ -297,22 +303,26 @@ Built on the three parts above, on the register (members forward every step thro
|
|||
(`request`, `code`), to the account's own address. An account without a password
|
||||
deletes with its session, as before.
|
||||
- **Sessions end everywhere:** a change of password ends every other session of the
|
||||
account; a reset of the password or the account ends all. The register ends its own
|
||||
and keeps a `sessions_ended_notice` per member (told at once and hourly until it
|
||||
confirms, `deliverSessionNotices`, as deletions are told): it names a moment, so a
|
||||
account (a setup's password replaced too); a reset of the password or the account ends
|
||||
all. The register ends its own and keeps a `sessions_ended_notice` per member (told at
|
||||
once in the background, and hourly until it confirms, `deliverSessionNotices`, as deletions are told): it names a moment, so a
|
||||
session made since stays, and the session that asked for a change. A member answering
|
||||
one (`/halkyon-base/member/sessions-ended`) ends its sessions made before the moment;
|
||||
a member signing someone in after a reset ends its own first and makes the new session
|
||||
only once its clock is past the moment (`issueSessionAfter`), refusing with
|
||||
`passwordChanged` (sign in again with the new password) when its clock is more than
|
||||
`maxClockSkew` behind. A refusal for a reset not due says when it takes effect
|
||||
`maxClockSkew` behind or ahead. The owner's warning of a session ended for its proofs is
|
||||
dismissed only by a session made since (`signedInBefore`). A refusal for a reset not due says when it takes effect
|
||||
(`takesEffectAt`).
|
||||
- **Older ways:** an account that signs in with a password (it had a confirmed
|
||||
authenticator, which a reset may have taken since: `passwordOnly` in its ways in) no
|
||||
longer signs in with GitHub (`usePassword`); where passwords are offered, no new GitHub
|
||||
account is linked (`deprecated`); from `GITHUB_SIGN_IN_ENDS` on GitHub signs nobody in
|
||||
(`ended`), the basics stop naming the day (`gitHubSignInEnds`, which apps show until
|
||||
then) and `forgetGitHubAccounts` deletes every GitHub ID.
|
||||
then) and `forgetGitHubAccounts` deletes every GitHub ID, first deleting the accounts
|
||||
that sign in with GitHub alone (no address, never a password). `password.set` adds an
|
||||
address without GitHub only for someone anonymous where the session lives
|
||||
(`anonymousHere`, which a member tells the register).
|
||||
|
||||
## Taking it into a host
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue