DB Schema & Notify-Affected
This subsystem covers the relational source of truth (src/db/schema.ts) and the server-side fan-out that decides which users a write should notify (src/api/lib/notify.ts).
Schema
Section titled “Schema”The Drizzle tables: users, lists, groups, tasks, steps, myDayEntries, listMembers, idempotencyKeys. See the Domain Model for columns and rules. Notable cross-cutting columns: rank (fractional ordering), assigneeId (task assignment, spec 012), and per-viewer order/group on listMembers (per-member List placement, spec 011).
Notify-affected
Section titled “Notify-affected”After a successful write, the Worker must signal the right users (ADR-011). src/api/lib/notify.ts:
affectedUsers(db, listId)— returns the owner ∪ active (non-tombstoned) members of a list: the existingaccessible()set. This is the authorization-aligned recipient set.notifyList(c, listId, surfaces)— fan a signal to everyone with access to a list, for the given surface tags.notifyUsers(c, userIds, surfaces)— signal a specific set of users (e.g. the acting user for owner-scoped surfaces like My Day).notifyMembership(c, …)— handle membership add/remove, which must also notify the user whose access just changed.
Fan-out runs off the request path and is bounded by member count; a notify failure never fails the already-committed write (constitution F-17/F-18). The internal dispatch(...) helper sends via offResponsePath(c, …), which calls c.executionCtx.waitUntil(...) in the Worker runtime and falls back to a detached run under a test harness that has no ExecutionContext — so a notify never breaks the handler. The recipient set deliberately mirrors the read-authorization rule, so a user is only ever signalled about data they can actually read.
Related: Worker API & Clerk Auth (the write routes), SyncInbox Durable Object (the delivery target).