feat: studysets record when they last changed; the library lists them so

Decided 2026-10-01: after the starred ones, the library lists the most
recently changed studysets first. That needs a change date, so studyset
gains updatedAt (ADR 0004): when the studyset itself last changed, its
content, place, star or archive date, written by the device making the
change in the same update as the change; the last writer wins. Studysets
from before have none and come last, the newest of them first.

The branch's migration is still unreleased (not merged, not deployed), so it
is recreated rather than followed by a second one:
20261001064926911-tree-tags-assets replaces 20260930213716558 and differs
only by one line on the server, ALTER TABLE "studyset" ADD COLUMN
"updatedAt" timestamp without time zone (nullable, so existing rows keep
null and no data changes), the same column in the table devices rebuild,
and its version. The model's comment on the payload no longer lists schema
1's fields alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-01 08:51:33 +02:00
commit 85c028fe3c
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -19,7 +19,7 @@ have yet:
Every migration of a synced table locks older app versions out of syncing (ADR 0002,
rule 3). Before the first release that costs nothing; after it, every device has to
update before it syncs again. So all of this comes in one migration now,
`20260930213716558-tree-tags-assets`, and later content fields go into the versioned
`20261001064926911-tree-tags-assets`, and later content fields go into the versioned
payloads instead. New card types (multiple choice, vocabulary, drag-and-drop, map
questions) need no migration at all: they are the next schema version of the card
revision's payload, and the per-side merge of ADR 0003 becomes per field.
@ -36,7 +36,12 @@ revision's payload, and the per-side merge of ADR 0003 becomes per field.
`studyset.archivedAt` and `studyset.starredAt` record when a studyset was archived or
starred (null when not). They are columns rather than payload fields for the same
reason as the parent: starring on one device and renaming on another must not
overwrite each other.
overwrite each other. `studyset.updatedAt` records when the studyset itself last
changed (its content, place, star or archive date), written by the device making the
change together with it; the last writer wins. The library lists the most recently
changed first, after the starred ones (added 2026-10-01: the library's order needs a
change date, and the column is free while the migration is unreleased). It is null
for studysets from before, which come last.
2. **Tags are rows, and so are their assignments.** `tag` holds a name in its payload
(content, like a studyset's title); `card_tag` links a card and a tag, one row per
assignment, never updated. Removing a tag deletes one row, and adding it on another