The envelope.* 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.
Callbackenvelope.callback
| Property | Value |
|---|---|
| Capability | envelope.callback |
| 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) |
A write operation in the envelope.* 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/envelope.callback with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Createenvelope.create
| Property | Value |
|---|---|
| Capability | envelope.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
At least one of documentId/fileId. Emits the genesis CREATED ledger event.
Input { documentId? | fileId?, matterId?, subject, message?, provider?, externalId?, expiresAt? } (fields ending in ? are optional)
Call POST /v/envelope.create with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool envelope.create.
Declineenvelope.decline
| Property | Value |
|---|---|
| Capability | envelope.sign |
| Risk class | Sensitive - autonomy L2 |
| 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) |
Forward-only terminal off-ramp. Marks the recipient DECLINED, the envelope DECLINED (terminal, immutable), and appends a DECLINED ledger event.
Input { envelopeId, recipientId, reason?, ip?, ua? } (fields ending in ? are optional)
Call POST /v/envelope.decline with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Expireenvelope.expire
| Property | Value |
|---|---|
| Capability | envelope.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Admin |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
The terminal-expiry driver (a scheduled sweep calls it). Already-terminal = no-op (INV-2-safe). Drives a non-terminal envelope to EXPIRED + appends an EXPIRED ledger event.
Input { envelopeId } (fields ending in ? are optional)
Call POST /v/envelope.expire with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Placeenvelope.field.place
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
Geometry normalised 0-1 (G1 reuse). CREATED-only (a sent envelope’s field set is frozen). The recipient must be on this envelope.
Input { envelopeId, recipientId, type, page?, x, y, w, h, required? } (fields ending in ? are optional)
Call POST /v/envelope.field.place with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Removeenvelope.field.remove
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
The Field-Designer delete verb ([2026] VJS-CC-OPBOX 35): remove a placed field WHILE
the envelope is CREATED (pre-send; a sent envelope’s field set is frozen, INV-8). A missing/cross-
workspace id is a clean BadInput. SECTION D anchor-preserving: ONE INV-8 audit event on the generic
event chain (CC-OPBOX 34), never an entry on the signing_event provenance ledger.
Input { fieldId } (fields ending in ? are optional)
Call POST /v/envelope.field.remove with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Updateenvelope.field.update
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
The Field-Designer edit verb the frontend
needs ([2026] VJS-CC-OPBOX 35, the signing lead case): adjust a placed field WHILE the envelope is
CREATED (pre-send; a sent envelope’s field set is frozen, INV-8). Only the KERNEL-OWNED columns
signing_field has are mutable here - field_type + the normalised 0-1 geometry (page/x/y/w/h) + the
required flag. Each is a PARTIAL update (an absent key leaves that column unchanged). The rich
frontend Field-Designer props (recipientRole, defaultValue, options, tabOrder, label) are a
FRONTEND EXTENSION per DEC-19/CC-OPBOX 35 (Plane 2) - the kernel signing_field has no such columns,
so this verb neither reads nor writes them; they are FLAGGED frontend-extension and left to the
frontend store keyed by this field id (see the return note). The recipient OWNER of a field is NOT
re-assignable here (changing who signs a field is a roster decision, recipient.set’s, not a geometry
edit). SECTION D: the per-envelope signing_event provenance chain is ANCHOR-PRESERVING - a pre-send
design edit is NOT a signing-act anchor, so (like the matter_relation sibling under the same general
ratio, CC-OPBOX 34/36) it emits ONE INV-8 audit event on the generic event chain, never an entry on
the signing_event ledger (which would pollute the regulated provenance vocabulary).
Input { fieldId, type?, page?, x?, y?, w?, h?, required? } (fields ending in ? are optional)
Call POST /v/envelope.field.update with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Getenvelope.get
| Property | Value |
|---|---|
| Capability | envelope.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 |
Returns the envelope + its recipients (status board) + its fields + the ledger chain length + the chain-integrity verdict (INV-6 derived ChainIntegrityReport). NEVER decrypts a field value into a read (INV-7 - the ciphertext stays at rest).
Input { envelopeId } (fields ending in ? are optional)
Call POST /v/envelope.get with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool envelope.get.
Listenvelope.list
| Property | Value |
|---|---|
| Capability | envelope.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 envelopes for a matter/doc with per-recipient progress counts. IDOR-scoped (the verb filters on workspace_id; RLS is the backstop).
Input { matterId? | documentId? | status? } (fields ending in ? are optional)
Call POST /v/envelope.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool envelope.list.
Setenvelope.recipient.set
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
CREATED-only. A recipient is a Party (partyId) OR a bare email. Returns the new recipient id.
Input { envelopeId, partyId? | email?, displayName?, role?, order? } (fields ending in ? are optional)
Call POST /v/envelope.recipient.set with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Viewenvelope.recipient.view
| Property | Value |
|---|---|
| Capability | envelope.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
The view-tracking transition the signing flow needs ([2026] VJS-CC-OPBOX
35): mark a recipient PENDING|SENT → VIEWED (the enum value already EXISTS in signing_recipient_status
AND signing_event_kind; no verb set it before). IDEMPOTENT: a recipient already VIEWED|SIGNED|DECLINED
is a no-op success (INV-2) - the chain is NOT re-anchored. SECTION D: VIEWED is a genuine SIGNING-ACT
provenance transition (a recipient opened the document), so it appends ONE INV-8 VIEWED event to the
EXISTING per-envelope signing_event hash-chain (anchor-preserving - the next link in the chain, ip/ua
HMAC-hashed INV-7), unlike the design-time field edits which stay on the generic event chain.
Input { recipientId, ip?, ua? } (fields ending in ? are optional)
Call POST /v/envelope.recipient.view with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Remindenvelope.remind
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
SENT|PARTIALLY_SIGNED only. No state change - appends a REMINDER ledger event and returns the count of still-outstanding recipients (the dispatch is fire-and-forget, INV-2).
Input { envelopeId } (fields ending in ? are optional)
Call POST /v/envelope.remind with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Sendenvelope.send
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
| High-risk oversight | Human four-eyes approval in HIGH-risk orgs (EU AI Act Art. 14) |
Forward-only guard AT the verb (CREATED-only). Requires ≥1 SIGNER recipient. Mints a single-use SIGNING_SESSION token per recipient (the external signer’s credential, like the portal pattern) and appends a SENT ledger event each. Returns the per-recipient session secrets ONCE.
Input { envelopeId } (fields ending in ? are optional)
Call POST /v/envelope.send with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Signenvelope.sign
| Property | Value |
|---|---|
| Capability | envelope.sign |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | External (portal / signer token) |
| Availability | Core - always on (MCP tier 1) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
The envelope must be SENT or
PARTIALLY_SIGNED. An EXTERNAL signer presents the SIGNING_SESSION sessionToken (validated against
the recipient’s bound token); a firm caller may sign without it. Captures the SIGNED provenance event
(ip/ua HMAC-hashed, INV-7), encrypts each field value (INV-7), marks the recipient SIGNED, and
advances the lifecycle: → PARTIALLY_SIGNED while any SIGNER is outstanding, → COMPLETED when all are.
Input { envelopeId, recipientId, sessionToken?, values?, ip?, ua? } (fields ending in ? are optional)
Call POST /v/envelope.sign with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool envelope.sign.
Updateenvelope.update
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
The pre-completion envelope metadata edit ([2026] VJS-CC-OPBOX
60). PARTIAL update: an ABSENT key leaves that column unchanged (the envelope.field.update precedent).
Allowed ONLY while the envelope is CREATED or SENT - a terminal/done envelope (COMPLETED/VOIDED/DECLINED/
EXPIRED) and any other in-progress state are IMMUTABLE here (INV-11/INV-8); a non-CREATED/SENT envelope
fails closed with Conflict. Writes ONLY the kernel-owned subject + expires_at columns - it does NOT
touch status, recipients, fields, or the signing_event provenance ledger (a metadata edit is NOT a
signing-act anchor, the same anchor-preserving stance field.update takes). ONE INV-8 audit event at
dispatch level (the generic event chain), never a signing_event entry.
Input { envelopeId, subject?, expiresAt? } (fields ending in ? are optional)
Call POST /v/envelope.update with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Voidenvelope.void
| Property | Value |
|---|---|
| Capability | envelope.write |
| 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) |
Forward-only terminal. Sets VOIDED + the reason; immutable thereafter.
Input { envelopeId, reason? } (fields ending in ? are optional)
Call POST /v/envelope.void with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.