halkyon/apps/meditate/halkyon_meditate_client/lib/migrations/migration_registry.dart

33 lines
1.4 KiB
Dart
Raw Normal View History

/// AUTOGENERATED BY SERVERPOD create-migration - DO NOT EDIT BY HAND
/// Merging: resolve registry conflicts the same as migration_registry.txt.
library;
import 'package:serverpod_database/serverpod_database.dart';
part '20261103074902604-sittings/migration.dart';
part '20261103130213716-dreams/migration.dart';
part '20261103143338267-library/migration.dart';
refactor(base,learn): people's files kept by halkyon_base ADR 0043, D2, D4, D6 and D7, the first step towards Todo's attachments: Learn's file store moves into the module, for every server that keeps files, and Learn becomes its first host. halkyon_base gets the store as Learn had it: uploads into the caller's own space by SHA-256, downloads by a row the caller may read, each person's room (FILE_LIMIT_IDENTIFIED_MB, FILE_LIMIT_INSTANCE_MB, the operator's file_allowance, which moves into the module unchanged) and the pruning of files no live row names. It stays free of the sync engine: a host hands it a FileStore saying which of its rows name a file and what it takes (HalkyonBase.files); without one the files endpoint refuses. Its tests, with refusals, run on a stand-in host. Learn hands it learnFiles: its asset rows, read by their space's members, a readable file over 20 MB only as a PDF, up to 100 MB. Its app calls the module; its own asset endpoint stays for released apps alone, forwarding to the module in Learn's own models, whose names are on the wire. Its file tests still pass through it, end to end. Migrations: the module's creates file_allowance. Learn's server migration holds version rows alone, as tables are matched by name (ADR 0014); its device migration creates the module's empty table, as every module's. Todo's, Train's and Meditate's create the empty table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-11 00:11:36 +01:00
part '20261110225636725-file-store/migration.dart';
feat(base,learn): spaces people share, kept by halkyon_base ADR 0044, step 2 (D1, D2, D11, D13, and D15 to D17, decided today). halkyon_base keeps the spaces several people share, for every app: shared_space, its members with their roles (Owner, Editor, Viewer), and invitations by handle waiting for someone with no account on the service yet. The sharedSpace endpoint creates a space, lists its members, invites by handle, changes roles, removes members, hands the space on, leaves and deletes it. Who may do what: - Only people with an identity reach the endpoint. - A space the caller isn't in can't be told from one that doesn't exist. - Members are named by their membership, never by their account's ID. - Only the Owner manages the members, unless the space lets members invite. - The Owner's role passes only by handing the space on, and the Owner leaves only naming who takes it on. - An invitation counts as an answer about a handle, as it tells whether one exists. Every rule has a test asserting the refusal. The module stays free of the sync engine: a host hands it a SpaceGrants, and every call runs in the module's transaction, so the engine's grants follow the roles or nothing changes. The Owner and an Editor write; a Viewer reads. Learn hands over SyncSpaceGrants on OfflineSyncSpaces. Todo hands over none yet, so its server refuses until its projects are shared. Deleting an account hands each space the person owns to the Editor who joined first, else the Viewer who joined first. A space with no other member goes. This runs before the host's own deletions. A person's first sign-in on a service makes their waiting invitations memberships, in the same transaction that makes them a person there. Migrations: the module's and every host's (Learn, Todo, Train, Meditate) create the three tables, their indexes and the two cascading foreign keys to shared_space, and nothing else. The old server keeps working. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-11 10:33:12 +01:00
part '20261111091722283-shared-spaces/migration.dart';
part '20261111100126298-shared-space-keys/migration.dart';
part '20261111145609511-shared-space-key-roll/migration.dart';
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:28:13 +01:00
part '20261111170120182-shared-space-invitations/migration.dart';
/// Migration registry for the client-side database.
class MigrationRegistry {
/// Ordered list of all client-side database migrations.
/// New migrations are always appended at the end.
static final List<MigrationVersionSql> migrations = [
_Migration20261103074902604_sittings(),
_Migration20261103130213716_dreams(),
_Migration20261103143338267_library(),
refactor(base,learn): people's files kept by halkyon_base ADR 0043, D2, D4, D6 and D7, the first step towards Todo's attachments: Learn's file store moves into the module, for every server that keeps files, and Learn becomes its first host. halkyon_base gets the store as Learn had it: uploads into the caller's own space by SHA-256, downloads by a row the caller may read, each person's room (FILE_LIMIT_IDENTIFIED_MB, FILE_LIMIT_INSTANCE_MB, the operator's file_allowance, which moves into the module unchanged) and the pruning of files no live row names. It stays free of the sync engine: a host hands it a FileStore saying which of its rows name a file and what it takes (HalkyonBase.files); without one the files endpoint refuses. Its tests, with refusals, run on a stand-in host. Learn hands it learnFiles: its asset rows, read by their space's members, a readable file over 20 MB only as a PDF, up to 100 MB. Its app calls the module; its own asset endpoint stays for released apps alone, forwarding to the module in Learn's own models, whose names are on the wire. Its file tests still pass through it, end to end. Migrations: the module's creates file_allowance. Learn's server migration holds version rows alone, as tables are matched by name (ADR 0014); its device migration creates the module's empty table, as every module's. Todo's, Train's and Meditate's create the empty table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-11 00:11:36 +01:00
_Migration20261110225636725_file_store(),
feat(base,learn): spaces people share, kept by halkyon_base ADR 0044, step 2 (D1, D2, D11, D13, and D15 to D17, decided today). halkyon_base keeps the spaces several people share, for every app: shared_space, its members with their roles (Owner, Editor, Viewer), and invitations by handle waiting for someone with no account on the service yet. The sharedSpace endpoint creates a space, lists its members, invites by handle, changes roles, removes members, hands the space on, leaves and deletes it. Who may do what: - Only people with an identity reach the endpoint. - A space the caller isn't in can't be told from one that doesn't exist. - Members are named by their membership, never by their account's ID. - Only the Owner manages the members, unless the space lets members invite. - The Owner's role passes only by handing the space on, and the Owner leaves only naming who takes it on. - An invitation counts as an answer about a handle, as it tells whether one exists. Every rule has a test asserting the refusal. The module stays free of the sync engine: a host hands it a SpaceGrants, and every call runs in the module's transaction, so the engine's grants follow the roles or nothing changes. The Owner and an Editor write; a Viewer reads. Learn hands over SyncSpaceGrants on OfflineSyncSpaces. Todo hands over none yet, so its server refuses until its projects are shared. Deleting an account hands each space the person owns to the Editor who joined first, else the Viewer who joined first. A space with no other member goes. This runs before the host's own deletions. A person's first sign-in on a service makes their waiting invitations memberships, in the same transaction that makes them a person there. Migrations: the module's and every host's (Learn, Todo, Train, Meditate) create the three tables, their indexes and the two cascading foreign keys to shared_space, and nothing else. The old server keeps working. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-11 10:33:12 +01:00
_Migration20261111091722283_shared_spaces(),
_Migration20261111100126298_shared_space_keys(),
_Migration20261111145609511_shared_space_key_roll(),
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:28:13 +01:00
_Migration20261111170120182_shared_space_invitations(),
];
/// List of all client-side database migration versions.
static List<String> get versions => migrations.map((m) => m.version).toList();
}