halkyon/apps/todo/AGENTS.md
Tizian 「ティツィアーン」 87671208df
All checks were successful
CI / check (push) Successful in 30m13s
CI / deploy (push) Has been skipped
feat(base)!: no anonymous accounts on the server (ADR 0020, D25)
The server's half of D25: every account has a way in, and the anonymous
accounts left from before go with the daily pruning.

- The module signs nobody in anonymously: `anonymousIdp` and
  `gitHubUpgrade` are gone, and so is linking GitHub at the register.
- A password is set only by someone whose address is theirs (a
  `firstPassword` code) or who signs in with GitHub alone (a fresh
  sign-in and a `signUp` code); an anonymous account is refused
  `wrongCredentials` before any code is used.
- SimpleLogin refuses to link onto a caller without `identified`
  (`wrongCaller`), the member's endpoint too, so nothing turns an
  anonymous account into one with a way in.
- `pruneAnonymousPeople` deletes every anonymous account left, however
  new, never one identified. Learn and Todo schedule it as
  `prune-accounts` and cancel the old `prune-abandoned-anonymous-people`
  entry once.
- Learn: someone without `identified` keeps no files;
  `FILE_LIMIT_ANONYMOUS_MB` is gone. `minimumAppBuild` is 23, as builds
  up to 22 start with an anonymous account.
- Learn's sync tests make their person and session by SQL in the
  development database, as Serverpod stores sessions.
- Docs, store listings and ADRs 0010, 0014, 0016, 0017 and 0019 amended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 16:14:42 +02:00

4.9 KiB

Halkyon Todo

What holds for every app and package of this repository is in the root AGENTS.md; it applies here in full, and Learn's patterns (apps/learn/AGENTS.md) wherever Todo needs the same thing.

  • A shell on the shared packages (decided 2026-10-19): signing in, the instances, the account and the look work; nothing of a person's is kept or synced yet, which waits for Todo's first model (the developer decides what it keeps and syncs). Packages: halkyon_todo_server, halkyon_todo_client (generated, never edited), halkyon_todo_flutter; app ID app.halkyon.todo on every platform; no web build. Licences as Learn's (server SSPL, client and app AGPL; LICENSE.md).
  • The server includes halkyon_base (ADR 0014) and configures it in server.dart (todoBase(), lib/src/todo_base.dart): its basics say it serves todo (never change it once apps use it), sign-in mails name Halkyon Todo, the source is this repository, minimumAppBuild 1, no data of its own to delete with a person yet (add a deletePersonData hook with Todo's first table). Authentication through the module's builders: a password, SimpleLogin on the register, GitHub (with the instance's own OAuth app) until it ends, email codes proving an address, server-side sessions; no anonymous accounts (ADR 0020, D25). Accounts (ADR 0016): Todo holds its own register when it runs alone, and is a member of the instance's register (Learn's server on learn.halkyon.eu) where the operator sets ACCOUNT_REGISTER_URL (todoBase(accounts: AccountsMode.fromEnvironment())) with the instance's shared INSTANCE_SECRET (instanceSecret); then sign-in, handles and profiles are the register's, the email settings are the register's alone (GitHub's are Todo's own OAuth app's), and an identified person's deletion goes to the register first. addInstanceRoutes serves the calls between the services on its web server, and the server doesn't start without the secret where it needs it. schedulePruning (lib/src/pruning.dart) keeps the module's pruning scheduled, one entry each however often the server starts (and cancels the one under the pruning's name before ADR 0020, D25): the anonymous accounts left from before daily, sign-up attempts and codes hourly, as the register the deletions its members haven't confirmed hourly, as a member the people the register no longer knows daily (each a no-op in the other mode). Session logs are never persisted, in any run mode. Migrations (2026-10-19): the initial one (Serverpod's tables, its auth modules' and the module's email_identity, email_code_request), profiles (public_profile) and deletion-notices (account_deletion_notice), nothing of Todo's own. Tests (test/integration/todo_server_test.dart) call the module's endpoints through the server's own dispatch (halkyon_base.<endpoint>), since the generated test tools expose the project's endpoints alone.
  • The app is halkyon_app's InstanceGate and SessionGate with Todo's frame (todoFrame: "Todo" under "Halkyon", its icon, todo.example.org, its own sentence) and ServerpodInstanceChecker(app: 'todo'); TodoDependencies (AppDependencies<TodoPerson>) on one instance, TodoPerson (empty) per person; a person's app with an empty home and the account sheet: halkyon_app's AccountTiles (whose account on which instance, Switch account, Sign out, Delete account, which asks first) in Todo's words, and halkyon_app's About (showAppAbout: the source of what the instance runs, from TodoDependencies.sourceCodeUrl, and the licence list). Texts through gen-l10n in British English (the template), German (informal du), an empty en_US and en_GB (test/l10n/arb_files_test.dart keeps them in step). The look follows the system's theme mode and language until Todo has settings. Countries in where an instance keeps its data are named by halkyon_app's CLDR names (AssetCountryNames), its language picked by halkyon_app's resolveAppLocale. Widget tests start Todo's whole tree with halkyon_app's fakes (test/app/todo_app_test.dart).
  • The icon is Lucide's list-checks (lucide-static 1.50.0) in the brand's blues on white: apps/todo/tool/app_icons.py (run from apps/todo) fetches it, draws its strokes with Pillow (no SVG renderer needed; other path commands fail loudly), writes assets/icon/halkyon_todo_icon.png and Lucide's ISC licence beside it, then every platform's launcher icon through flutter_launcher_icons as Learn's tool does. registerLucideLicense puts the notice in the licence list.
  • serverpod start runs in apps/todo/halkyon_todo_server (it launches the app from lib/driver.dart); .mcp.json's --server-dir names it when a session works on Todo. Its tests need throwaway passwords in its git-ignored config/passwords.yaml (database, serviceSecret, serverSideSessionKeyHashPepper, emailSignInPepper) or from the environment, as CI gives them. Learn's and Todo's development servers use the same ports: run one at a time.