halkyon/apps/meditate/halkyon_meditate_server/lib/src/journal/dream.spy.yaml
Tizian 「ティツィアーン」 769ae3b20a
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>
2026-11-04 09:31:57 +01:00

20 lines
825 B
YAML

### A dream the person wrote down (ADR 0038, D14): the night it belongs to,
### its title and text, its marks (lucid, nightmare, recurring), its clarity,
### the mood on waking, its labels and when it was written, all in its sealed
### payload; the instance sees that it exists, its size and when it changed.
### Changed and deleted by the person alone. Synced.
class: Dream
table: dream
database: sync
fields:
### The key it is sealed with (ADR 0002's envelope); never null in Meditate,
### where everything is sealed.
keyId: String?
### The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
payload: ByteData
### The sealing's nonce (ADR 0002's envelope).
nonce: ByteData?
indexes:
# Deleting a space finds its rows through this index (see content_key).
dream_space_idx:
fields: spaceId