# Native Kanban and Canonical Task SOT — Canonical Requirements **Status:** RATIFIED and independently approved for canonical publication under issue [#751](https://git.mosaicstack.dev/mosaicstack/stack/issues/751) **Date:** 2026-07-14 **Decision owner:** Jason **Publication owner:** web1 control plane (`mos-claude`; `mosaic-100` acting during Claude quota outage) **Implementation foundation:** current `mosaicstack/stack` main only **Implementation hold:** no feature implementation begins until this canon is squash-merged to `main` with terminal-green CI. ## 1. Purpose Deliver Mosaic Stack's native project/task control plane and thin writable Kanban on one authoritative PostgreSQL model. This document formalizes the ratified source plan; it does not create a parallel design. Normative terms **MUST**, **MUST NOT**, **SHOULD**, and **MAY** are binding as used here. ## 2. Ratified decisions | # | Ratified decision | Canonical result | | --- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | D1 | Foundation | Extend current `mosaicstack/stack` main with its existing Drizzle/PostgreSQL, NestJS Gateway, Next.js, Better Auth, and Valkey/BullMQ conventions. No greenfield service and no Prisma revival. | | D2 | Tenant boundary | `workspace_id` is the hard tenant boundary from the first migration. Teams are authorization groups inside a workspace, never tenant substitutes. | | D3 | Outage authority — Option A with amendment | PostgreSQL is the sole writable SOT and mutations fail closed whenever DB write-health cannot be proven. The amendment permits deployment-specific **recovery posture only**; it does not permit an alternate writer. Human outage notes are attributable post-recovery proposals, never shadow state. | | D4 | Generated files | `TASKS.md`, `mission.json`, and any file export are generated, read-only, non-authoritative, and never import sources. Generate on demand; commit only where repository review policy requires a snapshot. | | D5 | Status model | Task statuses are `backlog`, `ready`, `in_progress`, `blocked`, `in_review`, `done`, `cancelled`. Runtime readiness is orthogonal and computed. | | D6 | Coordinator approval | Hybrid: manual Project Sub-Orchestrator approval by default; automatic routing only under an explicit, approved, versioned low-risk policy. | | D7 | Initial migration scope | Project, mission, milestone, task, tags/archive, dependency, assignment, outage proposal, evidence/link, and orchestration state only. Calendar, email, GLPI cache, and personal-brain features remain out of scope. | ## 3. Fixed invariants — every deployment These are not tier settings and cannot be weakened by deployment configuration. 1. PostgreSQL is the **sole writable source of truth**. 2. The implementation uses Drizzle on current stack main. 3. Kanban and orchestration mutations **fail closed** unless DB write-health is positively proven `healthy`. 4. No failed mutation is redirected to Markdown, JSON, browser storage, Valkey, queue payloads, scratchpads, or provider issues. 5. `TASKS.md` and all file exports are generated, read-only, non-authoritative, and never parsed for import. 6. Human notes created during an outage become attributable proposals only after recovery. They do not reserve work, change status, satisfy a gate, or establish ordering. 7. Valkey is derived, expendable coordination infrastructure. PostgreSQL retains task truth, leases, fencing, audit, and the transactional outbox. 8. The Mechanical Coordinator is non-LLM and deterministic. It may evaluate eligibility, dependencies, approval policy, leases, fencing, heartbeat, retry, expiry, and quarantine. It cannot invent scope, alter acceptance criteria, waive gates, certify, or merge. 9. **Certifier** is the final independent quality-gate role. Certifier may pass, reject, or escalate with evidence; it has no merge authority. 10. Every business and orchestration record is workspace-scoped; cross-workspace relationships are rejected. 11. Every mutation is idempotent and expected-version checked where it changes an aggregate. 12. Stale worker mutations are rejected by monotonically increasing fencing tokens. 13. Audit events are append-only and attributable; authoritative state is reconstructable from PostgreSQL without Valkey or files. ## 4. Configurable recovery posture only Deployment tiers configure durability and operational recovery targets. They never configure SOT authority, fail-open writes, or gate bypass. ### 4.1 Tier defaults | Setting | Lite | Standard | High-assurance | | --------------------------- | --------------------------------------: | ------------------------------------------------------------: | ----------------------------------------------------------------------: | | Target RPO | 24 hours | 1 hour | **15 minutes** | | Target RTO | 24 hours | 8 hours | **4 hours** | | Base backup cadence | Daily | Daily | **Daily** | | WAL archive cadence | Disabled | Every 15 minutes | **Every 5 minutes** | | PITR retention | 0 days / disabled | 14 days | **35 days** | | Restore test frequency | Quarterly | Quarterly | **Monthly** | | Break-glass drill frequency | Annually | Semiannually | **Quarterly** | | Off-cluster storage | One encrypted off-cluster backup target | Encrypted off-cluster object storage, separate failure domain | **Encrypted off-cluster base backups and WAL, separate failure domain** | A deployment MAY override defaults only through the validated recovery-posture contract. An override MUST record actor, reason, effective time, and policy revision. A claimed RPO MUST be no smaller than the actual backup/WAL mechanism can support. Enabling PITR requires WAL archival and off-cluster storage. ## 5. Functional requirements and acceptance criteria ### REQ-SOT-001 — Sole writable PostgreSQL authority **Requirement:** All project, mission, milestone, task/tag/archive, dependency, assignment, execution/quarantine, lease, checkpoint, approval, outage proposal, event, link, artifact, and outbox mutations MUST commit through Gateway domain services into PostgreSQL. **Acceptance:** - Mutation journey tests show web, CLI, MCP, and agents invoke typed Gateway commands. - Static/process inventory finds no file, Valkey, browser, or provider issue writer acting as canonical state. - PostgreSQL state survives Valkey loss and reconstructs the same aggregate revisions. ### REQ-SOT-002 — Fail-closed mutation health **Requirement:** A mutation MUST execute only while health state is `healthy`. `read-only-degraded` and `write-unavailable` MUST return the frozen deliberate-denial error contract and MUST NOT enqueue a hidden write. **Acceptance:** - Public health response is a discriminated union; contradictory state/proof combinations fail contract validation. - Mutation methods accept only a fresh internal PostgreSQL transaction-local write proof, never caller-asserted/public health state. - Negative tests reject expired proofs, policy-revision mismatch, Valkey-only liveness, and caller-forged `healthy`. - Fault tests force both degraded states and prove row counts, outbox, files, and Valkey remain unchanged. - Exact failure mapping proves authoritative 503 denial, retryable 502/504/timeout uncertainty, and 409 version conflict cannot cross-map. - Replaying the same idempotency key after recovery returns one canonical result. ### REQ-SOT-003 — Generated projections **Requirement:** `TASKS.md`, `mission.json`, and other exports MUST contain a non-authoritative header, workspace/project IDs, generated time, and source revision. No production parser may mutate DB from an export. **Acceptance:** - Generated output matches the API snapshot revision. - Hand editing a projection fails CI validation or is overwritten by regeneration. - Repository search finds no import path from generated projections. ### REQ-SOT-004 — Attributable outage proposals **Requirement:** Human outage notes MAY be captured outside the system but, after recovery, can enter Mosaic only through workspace-scoped `change_proposals` attributed to an authenticated active member. A proposal stores source-note digest, target aggregate/version, typed command/payload, idempotency, lifecycle, decision actor/reason/time, and audit links. It MUST NOT silently change canonical state. **Acceptance:** - `(workspace_id, submitted_audit_event_id)` and `(workspace_id, accepted_command_audit_event_id)` are composite foreign keys to `task_events(workspace_id, id)`; missing and foreign-workspace event IDs fail before commit. - Submission preallocates the proposal ID and atomically inserts `change_proposal.submitted` for that exact workspace/proposal with the new proposal referencing it. - Accept locks proposal and target, obtains fresh write proof, checks expected version, executes the normal typed command, and atomically links that command's event for the same workspace/target and proposal causation. - Negative tests reject missing submission events, foreign-workspace submission/acceptance events, and same-workspace events for an unrelated proposal, aggregate, target, or command. - Tests prove a pending/rejected proposal cannot claim/order work, satisfy a dependency/gate, or mutate any target directly. ### REQ-TEN-001 — Workspace hard tenancy **Requirement:** Every canonical business/orchestration row MUST carry `workspace_id`. Workspace-aware constraints and authorization MUST prevent cross-tenant relationships and reads/writes. **Acceptance:** - API, repository, import, WebSocket, and Coordinator negative tests reject foreign-workspace IDs without existence oracles. - Project/task owners use exactly-one user/team references; assignment principals use exactly-one user/team/agent reference; agent/session targets are workspace-consistent. - User owners, principals, proposers, and decision actors require ACTIVE workspace membership in the authoritative transaction. - Dependency, project hierarchy, assignment, lease, checkpoint, approval-evidence, link, artifact, proposal target, and both proposal-audit-event composite relationships reject mixed workspaces. - Tenant context is derived from authenticated authority, never accepted blindly from request data. ### REQ-ID-001 — Workspace identity and service scope **Requirement:** Users, teams, agents, and agent sessions MUST be bound to a workspace with explicit role/capability scope. Agents MUST NOT receive raw DB credentials. **Acceptance:** - Workspace membership and service-identity tests enforce command-family scope. - Revoked/disabled agents and ended sessions cannot claim, heartbeat, or submit. ### REQ-PLAN-001 — Normalized planning hierarchy **Requirement:** Canonical planning entities are projects, milestones, missions, mission-milestone associations, and tasks. A task belongs to one required project and at most one mission/milestone/parent task. **Acceptance:** - CRUD tests preserve workspace, hierarchy, versions, and lifecycle constraints. - Mission membership does not duplicate task status. - Composite project-congruent constraints reject task→mission, task→milestone, task→parent, mission→milestone, and project→current-milestone mismatches. - Parent and association constraints reject cycles/orphans where applicable. ### REQ-TASK-001 — Canonical task fields **Requirement:** Tasks MUST support title, description, structured acceptance criteria, canonical status, priority, fractional board rank, accountable owner, assigned specialist role, due/not-before dates, estimate, progress, explicit blocker, retry policy, normalized workspace tags, non-lifecycle archival (`archived_at/by/reason`), metadata, monotonic fencing counter, and optimistic version. **Acceptance:** - API and UI round-trip every field without silent loss. - Current `tasks.tags`, `assignee`, and `due_date` remain declared/preserved during N-1 and backfill to the canonical model without loss. - Archive hides work without changing its canonical lifecycle status and requires actor/reason/time. - Invalid status, rank, progress, date, owner, tag, archive, or retry data is rejected. - Concurrent expected-version updates produce a visible conflict. ### REQ-TASK-002 — Fixed lifecycle and computed readiness **Requirement:** Human workflow status MUST use the seven ratified values. Dependency/schedule/policy/lease/retry conditions MUST be exposed as computed readiness, not hidden status rewrites. **Acceptance:** - A dependency becoming incomplete changes readiness but does not silently rewrite the Kanban column. - Readiness explanation identifies all active gates. - State-machine tests reject illegal transitions and require reasons for blocked/cancelled paths. ### REQ-DEP-001 — Dependency DAG **Requirement:** Workspace-local directed dependencies MUST be unique and acyclic. A task is dependency-eligible only after every blocking predecessor is `done` and completion conditions pass. **Acceptance:** - `(workspace_id, predecessor_task_id, successor_task_id)` is unique independent of dependency type. - Cycle, duplicate, self-edge, and cross-workspace attempts fail before commit. - Property/concurrency tests prove all blocking predecessors are evaluated. - UI displays dependency and readiness errors accessibly. ### REQ-ASN-001 — Assignment is not a lease **Requirement:** Assignment history and execution leases MUST be separate records. One persisted assignment identity freezes task version, exact target agent/session (or exactly-one non-agent principal), specialist role, expiry, state, policy revision, proposer, reason, and timestamps. Approval decisions relate to that assignment with workspace-aware constraints. **Acceptance:** - One assignment-state vocabulary is identical across schema, DTO, and engine. - Lease acquisition accepts IDs only, then reloads and locks assignment, approval, task, and target session to verify workspace, current task version, exact target, state, expiry, and policy revision. - Reassignment preserves history; assignment may exist without a lease; lease expiry does not erase ownership/evidence. ### REQ-AUD-001 — Semantic audit and outbox **Requirement:** Mutating commands MUST append semantic `task_events` with actor, correlation, causation, idempotency key, and aggregate versions in the same transaction as state. Notifications MUST flow from a transactional outbox. **Acceptance:** - Atomicity tests prove state/event/outbox commit or roll back together. - Proposal submission and acceptance tests prove their workspace-bound event links identify the exact submission and executed normal command, not merely an existing event UUID. - Duplicate idempotency keys return the prior result without duplicate events. - `task_events`, checkpoints, immutable artifacts, and evidence joins are INSERT/SELECT-only for application roles; parent hard deletes are RESTRICTed. - Normal lifecycle uses archive/cancel, never hard delete; retention purge requires audited break-glass authority and evidence. - Valkey outage leaves outbox pending and later replayable. ### REQ-API-001 — Typed Gateway command boundary **Requirement:** Gateway MUST expose workspace-safe project/task/dependency/assignment/link/artifact/change-proposal queries and explicit lifecycle commands. Generic patching MUST NOT bypass claim, heartbeat, review, certify, proposal acceptance, or completion invariants. **Acceptance:** - KBN-105 freezes exact route, request, success, denial, conflict, and transport-normalization DTOs before CLI/web implementation. - DTO validation, authorization, contract, and integration tests cover each command. - Exact MCP-owned Gateway files are coder3-owned; coder4 consumes only frozen Gateway contracts. - Endpoint registry aligns web, CLI, MCP, and generated client paths. - Direct SQL and raw Valkey writes are absent from clients. ### REQ-UI-001 — Writable thin Kanban/List MVP **Requirement:** Existing Tasks and Projects surfaces MUST become a real-data writable MVP with one shared query contract. **Acceptance:** - Users can create/edit/cancel/archive tasks, open task detail, and move cards within/across columns. - Server validates transition and persists fractional board rank. - Refresh, reconnect, CLI, MCP, and generated projection show the same revision. ### REQ-UI-002 — Tenant and work context **Requirement:** UI MUST show workspace context and support filters for project, mission, milestone, status, priority, owner/specialist, due state, and tags. **Acceptance:** - Context is visible on every mutation surface. - Filter tests cannot expose foreign-workspace data. - Empty/loading/error states are explicit. ### REQ-UI-003 — Dependency, ownership, lease, and audit visibility **Requirement:** Task detail MUST separate accountable owner, specialist assignment, active session/lease expiry, dependencies/readiness, acceptance criteria, blocker, external links, and audit timeline. **Acceptance:** - Each concept renders from its canonical endpoint. - A lease is never displayed as ownership or completion. - Conflict and stale-reconnect states require refresh rather than silent overwrite. ### REQ-UI-004 — Accessible interaction **Requirement:** Kanban MUST support keyboard-accessible moves, non-drag alternatives, responsive layout, and semantic status/error announcements. **Acceptance:** - Keyboard journey performs every card transition available by drag. - Automated accessibility checks and manual responsive checks pass. ### REQ-COORD-001 — Non-LLM Mechanical Coordinator **Requirement:** Coordinator decisions MUST be deterministic from structured data and versioned policy. It MUST NOT invoke an LLM to interpret scope or acceptance criteria. **Acceptance:** - Pure decision engine receives complete immutable snapshots and performs no ID loading, SQL, Gateway, Valkey, or recovery I/O. - Persistence/service adapter owns ID loading, transaction-local write proof, locking, persistence, and `recoverFromPostgres`. - Same snapshot and policy revision produce the same eligibility/order explanation. - Dependency, schedule, durable retry/quarantine, approval, role, and capacity inputs are auditable. - Code/config inspection finds no model/provider dependency in the scheduling engine. ### REQ-COORD-002 — Eligibility and approval routing **Requirement:** Only `ready` tasks under active project/mission, passed dependencies/schedule/retry/release policy, and without active lease may be proposed. Manual approval is default; auto-route requires an explicit approved policy revision. **Acceptance:** - Unapproved or gated tasks are never leased. - Every persisted assignment proposal includes task version, exact target agent/session, expiry, state, deterministic reasons, and policy revision. - Approval is relationally bound to the assignment identity and cannot be supplied as a forgeable proof-by-value DTO. - Override/reject/reassign requires an attributable reason. ### REQ-COORD-003 — Atomic lease, heartbeat, fencing, and recovery **Requirement:** Lease acquisition MUST be atomic in PostgreSQL, permit at most one active lease per task, atomically increment the durable per-task fencing counter under task lock, use bigint-safe tokens, require timely acknowledgement/heartbeat, and reject stale workers. Lease and checkpoint relations MUST bind the exact workspace+task+assignment/session+fence. **Acceptance:** - Concurrent claim tests yield one winner and strictly increasing fencing tokens. - Lower/expired tokens and mismatched same-workspace task/assignment/lease/checkpoint IDs fail. - Token values round-trip as bigint/decimal strings without JavaScript precision loss. - Coordinator restart reconstructs lease/retry/quarantine state from PostgreSQL alone. ### REQ-COORD-004 — Retry and quarantine **Requirement:** Missing acknowledgement, agent loss, or execution failure MUST produce a deterministic release, bounded backoff retry, or quarantine outcome according to retry policy. Ambiguous/non-idempotent work requires Sub-Orchestrator action. **Acceptance:** - Durable execution state records disposition, attempt/max, next eligibility, terminal reason, actor/policy, timestamps, and version. - Retry budget/backoff are bounded and tested. - Exhausted or non-idempotent failures quarantine with workspace-scoped artifact evidence. - One specialist-role vocabulary is enforced across schema, sessions, assignments, DTOs, and engine. - No task loops indefinitely or silently returns to ready. ### REQ-GATE-001 — Role and authority chain **Requirement:** Canonical flow is User → Interaction → Portfolio Orchestrator → Project Sub-Orchestrator → Gateway → domain services → Mechanical Coordinator → specialists → Certifier. **Acceptance:** - Role bindings and approvals are queryable and audited. - Coordinator cannot create scope or waive gates. - Certifier cannot merge or close provider artifacts. ### REQ-GATE-002 — Independent review and certification **Requirement:** Author and reviewer MUST differ. Auth, security, tenant, secrets, and data-integrity surfaces MUST receive mandatory SecReview. Certifier is the final quality gate after remediation. **Acceptance:** - Gate tests reject author self-review and missing required SecReview. - Certifier receives complete traceability/evidence and returns pass/reject/escalate. - A Certifier pass does not grant merge authority. ### REQ-REC-001 — Recovery posture validation **Requirement:** A deployment MUST select a validated Lite, Standard, or High-assurance posture and MAY override only recovery knobs. **Acceptance:** - Runtime invokes normative `validateRecoveryPostureV1`, not shape-only JSON Schema validation. - Validator rejects PITR/WAL mismatch, impossible RPO, unknown fields, non-encrypted/non-separated storage, and weakened High-assurance values. - A bounded recovery/infra slice owns parser wiring, override audit, mechanism verification, restore test, and break-glass evidence. - High-assurance defaults equal RPO 15m/RTO 4h, encrypted off-cluster WAL every 5m, 35d PITR, daily base backup, monthly restore test, and quarterly break-glass. ### REQ-MIG-001 — One-way shadow migration **Requirement:** Migration from jarvis-brain/Vikunja MUST use inventory, immutable source snapshots/checksums, one-way shadow import, read reconciliation, write freeze, final delta, cutover, and read-only stabilization. Dual writes are forbidden. **Acceptance:** - P0 publishes the current `origin/main` field-by-field expand/backfill/compatibility/switch/contract map before any schema lane starts. - Legacy columns remain in the unified Drizzle declaration for the entire expand/N-1 window. - Dry-run/apply/verify modes are idempotent and workspace-safe. - Import lineage preserves source system/key/file/checksum/batch and rejected-record reports. - Empty DB, production-shape, partial-resume, downgrade/rollback, status-shadow, workspace-backfill, and `mission_tasks.status` retirement tests pass. - Shadow records cannot auto-dispatch. ### REQ-MIG-002 — Cutover and rollback safety **Requirement:** Cutover MUST disable legacy writers and switch all clients to Gateway. Before first DB mutation rollback may switch authority back; afterward rollback requires freeze, DB-delta export/reconciliation, and owner decision. **Acceptance:** - Process inventory proves no active jarvis-brain/Vikunja project/task writer. - Cutover rehearsal meets signed reconciliation thresholds. - No reverse and forward sync run concurrently. ## 6. Explicit non-goals The P0–P3 canon does not authorize: - replacing Gitea issue/PR storage; - calendar, email, GLPI cache, CRM, billing, time tracking, or personal-brain migration; - arbitrary custom workflows/statuses/fields; - a writable offline/file/Valkey/browser fallback; - direct client database access; - LLM scheduling or autonomous scope invention; - Coordinator gate waiver, certification, merge, release, or provider issue closure; - Certifier merge authority; - full mission designer, portfolio analytics, critical-path UX, or advanced board customization in the thin MVP; - P4/P5 features unless separately released. ## 7. Global release evidence P0–P3 may close only when requirements traceability maps every requirement above to automated and situational evidence, including cross-workspace denials, DB/Valkey fault injection, concurrent leases, stale fencing, generated-file immutability, UI conflict/reconnect behavior, migration reconciliation, independent review, mandatory SecReview, and final Certifier evidence.