The board.* family (16 verbs). Every verb enters through the one front door: it is capability-checked, permission-checked, scope-checked and audited before it runs (see Security & permissions). Each entry below lists its capability, risk class (which fixes the minimum autonomy level), the minimum caller permission, its availability tier, whether it is idempotent, and any outbound egress.
Archiveboard.archive
| Property | Value |
|---|---|
| Capability | board.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
Withdraw a board from NEW instantiation: DRAFT|ACTIVE →
ARCHIVED. { id }. An ARCHIVED board can no longer instantiate new matters (matter.create already
refuses a non-ACTIVE board); EXISTING matters are unaffected (they pinned instantiatedFromVersion,
R11 - the published Version snapshot is immutable, INV-8). History + in-flight instances are
retained-not-deleted (INV-8); reversible only via authoring a new version. Mirrors party.archive/
portal.archive/doc.archive (status-not-timestamp, INV-3; never a hard DELETE).
Call POST /v/board.archive with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.archive.
Createboard.create
| Property | Value |
|---|---|
| Capability | board.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
author a new DRAFT Board/Template. { key, title, description?, phases? }.
Input
| Field | Type | Required | Description |
|---|---|---|---|
key | string | yes | |
title | string | yes | |
phases | object | yes | {version, phases:[{id,name,traversalMode,onComplete,steps:[…]}]} |
Call POST /v/board.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.create.
Editboard.edit
| Property | Value |
|---|---|
| Capability | board.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
re-draft a DRAFT board’s body. { id, title?, description?, phases? }.
Only DRAFT boards are editable (a published version is immutable, R11).
Call POST /v/board.edit with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.edit.
Getboard.get
| Property | Value |
|---|---|
| Capability | board.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
one board definition. { id }.
Input
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes |
Call POST /v/board.get with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.get.
Listboard.issue.list
| Property | Value |
|---|---|
| Capability | board.issue.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
list projected issues for a matter (or the whole tenant). { matterId? }.
READ/L0. The issues are a VIEW of PG MatterStep state; never read as the SoR.
Call POST /v/board.issue.list with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Reassignboard.issue.reassign
| Property | Value |
|---|---|
| Capability | board.issue.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
reassign a board_issue’s projected ASSIGNEE (ownership-only). WRITE/L1/ADMIN.
{ issueId, toAssignee }. Mirrors review.reassign: a guarded UPDATE ... WHERE id=$ AND workspace_id=$ move of the projected owner - rows_affected==0 ⇒ the issue does not exist in THIS
workspace (fail-closed not-found; the RLS/IDOR fence). Ownership/attribution ONLY: the board is a
VIEW (INV-6), so this NEVER writes matter/step state - it moves WHO owns the projected ticket, never
the work itself (the work moves only via matter.advance, INV-1). toAssignee is the kernel principal
(an org-node/actor id board.principal.resolve maps to an external board user).
Call POST /v/board.issue.reassign with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Syncboard.issue.sync
| Property | Value |
|---|---|
| Capability | board.issue.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
project/refresh a matter’s issues from its current MatterStep state.
{ matterId }. Idempotent: re-syncing upserts the same issue set (INV-2 re-sync safe). PG is the
SoR; this is a kernel->board projection (one direction), never a board->matter write (ADR-0002).
Call POST /v/board.issue.sync with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.issue.sync.
Handleboard.issue.webhook.handle
| Property | Value |
|---|---|
| Capability | board.issue.write |
| Risk class | Write - autonomy L1 |
| Min. permission | External (portal / signer token) |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
the ONE idempotent inbound seam (WRITE/L1/EXTERNAL, idempotent).
{ issueId | externalRef, transition, deliveryKey, signature, note? }.
An HMAC-verified board webhook. A terminal ticket transition (e.g. “done”) routes to
matter.advance(matter_id, step_id) - the ONE write path (INV-1). The handler NEVER writes
matter/step status directly: it resolves the linkage, then re-enters matter.advance.
• HMAC over the raw signed body (NFR-SEC-5); a bad/missing signature is a fail-closed deny.
• Idempotent on deliveryKey (TASK-BOARDS-05): a redelivery is a no-op, never a double-advance.
• Unknown linkage / unknown transition is rejected/ignored safely (fail-closed).
Call POST /v/board.issue.webhook.handle with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Listboard.list
| Property | Value |
|---|---|
| Capability | board.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
list boards in the workspace (optionally filter by status). { status? }.
Call POST /v/board.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.list.
Resolveboard.principal.resolve
| Property | Value |
|---|---|
| Capability | board.issue.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
map a KERNEL principal (org-node/actor) <-> an EXTERNAL board user.
WRITE/L1/ADMIN. { principalId, externalUserId, externalSystem? }. ONE idempotent linkage upsert
(one row per (workspace, principal, externalSystem)): re-resolving the SAME pair re-points the
EXISTING row (a moved external account), never a duplicate. The linkage is the cross-system id map
the projection reads to render board_issue.assignee against the external board - it carries ONLY
the id pairing, NEVER a copy of the actor’s role/grant (steering #1: the org/actor stays the SoR).
Call POST /v/board.principal.resolve with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.principal.resolve.
Publishboard.publish
| Property | Value |
|---|---|
| Capability | board.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
validate the DRAFT body, forward-mint an immutable Version, DRAFT→ACTIVE,
point current_version at the minted version. { id, changelog? }. R11: snapshot-not-live.
Input
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
changelog | string | no |
Call POST /v/board.publish with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.publish.
Regenerateboard.regenerate
| Property | Value |
|---|---|
| Capability | board.issue.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
tenant-wide reconcile: re-project EVERY matter’s steps -> board_issue. WRITE/L1/
ADMIN, IDEMPOTENT. The bulk twin of board.issue.sync: it walks every matter in THIS workspace and
upserts the same per-step linkage (the issue_sync upsert, applied workspace-wide), so a re-run mints
no duplicates (the uq_board_issue_matter_step arbiter + last_projected_version bump). PG is the SoR
(ADR-0002): this is a one-direction kernel->board refresh, never a board->matter write. Matters whose
board has been HALTED (board.stop-projecting; board.projecting=false) are SKIPPED - no new view rows
are minted for a stopped board (existing rows retained, INV-8).
Call POST /v/board.regenerate with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.regenerate.
Setboard.step.condition.set
| Property | Value |
|---|---|
| Capability | board.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Set step conditional-visibility on a DRAFT board. Rule-builder write path (US-RENDER-28). Accepts TWO exclusive forms:
- boolean (M1):
{conditionalVisibility:{visible:bool, onFail?:skip|block}} - fact-guard (TASK-MATTER-10):
{conditionalVisibility:{requiresFact:{factKey, targetType?, onFail?}}}DRAFT-board-only. Step must exist (BadInput if missing). The whole conditionalVisibility object is stored verbatim (the engine’s visibility() reads it); exactly one form must be present.
Call POST /v/board.step.condition.set with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.step.condition.set.
Stop projectingboard.stop-projecting
| Property | Value |
|---|---|
| Capability | board.issue.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
reversibly HALT a board’s matter->board_issue projection. WRITE/L1/ADMIN.
{ boardId }. Sets board.projecting=false: while OFF, board.regenerate / board.issue.sync mint NO
new view rows for that board’s matters. REVERSIBLE (a resume flips it back to true) and
NON-DESTRUCTIVE: existing board_issue rows are RETAINED, never hard-deleted (INV-8: regenerable view).
Guarded UPDATE ... WHERE id=$ AND workspace_id=$ (the RLS/IDOR fence); a re-stop of an already-halted
board is an idempotent no-op success.
Call POST /v/board.stop-projecting with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool board.stop-projecting.
Statusboard.sync.status
| Property | Value |
|---|---|
| Capability | board.issue.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
sync-health for a matter/tenant. { matterId? }. READ/L0.
Reports last-projected-version + stale/orphan/missing counts (the boards twin of connection.status).
• stale = a projected issue whose projected_state != the live PG step status (a refresh is due)
• orphan = a projected issue whose linked matter_step no longer exists (PG won; the issue lags)
• missing = a live PG step with NO projected issue yet (the projection is behind)
Call POST /v/board.sync.status with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Validateboard.validate
| Property | Value |
|---|---|
| Capability | board.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
save-time validatePhases + step-type-exists + cycle check. { id } or { phases }.
Returns { valid, errors[], normalized }. Never mutates (READ).
Call POST /v/board.validate with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.