feat(todo): sections, tasks and labels on the server (ADR 0033, D6)

Three more synced tables, each a sealed payload alone, as project's:
section, task and label; deleted with the person's space.

The migration only adds: the three tables (id uuid defaulting to
gen_random_uuid_v7(), spaceId, keyId, payload, nonce), each indexed on
spaceId and cascading with its space (ON DELETE CASCADE to
offline_sync_spaces), and the modules' version rows. Nothing is dropped
or changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-01 01:06:24 +01:00
commit 128bcb127b
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -52,13 +52,13 @@ void main() {
});
test(
'deleting a person deletes their space with every key and project in '
"it, and nobody else's",
'deleting a person deletes their space with every key, project, '
"section, task and label in it, and nobody else's",
() async {
for (final person in [alice, bob]) {
await _projectOf(session, person);
}
for (final table in ['content_key', 'project']) {
for (final table in _tables) {
expect(await rowsOf(alice, table), 1, reason: table);
}
@ -74,7 +74,7 @@ void main() {
),
0,
);
for (final table in ['content_key', 'project']) {
for (final table in _tables) {
expect(await rowsOf(alice, table), 0, reason: table);
expect(await rowsOf(bob, table), 1, reason: table);
}
@ -99,7 +99,10 @@ void main() {
/// database wraps it.
final _syncDatabases = Expando<OfflineSyncDatabase>();
/// A key and a project in [person]'s personal space, written as their device
/// Every synced table of Todo's.
const _tables = ['content_key', 'project', 'section', 'task', 'label'];
/// A key, a project, a section, a task and a label in [person]'s personal space, written as their device
/// would through the sync engine (payloads stand in for sealed ones: the
/// server never reads them).
Future<void> _projectOf(Session session, UuidValue person) =>
@ -115,4 +118,19 @@ Future<void> _projectOf(Session session, UuidValue person) =>
Project(keyId: 'todo1.0.key', payload: sealed, nonce: sealed),
transaction: transaction,
);
await Section.db.insertRow(
session,
Section(keyId: 'todo1.0.key', payload: sealed, nonce: sealed),
transaction: transaction,
);
await Task.db.insertRow(
session,
Task(keyId: 'todo1.0.key', payload: sealed, nonce: sealed),
transaction: transaction,
);
await Label.db.insertRow(
session,
Label(keyId: 'todo1.0.key', payload: sealed, nonce: sealed),
transaction: transaction,
);
});