halkyon/apps/todo/halkyon_todo_server/migrations
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Tizian 「ティツィアーン」 554e1604b4
feat(base,app,learn): invitations to shared spaces by mail and by link
The instance's half of Halkyon's ADR 0044, step 5 (D37 to D40).

An invitation by mail (sharedSpace.inviteByEmail) goes out through the
register (send-space-invitation), naming who invites by their handle
and nothing of what is shared, with a link to /join/<token>. The
instance keeps only the address's keyed hash, as for sign-in, and the
SHA-256 of the token. Whoever opens it joins with a code mailed to that
address (EmailCodePurpose.joinSpace, proven through the register,
prove-address-code), so a forwarded mail admits nobody else; a code
proving another address is refused. It lapses after 14 days, and the
hourly pruning forgets it; inviting the address again replaces it.

A space's own link (setJoinLink, the Owner's) admits whoever opens it
as a Viewer (joinByLink) while it is on; switched off and on, it gets a
new token. Its token is kept as it is, so that whoever may invite copies
the link again (joinLink). The page at /join/<token>, in English and
German, says who invites and as whom; preview tells the app the same.

A membership someone else made is new to its member until they mark it
seen (isNew, addedBy; mine names who shared it), for the Inbox.

halkyon_app learns the two new refusals (handleNeeded, otherAddress),
which Learn reports as not allowed until its screens offer these ways
in. The ADR records D37 to D40 and how the instance's half is built.

The migration, the same in the module and in each server including it
(Learn, Meditate, Todo, Train):

  ALTER TABLE "shared_space" ADD COLUMN "joinToken" text;
  CREATE UNIQUE INDEX "shared_space_join_token_idx"
    ON "shared_space" ("joinToken");
  CREATE TABLE "shared_space_email_invitation" (…), with its unique
    indexes on the space and address hash, and on the token's hash,
    and its foreign key to "shared_space" ON DELETE CASCADE;
  ALTER TABLE "shared_space_member" ADD COLUMN "addedBy" uuid;
  ALTER TABLE "shared_space_member"
    ADD COLUMN "isNew" boolean NOT NULL DEFAULT false;

Every space gets no token, and the unique index allows any number of
nulls; every membership gets no one who added it and isn't new, so
nothing already shared shows in an Inbox. The new table starts empty.
None of it rewrites a table, and the server before the switch names its
own columns, so it keeps working.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-11 18:36:21 +01:00
..
20261019193547604 feat(todo): the server on halkyon_base 2026-10-22 18:11:06 +02:00
20261019201213254-profiles refactor(profile): handles and profiles move into halkyon_base 2026-10-22 18:11:07 +02:00
20261019204122341-deletion-notices feat(accounts): one account across an instance's services (ADR 0016) 2026-10-22 18:11:07 +02:00
20261020111950710-passwords feat(auth): Learn's and Todo's servers take password sign-in 2026-10-22 18:11:11 +02:00
20261020125124942-sessions-ended feat(auth): change the password and the recovery phrase while signed in 2026-10-23 14:12:40 +02:00
20261020185752014-recovery-proof-key fix(auth)!: the recovery phrase is proved by a key of its own 2026-10-23 14:12:43 +02:00
20261020194229631-second-factor-waits fix(auth): codes wait after ten wrong in a row, and the owner is told 2026-10-23 14:12:44 +02:00
20261020204619863-session-code-tries fix(auth): a session's wrong codes end the session, not the account's codes 2026-10-23 14:12:47 +02:00
20261020211225101-email-code-purpose fix(auth): a code by mail serves only what it was asked for 2026-10-23 14:12:48 +02:00
20261021100422779-session-ended-warning feat(auth): a session ended for its wrong proofs warns its owner 2026-10-23 14:12:51 +02:00
20261021110200318-second-factor-paths fix(auth): codes after the recovery phrase count apart from the password's 2026-10-23 14:12:52 +02:00
20261021134804476-reset-hold-outs fix(auth): a hold-out moves a reset on only by its own time, and a reset lives 30 days at most 2026-10-23 14:12:59 +02:00
20261023181810436-oidc-module refactor(base): SimpleLogin's forwarding page on the OpenID Connect module (ADR 0023) 2026-10-24 09:17:47 +02:00
20261023192913500-simplelogin-keys feat(base): SimpleLogin accounts' keys without SRP, signing up in one call (ADR 0020, step 3) 2026-10-24 09:17:48 +02:00
20261025135744931-waiting-accounts feat(base)!: sign-ups as the operator says, waiting accounts, operators (ADR 0021, step 1) 2026-10-26 07:17:05 +01:00
20261025165103193-assistants feat(base,learn,todo): the operator's assistants, and the instance's privacy page (ADR 0021, step 2) 2026-10-26 07:17:06 +01:00
20261026140330157-assistant-budgets feat(base)!: one budget per person for all their assistants, the effort each takes, the operator's lists by page 2026-10-26 16:21:53 +01:00
20261101000019144-projects feat(todo): the sync engine and Todo's first models (ADR 0033, D5, D6) 2026-11-01 01:00:53 +01:00
20261101000604776-tasks feat(todo): sections, tasks and labels on the server (ADR 0033, D6) 2026-11-01 01:06:24 +01:00
20261101180755366-settings feat(todo): a project's Calendar, Upcoming's Display and its 3-day grid (ADR 0033, D17) 2026-11-01 20:01:00 +01:00
20261106183802735-filters feat(todo): filters in Todoist's language, and a view of each label (ADR 0033, D35) 2026-11-07 21:49:42 +01:00
20261106184947570-comments feat(todo): comments on a task (ADR 0033, D36) 2026-11-07 21:49:44 +01:00
20261110225635732-file-store refactor(base,learn): people's files kept by halkyon_base 2026-11-11 01:19:28 +01:00
20261110231607673-attachments feat(todo,app): files attached to tasks and comments 2026-11-11 01:19:41 +01:00
20261111091721303-shared-spaces feat(base,learn): spaces people share, kept by halkyon_base 2026-11-11 10:54:19 +01:00
20261111100125297-shared-space-keys feat(base,app,keys): keys of shared spaces, sealed to each member 2026-11-11 11:35:42 +01:00
20261111145609997-shared-space-key-roll feat(base,app,learn): a shared space's key rolls once a member goes 2026-11-11 16:57:49 +01:00
20261111170121038-shared-space-invitations feat(base,app,learn): invitations to shared spaces by mail and by link 2026-11-11 18:36:21 +01:00
migration_registry.txt feat(base,app,learn): invitations to shared spaces by mail and by link 2026-11-11 18:36:21 +01:00