The eight entities
Temporal classes
WorkTruck tracks history at four different fidelities:- Bitemporal (People, Organizations, Notes) — both valid-time and system-time tracked. Every edit writes a history row; “what did this person look like on Tuesday at 3pm” is answerable.
- Unitemporal (Tasks) — valid-time only. History rows on every edit; system-time of the edit isn’t preserved.
- Type 0 (Events, Messages) — no history. Designed for high-volume streams where the cost of full history would dominate the table.
- Event-log (Relationships) — insert-only. Updates and deletes are recorded as new rows with a kind discriminator.
docs/schema-review/temporal.md for the rationale.
Relationships are first-class
Almost every meaningful connection in WorkTruck is a row in therelationships table — Person attends Event, Note is about Task, File attached to Message, Organization employs Person. The relationship’s relationship_type field is a typed enum; the matrix of which (from-entity-type, to-entity-type, relationship_type) tuples are allowed lives in internal/relationships/matrix.go as the authority, with a Postgres CHECK constraint as defense-in-depth.
Agents query relationships in either direction — “all tasks about this Person”, “all Files attached to this Message” — without needing to know the underlying join.
Two write paths: API and worker
Agents write to WorkTruck two ways:- Synchronous via HTTP / MCP / CLI — direct CRUD. Fast, immediate, used by the dashboard and ad-hoc operator tooling.
- Asynchronous via the worker — reconciler jobs (email → person, message → thread), scheduled agent runs, retention/cleanup. Worker is river-backed; jobs are durable.