opbox

The policy.* family (8 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.

Createpolicy.create

PropertyValue
Capabilitypolicy.author
Risk classDestructive - autonomy L3
Min. permissionAdmin
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Authoring (agent-non-writable). Creates a DRAFT policy.

Input

FieldTypeRequiredDescription
keystringyes
titlestringyes
kindstringyese.g. ELIGIBILITY
jurisdictionstringno
bodyobjectnothe authored rules: {inputs, rules, fallback, output}

Call POST /v/policy.create with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Editpolicy.edit

PropertyValue
Capabilitypolicy.author
Risk classDestructive - autonomy L3
Min. permissionAdmin
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Re-author a DRAFT body (agent-non-writable). A PUBLISHED policy is edited by editing the DRAFT body then re-publishing (which forward-mints a NEW Version - prior verdicts pinned to the old version never drift, R11).

Input { id, title?, body? } (fields ending in ? are optional)

Call POST /v/policy.edit with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Evaluatepolicy.evaluate

PropertyValue
Capabilitypolicy.evaluate
Risk classSensitive - autonomy L2
Min. permissionMember
AvailabilityCore - always on (MCP tier 1)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

{ policyId, subject:{type,id}, inputs?, pinVersion?, gateOnConfirm? }. SENSITIVE/L2.

  1. Resolve the PINNED Policy Version (the caller may pin an explicit pinVersion; default = the policy’s current published version). Re-publishing later never drifts THIS evaluation (R11).
  2. Gather the typed input Facts: from inline inputs (testable, no-LLM) ELSE from the fact table by (subject, field_key). A missing REQUIRED input → BLOCK (a structured error), never a default (INV-9 fail-closed + no-silent-default).
  3. Evaluate the rule-set + override layer (AND-of-ranges + bump-up + group roll-up; RISK_SCORE country-weight map) - deterministically.
  4. Emit: (a) a result Fact (the verdict - the named INV-6 exception, materialised-for-citation), (b) the policy_evaluation citation row (policy version + matched branch + inputs hash), and optionally (c) a Gate when the outcome needs human confirmation. The dispatch records exactly one citation AuditEvent (INV-8).

Input

FieldTypeRequiredDescription
policyIdstringyes
subjectobjectyes{type: “matter”, id: “mat_…”}
inputsobjectnothe policy inputs, e.g. {criteriaMet: 4}

Call POST /v/policy.evaluate with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool policy.evaluate.

Getpolicy.get

PropertyValue
Capabilitypolicy.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityCore - always on (MCP tier 1)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

A read operation in the policy.* 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/policy.get with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool policy.get.

Listpolicy.list

PropertyValue
Capabilitypolicy.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityCore - always on (MCP tier 1)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

A read operation in the policy.* 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/policy.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool policy.list.

Publishpolicy.publish

PropertyValue
Capabilitypolicy.author
Risk classDestructive - autonomy L3
Min. permissionAdmin
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Authoring (agent-non-writable). Validates the DRAFT body, forward-mints an immutable version row (parent_type=‘OTHER’, parent_id=the policy id) snapshotting the body + jurisdiction + kind, and flips DRAFT→PUBLISHED with current_version = the new Version number. An evaluation pins THIS version; a later re-publish mints a HIGHER version and never drifts it (R11).

Input

FieldTypeRequiredDescription
idstringyes

Call POST /v/policy.publish with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Setpolicy.set

PropertyValue
Capabilitypolicy.author
Risk classWrite - autonomy L1
Min. permissionOwner
AvailabilityOn demand (MCP tier 2)
IdempotentYes
EgressNone - in-box (pure Postgres, no outbound call)

where key ∈ GATE_CATEGORIES | SENSITIVITY_DEFAULTS. WRITE/L1/OWNER.

This is the TENANT’S GOVERNANCE CONFIG, NOT an authored Policy rule-set (that is policy.create over the policy table + the policy.evaluate engine). It upserts the ONE per-(workspace, policy_key) config row on the workspace_policy table (migration 0034) - the SAME upsert shape as bill.defaults.set / party.facet.set / file.policy.* (steering #1: reuse the config-row pattern, never fork a bespoke per-knob column set). OWNER-only (process-level blast radius - a workspace’s gate-category set governs every future gate decision; its sensitivity defaults govern every new object’s classification floor). Agent-non-writable (INV-11) like the rest of the policy authoring surface: an AGENT actor is fail-closed denied.

GATE_CATEGORIES is TIGHTEN-ONLY (catalogue L119: floor=substrate, ceiling=tenant): the body’s categories array MUST include every substrate-mandated category - a tenant may ADD categories on top of the floor but may NEVER drop one (the regulated floor is non-negotiable). A body that omits a floor category is refused (Conflict), never silently accepted (INV-9 fail-closed, no silent-default).

Input { key, body } (fields ending in ? are optional)

Call POST /v/policy.set with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool policy.set.

Validatepolicy.validate

PropertyValue
Capabilitypolicy.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

(or { kind, body }). READ/L0. Validate the authored-definition without persisting.

Input { id } (fields ending in ? are optional)

Call POST /v/policy.validate with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.