194 lines
14 KiB
Markdown
194 lines
14 KiB
Markdown
|
|
# ADR 0045: Halkyon Days, its apps, names and domains
|
||
|
|
|
||
|
|
- **Status:** decided 12 Nov 2026 by the developer: D1 to D8 and D12 are their own
|
||
|
|
choices, D11 too (over the agent's recommendation to keep `halkyon_`), and D16; D9,
|
||
|
|
D10, D13 to D15 and D17 the agent's recommendations, which they chose, as the answers
|
||
|
|
to the open questions. Nothing is built yet.
|
||
|
|
- **Builds on:** ADR 0015 (one repository), ADR 0016 (one account across an instance),
|
||
|
|
ADR 0017 (a password and an authenticator), ADR 0020 (SimpleLogin), ADR 0031 (the
|
||
|
|
apps' icons), ADR 0039 (halkyon.li at home).
|
||
|
|
- **Amends:** ADR 0039, whose halkyon.li was the family's instance alone (D6); ADR
|
||
|
|
0016, for Halkyon and Myrmex (D7); ADR 0020, whose SimpleLogin goes out of use (D8);
|
||
|
|
ADR 0031, D3, D6 and D11, for Halkyon's icon (D14).
|
||
|
|
|
||
|
|
## Context
|
||
|
|
|
||
|
|
Halkyon began as one learning app, then grew a family under its name: Halkyon Learn,
|
||
|
|
Todo, Train and Meditate, sharing an account on an instance (ADR 0016). Of them, Learn
|
||
|
|
is the one the developer means to open to the public, Todo the next; Train, Meditate
|
||
|
|
and Shop depend on content the operator owns and serves, and stay personal. A family
|
||
|
|
named after one app runs into Todoist's trouble: its maker was named after its first
|
||
|
|
product and had to rename itself Doist once there was a second. And the apps' names,
|
||
|
|
"Halkyon Learn", "Halkyon Todo", describe rather than name.
|
||
|
|
|
||
|
|
The developer's names (11 and 12 Nov 2026) follow one myth and one theme. Halcyon, the
|
||
|
|
kingfisher, is Alcyone (Ἀλκυόνη), who with her husband Ceyx (Κῆυξ) was turned into a
|
||
|
|
kingfisher (Ovid, *Metamorphoses* XI); every winter Aeolus, her father, calms the winds
|
||
|
|
for the days she nests on the sea, the *halcyon days*. Myrmex (μύρμηξ, "ant") was a
|
||
|
|
girl of Attica whom Athena turned into an ant (Servius on the *Aeneid*, 4.402); the
|
||
|
|
ants of Aegina became the Myrmidons (Ovid, *Metamorphoses* VII). Mortals turned into
|
||
|
|
animals, and the calm the halcyon days bring, are the family's thread: software that
|
||
|
|
gives people calm from prying, surveillance-capitalist eyes.
|
||
|
|
|
||
|
|
## Decisions
|
||
|
|
|
||
|
|
- **D1 The project is Halkyon Days** (the developer's): the umbrella, not an app; with a
|
||
|
|
K, as the apps and halkyon.app have it ("Halcyon Days" is a British enamel-box brand
|
||
|
|
and an album). It names what the apps give, and keeps apart from any one of them, so
|
||
|
|
it never has to change as Todoist's maker had to. People see it on the project's
|
||
|
|
site, in the apps' About ("part of Halkyon Days") and at the foot of the instances'
|
||
|
|
pages.
|
||
|
|
- **D2 Halkyon is the learning app** (the developer's), "Halkyon Learn" until now: the
|
||
|
|
kingfisher, the project's first app and the one that gave it its name, as Proton
|
||
|
|
Mail is Proton's. Its icon becomes the kingfisher (D14).
|
||
|
|
- **D3 Myrmex is the task app** (the developer's), "Halkyon Todo" until now: the ant, an
|
||
|
|
image of tasks carried together. Said "MUR-mex" in English, "Mürmex" or "Mirmex" in
|
||
|
|
German. Its icon keeps Lucide's `list-todo` until an ant is drawn for it, as the
|
||
|
|
kingfisher was commissioned. Before the name is published: a trademark search
|
||
|
|
(EUIPO, the app stores); none was found by the agent's quick search (11 Nov), but for
|
||
|
|
an ant-keeping hobby project, *Agora Myrmex*.
|
||
|
|
- **D4 Keyx is the voice assistant, later** (the developer's): Ceyx, Alcyone's husband,
|
||
|
|
with a K as Halkyon has one. Nothing of it is built.
|
||
|
|
- **D5 The domains** (the developer's, 12 Nov 2026):
|
||
|
|
|
||
|
|
| Domain | What | Holds people's data |
|
||
|
|
|---|---|---|
|
||
|
|
| `halky.one` | the project's site: `/` Halkyon Days, `/halkyon`, `/myrmex`, `/keyx` (later), and the F-Droid repository, `/fdroid/repo` | no |
|
||
|
|
| `index.halky.one` | the index of published studysets across instances (the hybrid distribution model), a running service of its own, kept apart from the static site | its own records alone |
|
||
|
|
| `halkyon.li` | the public Halkyon instance | yes |
|
||
|
|
| `myrmex.li` | the public Myrmex instance (registered by the developer, 12 Nov) | yes |
|
||
|
|
| `halkyon.app` | redirects to `halky.one`, so old links keep working | no |
|
||
|
|
|
||
|
|
*halky.one* reads as *Halkyone*, Alcyone's Greek name; *.li* is Lindau's common
|
||
|
|
abbreviation, the developer's home on Lake Constance, where kingfishers fish. The
|
||
|
|
project's domain knows nobody; only an instance holds people's data, which is a
|
||
|
|
privacy story of its own. The pages are paths, not subdomains: one static site.
|
||
|
|
`index.halky.one` takes the place of the earlier thought of `halky.one` itself for
|
||
|
|
the distribution model. Moving the F-Droid repository now costs its one user re-adding
|
||
|
|
it; later it would cost everyone.
|
||
|
|
- **D6 halkyon.li is Halkyon's public instance** (the developer's), where ADR 0039 made
|
||
|
|
it the family's alone; it stays on the host at home behind ramiel (ADR 0039's
|
||
|
|
network, sandbox and backups hold). Who may sign up there is open (below).
|
||
|
|
- **D7 Halkyon and Myrmex keep their accounts apart** (the developer's): each server
|
||
|
|
holds a register of its own (ADR 0016's `AccountsMode.fromEnvironment()` without
|
||
|
|
`ACCOUNT_REGISTER_URL`), with its own handles, account domain (`halkyon.li`,
|
||
|
|
`myrmex.li`), operators, secrets and privacy page. Nothing passes between them, so
|
||
|
|
neither instance learns who uses the other. ADR 0016's register stays for an operator
|
||
|
|
who wants one account across their services; Halkyon Days' public instances don't.
|
||
|
|
Agents (ADR 0044) are Halkyon's.
|
||
|
|
- **D8 People sign up and in with an email address, a password and an authenticator**
|
||
|
|
(the developer's): ADR 0017's way alone, SimpleLogin out of use (`SIGN_IN_WAYS=
|
||
|
|
password` on both instances), switched off by configuration first and its code
|
||
|
|
removed once no account depends on it (the developer's choice, on the agent's
|
||
|
|
recommendation): ADR 0020's sign-in, the callback page, and the OpenID Connect module
|
||
|
|
`halkyon_oidc` (server, client, Flutter), written to be published for others and
|
||
|
|
kept in git's history should it be wanted again. An account signing in with
|
||
|
|
SimpleLogin alone (the developer's own) sets a password from its Profile first,
|
||
|
|
through a code mailed to its address (ADR 0017's fourth reading).
|
||
|
|
- **D9 Train and Meditate stay personal, on registers of their own** (the agent's
|
||
|
|
recommendation, which the developer chose): today they are members of Learn's register, so on
|
||
|
|
a public halkyon.li every Halkyon account could sign in to them. Each holds its own,
|
||
|
|
with `SIGN_UP=closed` once the family's accounts exist; `INSTANCE_SECRET` and
|
||
|
|
`INSTANCE_MEMBERS` go out of use. Over keeping them members, which would need a
|
||
|
|
per-service approval the module doesn't have.
|
||
|
|
- **D10 The app IDs follow halky.one** (the agent's recommendation, which the
|
||
|
|
developer chose):
|
||
|
|
`one.halky.halkyon` and `one.halky.myrmex`, Android's and iOS's IDs being domains
|
||
|
|
reversed. The developer is the apps' only user, so the change costs a reinstall of
|
||
|
|
each on their devices (their data comes back with the first sync) and new F-Droid
|
||
|
|
entries; later it would cost everyone. The signing keys stay.
|
||
|
|
- **D11 In the code, `halkyone_` is the project's prefix, the apps' names below it**
|
||
|
|
(the developer's, over the agent's recommendation to keep `halkyon_` for the shared
|
||
|
|
packages and `halkyon_learn_*` for Halkyon's): *Halkyone* as halky.one spells it.
|
||
|
|
The shared packages become `halkyone_ui`, `halkyone_app`, `halkyone_base_server` and
|
||
|
|
`_client`, `halkyone_core`, `halkyone_content`, `halkyone_editor`, `halkyone_keys`,
|
||
|
|
`halkyone_llm`, `halkyone_interop` (`halkyon_oidc` goes, D8); the apps' become
|
||
|
|
`halkyone_halkyon_server`, `_client`, `_flutter`, `_core`, `_curator`, `_agent`,
|
||
|
|
`halkyone_myrmex_…`, `halkyone_train_…`, `halkyone_meditate_…`. The folders take the
|
||
|
|
apps' names: `apps/halkyon/`, `apps/myrmex/`, later `apps/keyx/`, beside
|
||
|
|
`apps/train/` and `apps/meditate/`. The name an instance's basics give its app (ADR
|
||
|
|
0014) becomes `halkyon` and `myrmex`. Release tags become `halkyon-v…` and
|
||
|
|
`myrmex-v…`, the earlier `learn-v…`, `v…` and `todo-v…` counting as their history.
|
||
|
|
What changes with the names, the developer being the apps' only user: the classes'
|
||
|
|
prefix on the wire and the module's endpoints (`halkyon_base.…`), so builds before
|
||
|
|
and after don't mix; and Serverpod's record of applied migrations, kept per module
|
||
|
|
name, which each database renames in one statement as the renamed servers first
|
||
|
|
deploy (its SQL explained then), or they would create the module's tables again.
|
||
|
|
- **D12 The organisation is `halkyon-days`** (the developer's): code.halkyon.app's
|
||
|
|
`project-halkyon` renamed, its repositories keeping their names (`halkyon`, `website`
|
||
|
|
and the forks), every URL naming it changed in one commit (below).
|
||
|
|
- **D13 The deploy's variables carry their service's name** (the agent's
|
||
|
|
recommendation, which the developer chose, over a file of variables per service): with a register each (D7, D9), every register's
|
||
|
|
secrets are its own, and the unprefixed ones Learn has had since it ran alone become
|
||
|
|
`HALKYON_…`. What the operator shares across services stays unprefixed.
|
||
|
|
|
||
|
|
| Today | Becomes |
|
||
|
|
|---|---|
|
||
|
|
| `LEARN_DOMAIN`, `LEARN_PUBLIC_HOST`, `LEARN_POSTGRES_PASSWORD`, `LEARN_SESSION_KEY_HASH_PEPPER` | `HALKYON_…` |
|
||
|
|
| `TODO_DOMAIN`, `TODO_POSTGRES_PASSWORD`, `TODO_SESSION_KEY_HASH_PEPPER` | `MYRMEX_…` |
|
||
|
|
| `ACCOUNT_DOMAIN`, `EMAIL_SIGN_IN_PEPPER`, `EMAIL_FROM`, `TOTP_KEY`, `RECOVERY_CODE_KEY`, `SIGN_IN_DECOY_KEY`, `SIGN_IN_WAYS`, `SIGN_UP`, `AGENTS`, `SIMPLELOGIN_…` | `HALKYON_…`, and each register's own as `MYRMEX_…`, `TRAIN_…`, `MEDITATE_…` (but `AGENTS`, Halkyon's alone) |
|
||
|
|
| `INSTANCE_SECRET`, `INSTANCE_MEMBERS`, `INSTANCE_MEMBER_…` | gone (D9) |
|
||
|
|
| `EMAIL_SMTP_…`, `DATA_LOCATION`, `BACKUP_LOCATION`, `SOURCE_URL`, `COMPOSE_FILE`, `JELLYFIN_…`, `FILE_LIMIT_…`, the maps', weather's and Photon's | unchanged, the operator's |
|
||
|
|
|
||
|
|
`compose.learn.yaml` and `compose.todo.yaml` become `compose.halkyon.yaml` and
|
||
|
|
`compose.myrmex.yaml`, `sidecars/todo.caddy` `myrmex.caddy`; the Compose project keeps
|
||
|
|
its name, `halkyon-learn`, as Docker names its volumes after it.
|
||
|
|
- **D14 Halkyon's icon is the kingfisher** (the agent's recommendation on the developer's
|
||
|
|
wish of 12 Nov, which they chose): the commissioned drawing in its own colours, cobalt
|
||
|
|
back and orange belly, on ADR 0031's white tile, its themed variants the bird's
|
||
|
|
outline; on its launch screen too. Myrmex, Train and Meditate keep their glyphs, and
|
||
|
|
their launch screens the kingfisher in their colours (ADR 0031, D11) until Myrmex has
|
||
|
|
its ant. ADR 0031 records it as D12 when built.
|
||
|
|
|
||
|
|
- **D15 The public instances ask the operator's approval at first** (the agent's
|
||
|
|
recommendation, which the developer chose): `SIGN_UP=approval` on halkyon.li and
|
||
|
|
myrmex.li (ADR 0021), opened once the operator trusts them.
|
||
|
|
- **D16 The developer's account moves into Myrmex's register whole** (the developer's
|
||
|
|
choice, carrying their tasks over): Todo's rows are named by the account's ID and
|
||
|
|
sealed with its keys, so only the same account, not a new one, opens them. As
|
||
|
|
Myrmex's server becomes a register, the account's rows (its ID, address, password
|
||
|
|
verifier, wrapped keys and authenticator) are copied from Halkyon's register into
|
||
|
|
Myrmex's in one step of the switch, its SQL explained then; the same password and
|
||
|
|
authenticator sign in on both, apart from then on.
|
||
|
|
- **D17 The snaps are registered anew as `halkyon` and `myrmex`** (the agent's
|
||
|
|
recommendation, which the developer chose), where the Snap Store has them free;
|
||
|
|
`halkyon-learn` and `halkyon-todo` are closed, their one user moving over.
|
||
|
|
|
||
|
|
## Steps
|
||
|
|
|
||
|
|
1. **The organisation's rename** (D12): the developer renames `project-halkyon` in
|
||
|
|
Forgejo; one commit changes every URL naming it (the servers' source links, which
|
||
|
|
the AGPL requires, and their tests; the forks in the pubspecs and the lock; the
|
||
|
|
F-Droid metadata, the snaps, the release configurations; the docs); the checkouts'
|
||
|
|
remotes follow (the laptop, the server's `~deploy/halkyon`, balthasar's). The local
|
||
|
|
folder keeps its name, as the agent's memory and the worktrees know it by its path.
|
||
|
|
2. **Sign-in** (D8): the developer's account gets a password; `SIGN_IN_WAYS=password`
|
||
|
|
on the instance; then SimpleLogin's code and `halkyon_oidc` go, before the rename,
|
||
|
|
so that they aren't renamed only to be removed.
|
||
|
|
3. **The packages' rename** (D10, D11), in a worktree with `serverpod start` stopped,
|
||
|
|
the generated code made anew and the full check passing: the shared packages to
|
||
|
|
`halkyone_…`; `apps/learn/` to `apps/halkyon/` with `halkyone_halkyon_…`, its snap
|
||
|
|
recipe moved from the root to `apps/halkyon/snap/`; `apps/todo/` to `apps/myrmex/`
|
||
|
|
with `halkyone_myrmex_…`; Train's and Meditate's packages to `halkyone_train_…` and
|
||
|
|
`halkyone_meditate_…`; the app IDs; the instances' app names; the release tool's
|
||
|
|
configuration, tags and history; the migrations' module names (D11).
|
||
|
|
4. **The names people see** (D2, D3, D14): Halkyon's and Myrmex's texts, the launcher's
|
||
|
|
labels, windows, mails, the privacy and profile pages, the listings; Halkyon's
|
||
|
|
kingfisher icon; "part of Halkyon Days" in About.
|
||
|
|
5. **The deploy** (D7, D9, D13, D15, D16): the variables and compose files renamed;
|
||
|
|
Myrmex, Train and Meditate on registers of their own, the developer's account copied
|
||
|
|
into Myrmex's (and Train's and Meditate's, as their data is named by it too);
|
||
|
|
`myrmex.li` in Caddy; `SIGN_UP=approval`; the builds' instances (`serverUrl` in each
|
||
|
|
`release.dart`) `https://halkyon.li/` and `https://myrmex.li/`; learn.halkyon.eu and
|
||
|
|
todo.halkyon.eu go with their server, which retires this month (ADR 0039), as nobody
|
||
|
|
but the developer used them.
|
||
|
|
6. **The releases** (D10, D17): the first builds under the new IDs, on F-Droid and as
|
||
|
|
the snaps `halkyon` and `myrmex`; the developer installs them in place of the old.
|
||
|
|
7. **The site** (D5): halky.one's pages in the website's repository, the F-Droid
|
||
|
|
repository moved, halkyon.app redirecting.
|
||
|
|
8. **The index** (D5): `index.halky.one`, with the distribution model, later.
|
||
|
|
|
||
|
|
## Open questions
|
||
|
|
|
||
|
|
- **Shop**: personal, as Train and Meditate (ADR 0039); whether it takes a name of the
|
||
|
|
same myth later.
|