The gate.* family (6 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.
Applygate.apply
| Property | Value |
|---|---|
| Capability | gate.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
atomic, TOCTOU-safe apply on approval (US-GATE-02, INV-4). { gateId, reviewNote? }.
- Lock the gate row FOR UPDATE (routing/authz pre-read - NOT authoritative).
- The AUTHORITATIVE guard:
UPDATE gate SET status='APPLIED' ... WHERE id=$1 AND status='PENDING'.rows_affected()==0-> the gate is not PENDING (a concurrent winner already applied, or it was rejected/withdrawn/terminal) -> Conflict, the whole tx aborts before any replay (exactly one winner; re-apply on a terminal gate refused; APPROVED!=APPLIED upheld - only PENDING applies). - Replay the captured change-set through the target’s canonical verb (INV-1, no shadow path) on the SAME tx, and append the replay’s OWN AuditEvent (INV-8).
Input
| Field | Type | Required | Description |
|---|---|---|---|
gateId | string | yes | |
reviewNote | string | no |
Call POST /v/gate.apply with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool gate.apply.
Getgate.get
| Property | Value |
|---|---|
| Capability | gate.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 |
one gate (the changeset diff + attribution). { gateId }. READ/L0.
Call POST /v/gate.get with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool gate.get.
Listgate.list
| Property | Value |
|---|---|
| Capability | gate.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 |
list gates in the workspace (optional status/kind filter). { status?, kind? }. READ/L0.
Call POST /v/gate.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool gate.list.
Proposegate.propose
| Property | Value |
|---|---|
| Capability | gate.write |
| 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) |
capture a proposed mutation as a PENDING gate (US-GATE-01).
{ kind, targetType, targetId?, changeset, matterId?, restorationData? }.
The change-set is captured atomically with the PENDING insert; the deferred write does NOT
happen here - the proposing caller sees {gated:true, gateId} and must not also write the fact
(INV-1, no double write). For a data-gate the change-set carries {verb, input} to replay; for
an action-gate (ESCALATION) it carries {targetVerb, inputHash}.
Input
| Field | Type | Required | Description |
|---|---|---|---|
kind | string | yes | e.g. STEP_ACCEPTANCE |
targetType | string | yes | |
targetId | string | yes | |
matterId | string | no | |
changeset | object | yes | {verb, input} - the write to replay on apply |
Call POST /v/gate.propose with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Rejectgate.reject
| Property | Value |
|---|---|
| Capability | gate.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) |
close a PENDING gate -> REJECTED with a note (US-GATE-04). { gateId, reviewNote? }.
Atomic guard same as apply: only a PENDING gate can be rejected (no rejecting a terminal gate).
Call POST /v/gate.reject with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Revertgate.revert
| Property | Value |
|---|---|
| Capability | gate.write |
| Risk class | Sensitive - autonomy L2 |
| Min. permission | Admin |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Legal basis | CC-OPBOX 32 |
the SCOPED-REVERT undo ([2026] CC-OPBOX 32). State-restoring undo of an APPLIED gate: the
is-revertible guard (APPLIED + non-null restoration_data ONLY), the atomic terminal restored_at stamp (the
status enum STAYS ‘APPLIED’ in a RESTORED-terminal posture, preserving CC-OPBOX 25 immutability), and the
restoration replayed through the canonical verb (INV-1, re-gated, own AuditEvent - the SAME mechanism
gate.apply uses). The gate-attached restoration_data is the ONLY revertible target (no event.revert - an
arbitrary audit event has no before-state). Sensitive/L2/ADMIN, at parity with gate.apply. { gateId, reviewNote? }.
Call POST /v/gate.revert with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool gate.revert.