Skip to content

Task Attributes API

A Task is a child of a List with a title plus a set of attributes (Product Brief §5.2 “Task rules”). The fields and their HTTP surface are defined contract-first in src/api/routes/tasks.ts (registerTasksRoutes) over the tasks table.

The route module owns the Task fields, persists them to D1, and fans a signal to the List’s accessible users:

flowchart LR
  RT["registerTasksRoutes<br/>src/api/routes/tasks.ts"] --> TBL[("D1: tasks<br/>done, starred, dueDate,<br/>notes, assigneeId, rank")]
  RT --> NL["notifyList()<br/>src/api/lib/notify.ts"]
  RT --> REC["reconcileTasks<br/>(Sync-Core Reconcilers)"]
  AID["assigneeId"] -.->|"Member of List"| LM[("D1: listMembers")]
  CLIENT["client (optimistic write)"] -->|"PATCH field"| RT
  • done — completion state. (Recurring-task behavior — a new instance on completion — is a domain rule; recurrence fields are future scope.)
  • starred — marks the Task “important” (feeds the “Important” View).
  • dueDate — date only (YYYY-MM-DD), nullable (feeds “Planned”).
  • notes — plaintext, nullable, with notesUpdatedAt for last-write-wins reconciliation.
  • assigneeId — at most one Member of the Task’s List; assigning to the owner is allowed; removing the assignee clears it (spec 012). assignedToMe is derived per requesting user.
  • rank — fractional order within the List (new Tasks at the top).

Per-field updates go through PATCH routes with Zod schemas (the OpenAPI contract, ADR-003); validation failures return RFC 9457 422 (see Worker API & Clerk Auth). Writes are optimistic on the client and reconciled server-side (reconcileTasks, Sync-Core Reconcilers); a successful write fans a signal to the List’s accessible users (DB Schema & Notify-Affected).

A single attribute PATCH validates, writes one field, then signals everyone with access to the List:

sequenceDiagram
  participant Client
  participant RT as "registerTasksRoutes (PATCH)"
  participant D1 as "D1: tasks"
  participant Notify as "notifyList()"
  Client->>RT: PATCH /v1/lists/{listId}/tasks/{taskId}
  RT->>RT: Zod validate (else 422)
  RT->>D1: update field (done / starred / dueDate / notes / assigneeId / rank)
  D1-->>RT: updated Task
  RT->>Notify: notifyList(c, listId, surfaces)
  RT-->>Client: 200 Task (assignedToMe derived per user)
  Note over Notify: signals owner ∪ active members

Related: DB Schema & Notify-Affected, Sync-Core Reconcilers, Steps in a Task (Task children).