Files
stack/docs/requirements/native-kanban-sot.md
jason.woltje 49e8a54105
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
docs(#751): Publish native Kanban/SOT canon (#752)
2026-07-14 17:08:09 +00:00

27 KiB
Raw Blame History

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.

  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 P0P3 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

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