feat(meditate): dreams on the server, sealed and synced like the sittings
The dream journal's table (ADR 0038, D14): `dream`, in the sync engine's
database, a row a dream, its content sealed on the device (key ID,
payload, nonce), so the instance sees only that a dream exists, its size
and when it changed. The same rules as the sittings: the sync engine's
connector refuses a call without a session, each row lives in its
person's space, and deleting the person deletes their dreams with it
(the deletion test now writes and counts a dream too, and leaves
another person's).
The migration `20261103130213716-dreams`:
- `CREATE OR REPLACE FUNCTION gen_random_uuid_v7()`: the generator
repeats the UUID v7 function every migration; replacing it with the
same body changes nothing.
- `CREATE TABLE "dream"`: `id` a UUID v7 by default, `spaceId` the
person's sync space, `keyId` the key it is sealed with, `payload` the
sealed bytes (not null), `nonce` the sealing's nonce.
- `CREATE INDEX "dream_space_idx"` on `spaceId`, so deleting a space
finds its dreams without scanning the table.
- The foreign key from `spaceId` to `offline_sync_spaces("id")` with
`ON DELETE CASCADE`: deleting the space deletes its dreams.
- The version rows of every module in `serverpod_migrations`.
A new, empty table: nothing existing changes and no data moves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
cb026dce8d
commit
769ae3b20a
1 changed files with 18526 additions and 7 deletions
|
|
@ -21,9 +21,11 @@ import 'package:serverpod_auth_idp_server/serverpod_auth_idp_server.dart'
|
|||
as _iais;
|
||||
import 'package:serverpod_offline_sync_server/serverpod_offline_sync_server.dart'
|
||||
as _izehhkf5;
|
||||
import 'journal/dream.dart' as _is2va3v7;
|
||||
import 'privacy/content_key.dart' as _imed3x5d;
|
||||
import 'settings/meditate_settings.dart' as _iutacwgf;
|
||||
import 'sitting/sitting.dart' as _ic8w2fbu;
|
||||
export 'journal/dream.dart';
|
||||
export 'privacy/content_key.dart';
|
||||
export 'settings/meditate_settings.dart';
|
||||
export 'sitting/sitting.dart';
|
||||
|
|
@ -98,6 +100,73 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
],
|
||||
managed: true,
|
||||
),
|
||||
_isp.TableDefinition(
|
||||
name: 'dream',
|
||||
dartName: 'Dream',
|
||||
schema: 'public',
|
||||
module: 'halkyon_meditate',
|
||||
columns: [
|
||||
_isp.ColumnDefinition(
|
||||
name: 'id',
|
||||
columnType: _isp.ColumnType.uuid,
|
||||
isNullable: false,
|
||||
dartType: 'UuidValue?',
|
||||
columnDefault: 'random_v7',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'spaceId',
|
||||
columnType: _isp.ColumnType.bigint,
|
||||
isNullable: true,
|
||||
dartType: 'int?',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'keyId',
|
||||
columnType: _isp.ColumnType.text,
|
||||
isNullable: true,
|
||||
dartType: 'String?',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'payload',
|
||||
columnType: _isp.ColumnType.bytea,
|
||||
isNullable: false,
|
||||
dartType: 'dart:typed_data:ByteData',
|
||||
),
|
||||
_isp.ColumnDefinition(
|
||||
name: 'nonce',
|
||||
columnType: _isp.ColumnType.bytea,
|
||||
isNullable: true,
|
||||
dartType: 'dart:typed_data:ByteData?',
|
||||
),
|
||||
],
|
||||
foreignKeys: [
|
||||
_isp.ForeignKeyDefinition(
|
||||
constraintName: 'dream_fk_0',
|
||||
columns: ['spaceId'],
|
||||
referenceTable: 'offline_sync_spaces',
|
||||
referenceTableSchema: 'public',
|
||||
referenceColumns: ['id'],
|
||||
onUpdate: _isp.ForeignKeyAction.noAction,
|
||||
onDelete: _isp.ForeignKeyAction.cascade,
|
||||
matchType: null,
|
||||
),
|
||||
],
|
||||
indexes: [
|
||||
_isp.IndexDefinition(
|
||||
indexName: 'dream_space_idx',
|
||||
tableSpace: null,
|
||||
elements: [
|
||||
_isp.IndexElementDefinition(
|
||||
type: _isp.IndexElementDefinitionType.column,
|
||||
definition: 'spaceId',
|
||||
),
|
||||
],
|
||||
type: 'btree',
|
||||
isUnique: false,
|
||||
isPrimary: false,
|
||||
),
|
||||
],
|
||||
managed: true,
|
||||
),
|
||||
_isp.TableDefinition(
|
||||
name: 'meditate_settings',
|
||||
dartName: 'MeditateSettings',
|
||||
|
|
@ -267,6 +336,9 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
}
|
||||
}
|
||||
|
||||
if (t == _is2va3v7.Dream) {
|
||||
return _is2va3v7.Dream.fromJson(data) as T;
|
||||
}
|
||||
if (t == _imed3x5d.ContentKey) {
|
||||
return _imed3x5d.ContentKey.fromJson(data) as T;
|
||||
}
|
||||
|
|
@ -276,6 +348,9 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
if (t == _ic8w2fbu.Sitting) {
|
||||
return _ic8w2fbu.Sitting.fromJson(data) as T;
|
||||
}
|
||||
if (t == _is.getType<_is2va3v7.Dream?>()) {
|
||||
return (data != null ? _is2va3v7.Dream.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _is.getType<_imed3x5d.ContentKey?>()) {
|
||||
return (data != null ? _imed3x5d.ContentKey.fromJson(data) : null) as T;
|
||||
}
|
||||
|
|
@ -309,6 +384,7 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
|
||||
static String? getClassNameForType(Type type) {
|
||||
return switch (type) {
|
||||
_is2va3v7.Dream => 'Dream',
|
||||
_imed3x5d.ContentKey => 'ContentKey',
|
||||
_iutacwgf.MeditateSettings => 'MeditateSettings',
|
||||
_ic8w2fbu.Sitting => 'Sitting',
|
||||
|
|
@ -329,6 +405,8 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
}
|
||||
|
||||
switch (data) {
|
||||
case _is2va3v7.Dream():
|
||||
return 'Dream';
|
||||
case _imed3x5d.ContentKey():
|
||||
return 'ContentKey';
|
||||
case _iutacwgf.MeditateSettings():
|
||||
|
|
@ -375,6 +453,9 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
if (dataClassName is! String) {
|
||||
return super.deserializeByClassName(data);
|
||||
}
|
||||
if (dataClassName == 'Dream') {
|
||||
return deserialize<_is2va3v7.Dream>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'ContentKey') {
|
||||
return deserialize<_imed3x5d.ContentKey>(data['data']);
|
||||
}
|
||||
|
|
@ -458,6 +539,8 @@ class Protocol extends _is.DatabaseSerializationManager {
|
|||
}
|
||||
}
|
||||
switch (t) {
|
||||
case _is2va3v7.Dream:
|
||||
return _is2va3v7.Dream.t;
|
||||
case _imed3x5d.ContentKey:
|
||||
return _imed3x5d.ContentKey.t;
|
||||
case _iutacwgf.MeditateSettings:
|
||||
|
|
|
|||
Loading…
Reference in a new issue