docs(adr): one account across an instance's services (ADR 0016)
A register in one service's server, the others its members; one account ID everywhere; each app signs in itself; handles and profiles in halkyon_base; deleting the account deletes it everywhere. The way to Todo as the agenda of the others (ADR 0018), after the password, TOTP and keys (ADR 0017). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
707accba28
commit
2033e5606f
1 changed files with 66 additions and 0 deletions
66
docs/adr/0016-accounts-across-an-instance.md
Normal file
66
docs/adr/0016-accounts-across-an-instance.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# ADR 0016: One account across an instance's services
|
||||
|
||||
- **Status:** decided 19 Oct 2026, by the developer.
|
||||
- **Builds on:** ADR 0010 (email sign-in), ADR 0011 (profile pages and the account domain),
|
||||
ADR 0014 (halkyon_base), ADR 0015 (one repository).
|
||||
- **Followed by:** ADR 0017 (password, TOTP and the keys), ADR 0018 (the agenda).
|
||||
|
||||
## Context
|
||||
|
||||
An operator may run several Halkyon services side by side (learn.example.com,
|
||||
todo.example.com, later train. and meditate.). Each has its own server, database and
|
||||
sessions, and until now its own accounts: the same address signed in to Learn and to
|
||||
Todo reached two people, with two handles and two deletions.
|
||||
|
||||
The reason to join them is Todo as the agenda of all the others, both ways: Learn's cards
|
||||
due today, Train's planned exercise and Meditate's session appear in Todo, and moving one
|
||||
there moves it in the app it belongs to (ADR 0018). That needs one person behind them all.
|
||||
Handles on the account domain (ADR 0011) need it too: two services handing out handles on
|
||||
one domain would hand the same one to two people.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **Within one operator's instance only.** Across operators would need an OpenID Connect
|
||||
provider with web sign-in pages, browser sessions and consent; not now.
|
||||
2. **A register in one service's server.** halkyon_base runs in one of two modes. The
|
||||
service the operator names holds the register (on learn.halkyon.eu, Learn's server: it
|
||||
holds the identities and handles already, so nobody's account moves); the others are its
|
||||
members and ask it. With a single service nothing changes: it is its own register.
|
||||
3. **One account ID everywhere.** A member's own person (its `AuthUser`) takes the
|
||||
register's account ID, so a deletion, a handle or an agenda item names the same person
|
||||
in every service.
|
||||
4. **Each app signs in itself.** Apps on one device can't read each other's sessions, so
|
||||
Todo signs in on its own (today with an email code or GitHub, after ADR 0017 with the
|
||||
password and TOTP) and reaches the same account: the member's server runs the sign-in by
|
||||
asking the register (it mails the codes and resolves addresses and GitHub IDs), then
|
||||
opens a session of its own for that account. As Proton's apps do.
|
||||
5. **Trust between servers:** a secret the instance's services share (`instanceSecret`;
|
||||
`INSTANCE_SECRET` in `deploy/.env`), sent with every call a member makes; members reach
|
||||
the register at an address the operator gives (its address on the instance's own network
|
||||
when on one host). Nothing a person's device sends can call the register as a member.
|
||||
6. **Anonymous accounts stay per service.** Becoming identified (an address or GitHub
|
||||
added) makes the anonymous person an account of the register under the same ID, or
|
||||
switches to the account the identity belongs to, as linking and switching do today.
|
||||
7. **Handles and profiles move into halkyon_base**, served by the register (the tables
|
||||
unchanged, as the identities moved in ADR 0014): one handle per account on the account
|
||||
domain, shown alike by every service. What fixes a handle (Learn: the first publish) is
|
||||
the host's, told to the module.
|
||||
8. **Deleting the account deletes it everywhere.** From any app: a member passes it to the
|
||||
register, which deletes the account and its ways in, then tells every member to delete
|
||||
that person's data; a member it can't reach is told again until it answers, and each
|
||||
member also deletes, as it prunes, people the register no longer knows.
|
||||
9. **Released apps:** the profile endpoints move, so the change rides on build 21's raise of
|
||||
`minimumAppBuild` if it is through its checks by 22 Oct, else on a later release with a
|
||||
raise of its own.
|
||||
|
||||
## Consequences
|
||||
|
||||
- The register's server learns when someone signs in to which service of the instance (the
|
||||
privacy page says so); the services already share one operator.
|
||||
- An operator running one service configures nothing new. One running several names the
|
||||
register, gives every service the shared secret, and the register its members.
|
||||
- If the register's server is down, members can't sign anyone in or create handles;
|
||||
sessions already open keep working, and deletions wait.
|
||||
- Learn's sign-in, profile and deletion code paths go through the module's register mode on
|
||||
learn.halkyon.eu; Todo's through its member mode.
|
||||
- Passwords, TOTP and end-to-end keys (ADR 0017) and the agenda (ADR 0018) build on this.
|
||||
Loading…
Reference in a new issue