The doc.* family (62 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.
Annotatedoc.annotate
| Property | Value |
|---|---|
| Capability | doc.annotate |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
type ∈ {BOUNDING_BOX, ARROW, COMMENT}; coords normalized 0..1 (INV-6 - pixel
positions computed at render, never stored). An out-of-0..1 coord / page<1 / unknown type is a
fail-closed BadInput (INV-11) BEFORE any write. The File must exist in THIS workspace (RLS + FK).
Input { fileId, type, pageNumber, x,y,w,h, endX?,endY?, color?, label?, criterion?, comment? } (fields ending in ? are optional)
Call POST /v/doc.annotate with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.annotate.
Getdoc.annotation.get
| Property | Value |
|---|---|
| Capability | doc.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 |
Returns every annotation on the File (RLS-scoped), in page+creation order.
Input { fileId } (fields ending in ? are optional)
Call POST /v/doc.annotation.get with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Removedoc.annotation.remove
| Property | Value |
|---|---|
| Capability | doc.annotate |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Removes the annotation (RLS-scoped). Not found → BadInput (fail-closed).
Input { annotationId } (fields ending in ? are optional)
Call POST /v/doc.annotation.remove with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Archivedoc.archive
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
A destructive operation in the doc.* family. Called through the one governed front door: capability, permission tier, autonomy, scope and egress are all resolved before the handler runs, and the call is audited (INV-1, INV-8).
Call POST /v/doc.archive with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Createdoc.comment.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
user_id from acting user, workspace_id from ctx. Validates parentId resolves in the same workspace. createdAt may be backdated (docx import); else DB now().
Call POST /v/doc.comment.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.comment.create.
Deletedoc.comment.delete
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
RLS fence; idempotent (reactions+replies are FK-cascade).
Call POST /v/doc.comment.delete with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.comment.delete.
Updatedoc.comment.update
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
content edit and/or resolve toggle. RLS fence id+workspace_id. On resolve transition, sets resolved_by_id (acting user) + resolved_at; on un-resolve clears them.
Call POST /v/doc.comment.update with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.comment.update.
Createdoc.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
The DocEngine PARSES the body into (content, structural_map) - the kernel never parses OOXML.
Input
| Field | Type | Required | Description |
|---|---|---|---|
title | string | yes | |
kind | string | yes | e.g. NATIVE |
matterId | string | no | |
content | object | no | the native doc model, e.g. {paragraphs:[{runs:[{text:”…”}]}]} |
Call POST /v/doc.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.create.
Createdoc.docversion.create
| Property | Value |
|---|---|
| Capability | doc.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) |
on (document_id,version). Fence the documents table in workspace. NOTE: distinct from doc.version.snapshot (which backs the KERNEL document_version singular).
Call POST /v/doc.docversion.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.docversion.create.
Editdoc.edit
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | Doc engine - the co-located document service (policy-gated rail) |
| High-risk oversight | Human four-eyes approval in HIGH-risk orgs (EU AI Act Art. 14) |
{ id, patches:[{op,…}], trackChanges? }. WRITE/L1.
The edit goes through the DocEngine apply_patches port: it mutates the addressed paragraphs/runs
SURGICALLY and PRESERVES the structural_map (the verbatim ~35%-unmodeled blob is byte-identical
out as in). It NEVER rebuilds the whole document from the content/StructuralMap (the foreclosed
anti-pattern). When track-mode is on, each run-delta becomes a TrackedChange record (rt-006).
Call POST /v/doc.edit with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.edit.
Extractdoc.extract
| Property | Value |
|---|---|
| Capability | doc.extract |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | Doc engine - the co-located document service (policy-gated rail) |
| High-risk oversight | Human four-eyes approval in HIGH-risk orgs (EU AI Act Art. 14) |
{ fileId?, docKind?, mapping, target:{type,id}, fields:{key:{value,confidence,pii?}}, confidenceThreshold? }.
SENSITIVE/L2. Reads typed Facts out of a binary doc under an INV-9 quality gate:
• a REQUIRED field below the threshold is NOT written - recorded LOW + routed to Review (a stub id).
• an OPTIONAL low-confidence field is recorded (visible), not silently dropped.
• a high-confidence field is written through the CANONICAL Fact path (INV-1) - encrypt-before-write
for any PII field with an explicit encryption_scheme (INV-7 - no plaintext PII column).
The coverage/quality report is written to the extraction snapshot on BOTH success and failure (INV-9).
Call POST /v/doc.extract with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Adddoc.favourite.add
| Property | Value |
|---|---|
| Capability | doc.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) |
on (document_id,user_id).
Call POST /v/doc.favourite.add with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.favourite.add.
Removedoc.favourite.remove
| Property | Value |
|---|---|
| Capability | doc.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) |
Delete own favourite by (document_id,user_id).
Call POST /v/doc.favourite.remove with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.favourite.remove.
Listdoc.gen.list
| Property | Value |
|---|---|
| Capability | doc.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
Lists the audited
generated_document snapshots (the two-phase authoring spine, INV-9/INV-8) scoped to a matterId
(the matter’s generation history) or a templateId (every generation off one doc-pack) or the whole
workspace. RLS-scoped + an explicit workspace_id = $ predicate (a cross-workspace snapshot is
unreachable). Returns metadata only (id/status/mode/template-version cursor/timestamps) - NOT the
payload/coverage blobs (those are the gated single-read generated.get). BLOCKED/FAILED snapshots are
LISTED too (the audit row exists on success AND failure, INV-9 - never silently dropped). Paginated
(NFR-PERF-3). Computes nothing authoritative (INV-14).
Input { matterId?, templateId?, status?, mode?, limit? } (fields ending in ? are optional)
Call POST /v/doc.gen.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.gen.list.
Generatedoc.generate
| Property | Value |
|---|---|
| Capability | doc.gen |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | Doc engine - the co-located document service (policy-gated rail) |
| High-risk oversight | Human four-eyes approval in HIGH-risk orgs (EU AI Act Art. 14) |
| Budget-gated | Refused when the workspace AI budget is exceeded (Owner break-glass audited) |
Two-phase (INV-9/INV-8): a generation snapshot is written on BOTH success AND failure.
- PIN the template’s CURRENT version at generation time (R11 - re-publishing later won’t drift it).
- Run the coverage gate through the DocEngine port: an unmapped REQUIRED var → BLOCK (refuse, structured error) before any document is produced; an optional missing var → a visible [MISSING] marker. A coverage report is written on both paths.
- The generate↔edit fidelity guard (INV-5 boundary): the generation RE-PARSES its own output; a non-round-tripping generation is FAILED (not silently accepted).
- On success, the produced content lands as a first-class Document and the snapshot commits.
Input { templateId, mode?, payload, matterId?, modelUsed?, agentSessionId? } (fields ending in ? are optional)
Call POST /v/doc.generate with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.generate.
Createdoc.generated.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Persist the generated-document metadata row (rendering + persistFilesToKB stay in FE). created_by_id is the acting user (nullable column).
Call POST /v/doc.generated.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.generated.create.
Adddoc.generated.file.add
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
One produced file row; fence parent in workspace.
Call POST /v/doc.generated.file.add with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.generated.file.add.
Snapshotdoc.generated.snapshot
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Post-generation audit write onto an existing row (partial).
Call POST /v/doc.generated.snapshot with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.generated.snapshot.
Getdoc.get
| Property | Value |
|---|---|
| Capability | doc.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 |
An ARCHIVED document is STILL readable (retain-not-delete, INV-8).
Input { id } (fields ending in ? are optional)
Call POST /v/doc.get with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.get.
Adddoc.label.add
| Property | Value |
|---|---|
| Capability | doc.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) |
ON CONFLICT(document_id,label) DO NOTHING + re-read.
Call POST /v/doc.label.add with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.label.add.
Removedoc.label.remove
| Property | Value |
|---|---|
| Capability | doc.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) |
Targeted single-label delete (document_id+label).
Call POST /v/doc.label.remove with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.label.remove.
Listdoc.list
| Property | Value |
|---|---|
| Capability | doc.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 |
Lists Documents scoped to a
matterId (the matter’s doc set) or parentId (a folder subtree) or the whole workspace. Returns
metadata only (title/kind/status/cursor/sensitivity) - NOT the content blob (the binary stays SoR;
doc.get is the sensitivity-gated single-read). RLS-scoped + an explicit workspace_id = $
predicate (a cross-workspace doc is unreachable). Paginated (NFR-PERF-3). Computes nothing
authoritative (INV-14). ARCHIVED docs are still LISTED (retain-not-delete, INV-8).
Input { matterId?, parentId?, kind?, status?, limit? } (fields ending in ? are optional)
Call POST /v/doc.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.list.
Createdoc.pack.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
workspace_id from ctx, created_by_id acting user.
Call POST /v/doc.pack.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.pack.create.
Deletedoc.pack.delete
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
RLS fence; idempotent (child template_pack_documents are FK-cascade).
Call POST /v/doc.pack.delete with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.pack.delete.
Adddoc.pack.document.add
| Property | Value |
|---|---|
| Capability | doc.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) |
on (pack_id,document_row_id). Fence pack in workspace.
Call POST /v/doc.pack.document.add with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.pack.document.add.
Removedoc.pack.document.remove
| Property | Value |
|---|---|
| Capability | doc.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) |
Confirm pack in workspace; delete by composite key.
Call POST /v/doc.pack.document.remove with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.pack.document.remove.
Updatedoc.pack.document.update
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Variable-extraction cache write; fence via parent pack workspace.
Call POST /v/doc.pack.document.update with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.pack.document.update.
Generatedoc.pack.generate
| Property | Value |
|---|---|
| Capability | doc.pack.gen |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | Doc engine - the co-located document service (policy-gated rail) |
| High-risk oversight | Human four-eyes approval in HIGH-risk orgs (EU AI Act Art. 14) |
[2026] VJS-CC-OPBOX 84: doc.pack.generate (SENSITIVE/Member) - orchestrate per-template doc.generate for a kernel-modeled doc PACK. Loads the package + its package_rule rows (Design B1), runs the rules interpreter (mode=once | mode=forEach over iterateOver, the loop item bound under as_alias), calls doc.generate per template, and accumulates PER-TEMPLATE PARTIAL-SUCCESS results (Design B2): one template BLOCKED/FAILED does NOT abort the pack - doc.generate writes each template’s own generation_snapshot (on success AND failure, INV-8) BEFORE returning its app-level error, so we catch the per-template failure (Conflict/BadInput, tx-safe)
- record it + continue; a genuine DB/internal error aborts the pack. The caller re-runs just the failed template (VJS-ACT 10 correction floor). Inherits doc.generate’s INV-9 coverage gate + INV-5 fidelity guard; the pack writes NO snapshot itself (doc.generate is the sole writer - DEC-15 one-writer, CC-OPBOX 80).
Call POST /v/doc.pack.generate with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.pack.generate.
Updatedoc.pack.update
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Partial conditional set; RLS fence packId+workspace_id.
Call POST /v/doc.pack.update with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.pack.update.
Declaredoc.presence.declare
| Property | Value |
|---|---|
| Capability | doc.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) |
Only (KYC linking + grant lifecycle; no user session). ctx.workspace_id = custodian workspace. Supersede-then-insert when fileId differs; else refresh; else insert. BEARERLESS.
Call POST /v/doc.presence.declare with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Expiredoc.presence.expire
| Property | Value |
|---|---|
| Capability | doc.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) |
Only (reconciliation + grant lifecycle). Mark matching rows EXPIRED in the custodian (ctx) workspace; optionally stamp pruned_at. BEARERLESS.
Call POST /v/doc.presence.expire with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Prunedoc.presence.prune
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Only. Hard-delete soft-deleted rows past pruned_at cutoff in the custodian (ctx) workspace. BEARERLESS.
Call POST /v/doc.presence.prune with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Cascadedoc.purge.cascade
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Only. Single-tx deleteMany across the 7 document child tables for one documentId (workspace-fenced where the column exists). Does NOT touch table_row / pdf_signing_field_placement / stored_file (other domains keep those as separate dispatches). Returns counts.
Call POST /v/doc.purge.cascade with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Adddoc.reaction.add
| Property | Value |
|---|---|
| Capability | doc.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) |
on (comment_id,user_id,emoji). Fence comment in workspace.
Call POST /v/doc.reaction.add with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.reaction.add.
Removedoc.reaction.remove
| Property | Value |
|---|---|
| Capability | doc.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) |
Delete own reaction by (comment_id,user_id,emoji).
Call POST /v/doc.reaction.remove with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.reaction.remove.
Renderdoc.render
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | Doc engine - the co-located document service (policy-gated rail) |
| High-risk oversight | Human four-eyes approval in HIGH-risk orgs (EU AI Act Art. 14) |
The render goes through the DocEngine port. A render FAILURE lands a FAILED row + a warning and the verb still returns OK (the canonical Document is UNTOUCHED, INV-2 - PDF is a derivative, never authoritative). Nothing on the write path gates on render success.
Input { id, format? } (fields ending in ? are optional)
Call POST /v/doc.render with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.render.
Sharedoc.share
| Property | Value |
|---|---|
| Capability | acl.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
The doc twin of matter.share -
forwards to acl.grant with object_type=‘document’ (INV-1, one write path).
Input { documentId, granteeType, granteeId, level } (fields ending in ? are optional)
Call POST /v/doc.share with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.share.
Adddoc.signer.add
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Fence parent generated_documents in workspace; refuse if parent status is terminal (SENT|COMPLETED|VOIDED). lowercase email. signer_index defaults to order.
Call POST /v/doc.signer.add with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.signer.add.
Actdoc.signoff.act
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Same-tx append document_signoff_event + update signoff status. action: sign|reject -> SIGNED|REJECTED (+ signed_at, comment); rescind -> PENDING (clear comment+signed_at).
Call POST /v/doc.signoff.act with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.signoff.act.
Configuredoc.signoff.configure
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Set mode on all signoff rows for a document.
Call POST /v/doc.signoff.configure with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.signoff.configure.
Createdoc.signoff.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Compute next order, inherit mode from existing rows. Unique (document_id,user_id) -> Conflict ‘already a signatory’.
Call POST /v/doc.signoff.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.signoff.create.
Removedoc.signoff.remove
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Delete the row then re-sequence remaining rows to contiguous order.
Call POST /v/doc.signoff.remove with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.signoff.remove.
Archivedoc.template.archive
| Property | Value |
|---|---|
| Capability | doc.template.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 doc-pack from NEW generation: DRAFT|ACTIVE → ARCHIVED.
doc.generate already refuses a non-ACTIVE template, so an ARCHIVED pack can no longer author new
documents. It NEVER reshapes an in-flight / already-generated document: each generation PINNED its
template Version at generate-time (R11, the immutable snapshot), so the produced Documents +
generation history are untouched. The pack’s version spine, the generated_document audit rows, and
every produced Document are RETAINED (INV-8) - this is a status flip, never a hard DELETE; reversible
only via authoring a new version. Mirrors board.archive/doc.archive (status-not-timestamp, INV-3).
Idempotent: a re-archive of an ARCHIVED template is a no-op success (changed
Input { id } (fields ending in ? are optional)
Call POST /v/doc.template.archive with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.template.archive.
Getdoc.template.get
| Property | Value |
|---|---|
| Capability | doc.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 |
-> { id,key,title,status,currentVersion,mergeVars,body,mapping }.
READ/L0/MEMBER. Reads a doc template by id, RLS-scoped.
Input { templateId } (fields ending in ? are optional)
Call POST /v/doc.template.get with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.template.get.
Listdoc.template.list
| Property | Value |
|---|---|
| Capability | doc.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 |
Withdraw a Document from active listing/authoring → ARCHIVED. The
binary, every DocumentVersion, the tracked-change history, and the audit chain are RETAINED (INV-8);
the document is still readable via doc.get. Post-archive edit/track/gen are refused; it is NOT a
hard delete (byte retention is the EPIC-FILE sweep).
{ status?, cursor? } -> { items:[{id,key,title,status,currentVersion,mergeVarCount}], count, nextCursor? }.
READ/L0/MEMBER. Lists doc templates in the workspace, RLS-scoped, paginated.
Input { id } (fields ending in ? are optional)
Call POST /v/doc.template.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.template.list.
Publishdoc.template.publish
| Property | Value |
|---|---|
| Capability | doc.template.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Publish: make a pack version CURRENT (DRAFT→ACTIVE). An in-flight generation pinned to a PRIOR version never re-shapes (R11 - the pin is at generate-time).
Input { id, version? } (fields ending in ? are optional)
Call POST /v/doc.template.publish with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.template.publish.
Registerdoc.template.register
| Property | Value |
|---|---|
| Capability | doc.template.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
{ key, title, mergeVars:[{name,class,type?}], body? }. DESTRUCTIVE/L3/ADMIN. Registers a doc-pack
body with merge-vars CLASSIFIED required|optional|computed|system at register (the INV-9 coverage source).
Call POST /v/doc.template.register with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.template.register.
Versiondoc.template.version
| Property | Value |
|---|---|
| Capability | doc.template.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Cut a pack version (delegates to the generic version
primitive, parent_type=‘OTHER’). The minted version is what doc.template.publish makes current.
Input { id, changelog? } (fields ending in ? are optional)
Call POST /v/doc.template.version with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Createdoc.tmpl.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
workspace_id from ctx (workspace-owned), created_by_id acting user.
Call POST /v/doc.tmpl.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.tmpl.create.
Deletedoc.tmpl.delete
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
HARD delete (preserves FE semantics); RLS fence id+workspace_id.
Call POST /v/doc.tmpl.delete with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.tmpl.delete.
Updatedoc.tmpl.update
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Partial conditional set; RLS fence id+workspace_id.
Call POST /v/doc.tmpl.update with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.tmpl.update.
Createdoc.tmpl.version.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Same-tx: insert template_version (next version) + bump templates.current_version. Fence parent template in workspace.
Call POST /v/doc.tmpl.version.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.tmpl.version.create.
Acceptdoc.track.accept
| Property | Value |
|---|---|
| Capability | doc.track |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Accept (keep+unwrap) / reject (revert) a tracked change. The OOXML run-delta that accept/reject implies belongs to the DocEngine service; the kernel owns the record’s lifecycle + audit. Atomic guard: only a PENDING change transitions (terminal-immutable).
Input { trackedChangeId } (fields ending in ? are optional)
Call POST /v/doc.track.accept with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Rejectdoc.track.reject
| Property | Value |
|---|---|
| Capability | doc.track |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
A sensitive operation in the doc.* family. Called through the one governed front door: capability, permission tier, autonomy, scope and egress are all resolved before the handler runs, and the call is audited (INV-1, INV-8).
Call POST /v/doc.track.reject with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Versiondoc.version
| Property | Value |
|---|---|
| Capability | version.author |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Snapshot-before-overwrite (INV-8 immutable). Mints the generic version
row (parent_type=‘DOCUMENT’) for the changelog spine AND a document_version body (content+map).
Input { id, changelog? } (fields ending in ? are optional)
Call POST /v/doc.version with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Snapshotdoc.version.snapshot
| Property | Value |
|---|---|
| Capability | version.author |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
The least-privilege member-tier sibling of doc.version
(Design O-A, [2026] VJS-CC-OPBOX 85): Authz::Member / RiskClass::Write, REUSING the EXISTING
version.author capability (no new grant) so the member-session write sites (reupload pre-snapshot,
throttled doc-edit snapshot, pre-restore backup) route through the kernel instead of writing
DocumentVersion rows directly via Prisma (VJS-DEC 15: writes via verbs).
INV-5 patch-not-reconstruct: the version row is MINTED from the current document state (content + structural_map + binary key as they stand now); it NEVER reconstructs or rebuilds the document.
Idempotent on (documentId, version): the caller MAY pin the version number it is snapshotting
(the frontend computes the current version cursor before overwriting); if that (document, version)
snapshot already exists, the verb is a no-op SUCCESS that returns the existing row (no 23505, no
duplicate). Omitting version forward-mints MAX(version)+1 (the doc.version behaviour) which is
not re-derivable, so an UPSERT only short-circuits when the caller pins a version it already wrote.
INV-15 no-amplification: member autonomy stays L1 (min(session, verb) = min(L1, L1) = L1), the
write is workspace-scoped (the same RLS as doc.edit), and no capability beyond version.author
(already held by every member who can call doc.edit) is conferred. Reversible to Admin in one line
(the registry authz field) without touching the immutable rows.
Input { id, version?, changelog? } (fields ending in ? are optional)
Call POST /v/doc.version.snapshot with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.version.snapshot.
Recorddoc.view.record
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Append-only view log (the 5-min throttle read stays in FE).
Call POST /v/doc.view.record with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.view.record.
Adddoc.watch.add
| Property | Value |
|---|---|
| Capability | doc.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) |
on (document_id,user_id).
Call POST /v/doc.watch.add with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.watch.add.
Removedoc.watch.remove
| Property | Value |
|---|---|
| Capability | doc.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) |
Delete own watch by (document_id,user_id).
Call POST /v/doc.watch.remove with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.watch.remove.
Createdoc.webhook.create
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Per-document/workspace webhook subscription with an encrypted secret. workspace_id from ctx. Returns id only (never echoes the secret).
Call POST /v/doc.webhook.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.webhook.create.
Deletedoc.webhook.delete
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
RLS fence; idempotent (deliveries are FK-cascade).
Call POST /v/doc.webhook.delete with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.webhook.delete.
Updatedoc.webhook.update
| Property | Value |
|---|---|
| Capability | doc.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
Partial update; undefined=leave, null=clear (documentId scope, headers JsonNull, secret). RLS fence id+workspace_id.
Call POST /v/doc.webhook.update with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool doc.webhook.update.