docs(auth): the short reading of the fixes (ADR 0017)
ADR 0017 gets "The short reading": its findings, the developer's four decisions of 21 Oct, and what changed. "The rules as they stand" says a reset takes effect 14 days after it was asked at the latest, that a member keeps the session a reset signed in and deletes nobody while the register is out of reach, and no longer claims every secret is kept out of every capture: Android holds them back, Windows from 10 2004, macOS from screenshots but not ScreenCaptureKit on macOS 15 and later, iOS covers the app switcher's picture alone, Linux nothing. The module's and halkyon_app's READMEs and Learn's AGENTS.md follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
012f2375a5
commit
a3b70175f6
2 changed files with 105 additions and 21 deletions
|
|
@ -67,7 +67,9 @@ Written as the apps are: Dart 3.13's primary constructors, Material from
|
|||
the system's keyring, per instance and person, gone once another person
|
||||
signs in or nobody; on iOS and macOS `unlocked_this_device`, so readable
|
||||
only while the device is unlocked, never in a backup restored elsewhere nor
|
||||
in iCloud Keychain, each write deleting the entry before it). Signing in (SRP's M2 checked and the keys opened before
|
||||
in iCloud Keychain, each write deleting the entry before it, and forgetting
|
||||
finding too the entries earlier builds kept with another accessibility, a
|
||||
keyring that can't be read now stopping nothing). Signing in (SRP's M2 checked and the keys opened before
|
||||
anything is trusted), signing up (the recovery phrase shown once and three of
|
||||
its words typed back before anything reaches the instance), a setup never
|
||||
finished, the authenticators (QR codes drawn with pub.dev's `qr`), recovery
|
||||
|
|
@ -87,13 +89,17 @@ Written as the apps are: Dart 3.13's primary constructors, Material from
|
|||
through Flutter, so clipboard histories and cloud clipboards would keep
|
||||
it): the recovery phrase and codes are saved or written down, an
|
||||
authenticator's key scanned, opened or typed; all of them show in a
|
||||
`SecretScreen` (the phrase typed back too), kept out of screenshots,
|
||||
`SecretScreen` (the phrase typed back too, its fields offering Paste and
|
||||
Select all alone, their copy keys doing nothing), kept out of screenshots,
|
||||
screen recordings and recents where the app's window answers
|
||||
`app.halkyon/screen_guard`: Android's `FLAG_SECURE` (as Learn's and Todo's
|
||||
`ScreenGuard.kt` in their `MainActivity`), macOS's `sharingType = .none`
|
||||
(`MainFlutterWindow.swift`) and Windows' `WDA_EXCLUDEFROMCAPTURE`
|
||||
(`flutter_window.cpp`); covered on iOS while the app isn't in front;
|
||||
nothing on Linux; keyboards learn nothing typed into a password, a code or
|
||||
(`MainFlutterWindow.swift`; screenshots, but not ScreenCaptureKit's
|
||||
captures on macOS 15 and later) and Windows' `WDA_EXCLUDEFROMCAPTURE`
|
||||
from Windows 10 2004 on, `WDA_MONITOR` (black in captures) before, by the
|
||||
version `RtlGetVersion` tells (`flutter_window.cpp`); neither run yet;
|
||||
covered on iOS in the app switcher's picture while the app isn't in front,
|
||||
screenshots there not held back; nothing on Linux; keyboards learn nothing typed into a password, a code or
|
||||
the phrase; no state's text (which a debug build's bloc observer logs) holds
|
||||
a secret, a code or the address; only an `otpauth:` URI is shown as a QR
|
||||
code or opened; and anything a step didn't expect (bytes of the wrong
|
||||
|
|
|
|||
|
|
@ -104,8 +104,12 @@ the same ID. Sessions stay each service's own: every app signs in itself.
|
|||
under the account's ID the first time). Linking a way in makes the person identified on
|
||||
the register and then on the member; a switch token signs in as the account the
|
||||
address is already. Every refusal is the register's, as on the register itself.
|
||||
- **Deleting:** an identified person's deletion on a member goes to the register first
|
||||
(refused while it can't be reached, deleting nothing), which deletes the account and
|
||||
- **Deleting:** a deletion on a member asks the register first whose account it is
|
||||
(`knownAccounts`), and is refused while it can't be reached, deleting nothing, a
|
||||
person still anonymous on the member too: the register may have linked them while
|
||||
their becoming identified there failed (the app then gives an anonymous account up
|
||||
all the same, leaving it to the pruning). An account of the register's goes there,
|
||||
which deletes the account and
|
||||
keeps a notice for each member in the same transaction (`account_deletion_notice`),
|
||||
told at once and again hourly (`deliverDeletionNotices`, tried least first) until each
|
||||
confirms; notices to a member no longer named are dropped. An anonymous person goes
|
||||
|
|
@ -293,11 +297,14 @@ Built on the three parts above, on the register (members forward every step thro
|
|||
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. A reset takes effect once the owner had 72 hours
|
||||
outside hold-outs (codes waiting, the address's ceiling of proofs filled): each
|
||||
outside hold-outs (codes waiting, the address's ceiling of proofs filled), and 14
|
||||
days after it was asked at the latest, held out or not (`resetWaitsAtMost`): each
|
||||
hold-out that begins before it takes effect moves it on by the time it holds the owner
|
||||
out and no hold-out counted before did (`pushOutResets`, `account_resets.dart`, the
|
||||
row's `heldOutUntil`); a reset that took effect and wasn't carried out lapses a week
|
||||
later (`resetLapsesAfter`), and every reset not carried out 30 days after it was asked
|
||||
out and no hold-out counted before did, never past that (`pushOutResets`,
|
||||
`account_resets.dart`, the row's `heldOutUntil`; a refusal at the address's ceiling
|
||||
pushes after it has answered, on a session of its own, so its time tells nothing); a
|
||||
reset that took effect and wasn't carried out lapses a week later
|
||||
(`resetLapsesAfter`), and none outlives 30 days after it was asked
|
||||
(`resetLivesAtMost`), both 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.
|
||||
|
|
@ -325,7 +332,9 @@ Built on the three parts above, on the register (members forward every step thro
|
|||
taken by its own clock (the notice carries the register's, `sentAt`, so the clocks'
|
||||
offset drops out); a member signing someone in after a reset ends every session of the
|
||||
account it holds made before the register's moment or before now, whichever is later,
|
||||
then makes the new one (`issueSessionAfter`), waiting for nothing. The owner's warning of a session ended for its proofs is
|
||||
then makes the new one (`issueSessionAfter`), waiting for nothing, and keeps it when
|
||||
the register's notice of that moment comes, however late (remembered in memory for a
|
||||
day). 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
|
||||
|
|
@ -336,8 +345,8 @@ Built on the three parts above, on the register (members forward every step thro
|
|||
then) and, 30 days later (`gitHubAccountsKeptAfterEnd`, so a date set wrong can be put
|
||||
right first), `forgetGitHubAccounts` deletes every GitHub ID on the register, first
|
||||
deleting the accounts that sign in with GitHub alone (no address, never a password),
|
||||
each on its own (one failing is tried again the next day), the members told once
|
||||
after all of them. `password.set` adds an
|
||||
each on its own (one failing is tried again the next day; one deleted whose host step
|
||||
after failed counts as deleted), the members told once after all of them. `password.set` adds an
|
||||
address without GitHub only for someone anonymous where the session lives
|
||||
(`anonymousHere`, which a member tells the register).
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue