docs(auth): what building the apps' side settled (ADR 0017)

ADR 0017's step-3 section: codes by mail sign nobody in, the ways in
for accounts without a working password, changes while signed in,
sessions ended in every service, the apps' screens (the QR package and
the alternatives considered), the keys in the keyring, anonymous
people's keys waiting for step 4, and libsodium on devices (results
copied before they leave an isolate; a C compiler and make for every
build). The module's and halkyon_app's READMEs and the AGENTS files say
the same; the snap's build installs make for sodium's build hook.

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-20 19:34:02 +02:00
commit 4f7b123ad4
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -49,11 +49,32 @@ Written as the apps are: Dart 3.13's primary constructors, Material from
account deletes it, so asks first) and deleting it (after asking), for an
app's settings, in the app's words where only it can say them.
- **Signing in** (`lib/src/auth/`): `AuthRepository` on an `AuthGateway`;
`ServerpodAuthGateway` signs in anonymously, with GitHub (the system
browser and a loopback address on Linux and Windows, `LoopbackWebAuth`) and
with a code by mail, through the instance's `halkyon_base`; `SessionBloc`,
`GitHubSignInBloc`, `EmailSignInBloc` (with `showEmailSignInSheet`) and
`ServerpodAuthGateway` signs in anonymously and with GitHub (the system
browser and a loopback address on Linux and Windows, `LoopbackWebAuth`),
through the instance's `halkyon_base`, and puts a session granted elsewhere
in place (`useSession`); `SessionBloc`, `GitHubSignInBloc` and
`SignInWaysCubit`; `SignedOutMark`, `SignInAddresses`, `PersonFolders`.
- **A password and TOTP** (`lib/src/password/`, ADR 0017): `PasswordRepository`
on a `PasswordGateway` (`ServerpodPasswordGateway`), an `AccountCrypto`
(`SodiumAccountCrypto`: halkyon_keys and SRP's client half, each step on an
isolate of its own, whose results are copied before they cross back:
sodium's are views of memory freed with the isolate that made them) and an
`AccountKeyStore` (`SecureAccountKeyStore`: the account's unlocked keys in
the system's keyring, per instance and person, gone once another person
signs in or nobody). 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
codes, changing the password, a new phrase, and getting back in. The
screens: the start screen's Sign in and Create an account,
`showPasswordSignInSheet`, `showAccountSetupSheet`,
`showAccountRecoverySheet`, and `AccountSecuritySection` for an app's
account part. Anonymous people get no keys until something is encrypted
(step 4). Every build of an app needs a C compiler and make: sodium's build
hook compiles libsodium.
- **Files** (`FileSaver`, `PlatformFileSaver`): keeping a file the app made
where the person chooses (a recovery phrase, recovery codes, an app's
exports).
- **Sync** (`lib/src/sync/`): `SyncService` (once at start, shortly after
local changes, on resume and every few minutes, one sync at a time, counting
the changes not on the server yet, `PendingChangesStore`), `AppCompatibility`
@ -63,7 +84,8 @@ Written as the apps are: Dart 3.13's primary constructors, Material from
- **A client of `halkyon_base` alone** (`BaseClient`): to ask an instance
about itself, and to sign in as another person than the app's client holds.
- **Testing** (`package:halkyon_app/testing.dart`): fakes of every boundary
(`FakeAuthGateway`, `FakeInstanceChecker`, the stores in memory), a frame
(`FakeAuthGateway`, `FakePasswordGateway`, `FakeAccountCrypto`,
`FakeInstanceChecker`, the stores in memory), a frame
(`testFrame`), `testApp`, and `TestAppDependencies`.
## Using it in an app
@ -88,8 +110,12 @@ Written as the apps are: Dart 3.13's primary constructors, Material from
say: what the first start's instance keeps of the person's, what a switch
to another account leaves behind, and where GitHub is added later.
5. **The dependencies**: the app's composition root implements
`AppDependencies<P>` (`serverName`, `auth`, `signedOut`, `sourceCodeUrl`,
`openPerson`, `dispose`), its person's dependencies `Disposable`. Its `auth` is an
`AppDependencies<P>` (`serverName`, `auth`, `signedOut`, `passwords`,
`fileSaver`, `sourceCodeUrl`, `openPerson`, `dispose`), its person's
dependencies `Disposable`. Its `passwords` is a `PasswordRepository` on
`ServerpodPasswordGateway(client, base: client.modules.base)`,
`SodiumAccountCrypto()`, `SecureAccountKeyStore(storage.keysOf(instance))`,
the auth gateway and the app's `SignInAddresses`. Its `auth` is an
`AuthRepository` on `ServerpodAuthGateway(client, base:
client.modules.base, callbackScheme: …, appName: …)`; the scheme is the
app's own (`app.halkyon.learn`), registered with each platform and in the