---
kind: spec
status: active
source_of_truth: true
---

# 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.
