27 KiB
Native Kanban and Canonical Task SOT — Canonical Requirements
Status: RATIFIED and independently approved for canonical publication under issue #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.
- PostgreSQL is the sole writable source of truth.
- The implementation uses Drizzle on current stack main.
- Kanban and orchestration mutations fail closed unless DB write-health is positively proven
healthy. - No failed mutation is redirected to Markdown, JSON, browser storage, Valkey, queue payloads, scratchpads, or provider issues.
TASKS.mdand all file exports are generated, read-only, non-authoritative, and never parsed for import.- 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.
- Valkey is derived, expendable coordination infrastructure. PostgreSQL retains task truth, leases, fencing, audit, and the transactional outbox.
- 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.
- Certifier is the final independent quality-gate role. Certifier may pass, reject, or escalate with evidence; it has no merge authority.
- Every business and orchestration record is workspace-scoped; cross-workspace relationships are rejected.
- Every mutation is idempotent and expected-version checked where it changes an aggregate.
- Stale worker mutations are rejected by monotonically increasing fencing tokens.
- 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 totask_events(workspace_id, id); missing and foreign-workspace event IDs fail before commit.- Submission preallocates the proposal ID and atomically inserts
change_proposal.submittedfor 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, anddue_dateremain 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/mainfield-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.statusretirement 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.