apps/train with halkyon_train_server, _client and _flutter, as Todo's: halkyon_base configured by trainBase(), its own register alone and a member of the instance's where the operator names one, the app on halkyon_app's gates with Train's frame, account sheet and About, texts in British English and German that speak of workouts, app.halkyon.train on Android, iOS, Linux, macOS and Windows. Where it differs from Todo: development ports of its own (8180 to 8190), so it runs beside Learn's server; one initial migration with the schema Todo's migrations end at (the same tables, compared line by line), not Todo's seventeen; and Todo's icon as a placeholder until the icon tool of ADR 0031 draws Train's bike. The workspace, the licences, the READMEs and AGENTS.md name it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
5.1 KiB
5.1 KiB
Halkyon Train
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 Train needs the same thing.
- A shell on the shared packages, Todo's copied and renamed (decided 2026-10-28, ADR 0030, D12; what Train is to do: ADR 0030): signing in, the instances, the account and the look work; nothing of a person's is kept or synced yet, which waits for Train's first model (ADR 0030: synced with
serverpod_offline_sync, every row sealed, D7). Packages:halkyon_train_server,halkyon_train_client(generated, never edited),halkyon_train_flutter; app IDapp.halkyon.trainon 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 inserver.dart(trainBase(),lib/src/train_base.dart): its basics say it servestrain(never change it once apps use it), sign-in mails name Halkyon Train, the source is this repository,minimumAppBuild1, no data of its own to delete with a person yet (add adeletePersonDatahook with Train's first table). Authentication through the module's builders: a password, SimpleLogin on the register, email codes proving an address, server-side sessions; no anonymous accounts (ADR 0020, D25), nor GitHub (D36). Accounts (ADR 0016): Train 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 setsACCOUNT_REGISTER_URL(trainBase(accounts: AccountsMode.fromEnvironment())) with the instance's sharedINSTANCE_SECRET(instanceSecret); then sign-in, handles and profiles are the register's, the email settings are the register's alone, and an identified person's deletion goes to the register first.addInstanceRoutesserves 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-28): one initial one with Serverpod's tables, its auth modules' and the module's as they stand, nothing of Train's own (Todo's grew one by one with the module; Train starts where they ended). Tests (test/integration/train_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
InstanceGateandSessionGatewith Train's frame (trainFrame: "Train" under "Halkyon", its icon,train.example.org, its own sentence) andServerpodInstanceChecker(app: 'train');TrainDependencies(AppDependencies<TrainPerson>) on one instance,TrainPerson(empty) per person; a person's app with an empty home and the account sheet: halkyon_app'sAccountTiles(whose account on which instance, Switch account, Sign out, Delete account, which asks first) in Train's words, and halkyon_app's About (showAppAbout: the source of what the instance runs, fromTrainDependencies.sourceCodeUrl, and the licence list). Texts through gen-l10n in British English (the template), German (informal du), an emptyen_USanden_GB(test/l10n/arb_files_test.dartkeeps them in step). The look follows the system's theme mode and language until Train 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'sresolveAppLocale. Widget tests start Train's whole tree with halkyon_app's fakes (test/app/train_app_test.dart). - The icon is to be Lucide's
bikefading from cobalt through violet and strawberry into carrot (ADR 0031). Until the icon tool for every app is decided and built (ADR 0031, What follows), Train carries Todo's icon (assets/icon/halkyon_train_icon.pngand the platforms' launcher icons, copied) and no tool of its own.registerLucideLicenseputs Lucide's notice (ISC) in the licence list. serverpod startruns inapps/train/halkyon_train_server(it launches the app fromlib/driver.dart);.mcp.json's--server-dirnames it when a session works on Train. Its tests need throwaway passwords in its git-ignoredconfig/passwords.yaml(database,serviceSecret,serverSideSessionKeyHashPepper,emailSignInPepper) or from the environment, as CI gives them. Train's development server has ports of its own (API 8180, Insights 8181, web 8182, PostgreSQL 8190; the app'sassets/config.json), so it runs beside Learn's, as a member of Learn's register; its tests useconfig/test.yaml's ports, as Learn's and Todo's do, which Melos runs one package at a time.