Runtime policy authoring and rollout
Policies decide whether an authenticated agent may call an approved MCP tool. They run after identity, registry approval, schema validation, and request detection, and before any request reaches the upstream server.
The console's Policies screen is the complete operating surface:
- install environment rollout packs;
- start from a built-in template or create a custom rule;
- author selectors and conditions with server-side validation;
- test an unsaved draft with the gateway's real engine;
- save disabled, review the explanation, then enable;
- edit, duplicate, disable, or delete rules with audit evidence.
Decision semantics
Every enabled policy whose selector matches contributes a decision. Combination is Cedar-style forbid-overrides:
deny > step_up > require_approval > sanitize > redact > allow
Priority controls evaluation order and the explanation trail. It does not
let a high-priority allow override a matching deny. If no rule matches, the
gateway's secure default is deny.
| Effect | Runtime behavior |
|---|---|
allow | Forward the validated call. |
deny | Block the call. |
require_approval | Hold the exact argument-bound call for human approval. |
step_up | Require stronger authentication before retry. |
redact | Forward while redacting configured argument paths. |
sanitize | Forward and sanitize sensitive response content. |
Detection and structural safety floors remain independent: an unapproved or quarantined tool, invalid schema, out-of-scope agent credential, or critical detection can still block a call that policy would otherwise allow.
Selector reference
The match object may contain any combination of these fields. Dimensions are
ANDed; values within one list are ORed.
| Field | Values | Meaning |
|---|---|---|
serverIds | server IDs or * | Specific registered servers. |
environments | local, development, staging, production | Server deployment environment. |
toolIds | tool IDs or * | Specific registered tools. |
toolName | one exact name | A case-sensitive exact tool-name match. |
toolNameGlobs | get_*, deploy_? | Case-insensitive tool-name globs. |
capabilities | read, write, destructive, admin, unknown | Classified capability. |
riskTiers | low, medium, high, critical | Registry risk tier. |
dataClasses | public, internal, confidential, pii, secrets, financial, source_code, production_data | Data handled by the tool. |
tags | tag names or * | Registry tags such as github, filesystem, or sql. |
An empty match object is a valid global rule and matches every registered
tool. The console highlights global enabled rules because their blast radius is
large.
Condition reference
Conditions refine a matched rule. Failed authorization/allowlist conditions
escalate the result to deny; insufficient assurance escalates to step_up.
| Field | Meaning |
|---|---|
requireScopes | Caller must hold every listed scope. |
requireAnyRole | Caller must hold at least one listed role. |
minAuthLevel | Minimum aal1, aal2, or aal3. |
argumentAllowlist | Argument dot-path to allowed glob values. |
redactPaths | Argument paths to remove from logs/forwarded content. |
maxRiskScore | Detection score from 0–100; higher requests are denied. |
Example:
{
"name": "Production deploys need approval",
"description": "Platform-owned deployment control",
"priority": 90,
"enabled": false,
"effect": "require_approval",
"match": {
"environments": ["production"],
"toolNameGlobs": ["deploy_*"],
"capabilities": ["write", "admin"]
},
"condition": {
"requireAnyRole": ["release-manager", "platform-admin"],
"minAuthLevel": "aal2",
"maxRiskScore": 60
}
}
Unknown fields, invalid enums, empty allowlist glob sets, out-of-range risk
scores, and malformed names/priorities are rejected with HTTP 422; typos do
not silently become ineffective policy.
Templates and rollout packs
Six built-in templates cover read baselines, destructive blocks, high-risk approval, secret sanitization, filesystem path allowlists, and production-data approval.
Packs materialize those templates with an environment selector:
| Pack | Intended stage |
|---|---|
pack-dev-observe | Development baseline while reviewing would-block events. |
pack-staging | Adds approval for high/critical tools. |
pack-production | Adds production-data assurance and filesystem controls. |
Pack installation is idempotent per template and environment. Reinstalling the same pack does not create duplicates.
Draft simulation
While the editor is open, Policy Test sends the unsaved rule as a simulation override. You can combine it with active rules to see real forbid-overrides, or isolate it to understand the draft alone. Overrides are simulation-only and cannot change enforcement.
POST /v1/policies/simulate
{
"serverId": "srv_github",
"toolName": "delete_repo",
"arguments": { "repo": "acme/payments" },
"roles": ["developer"],
"authLevel": "aal1",
"draftPolicy": {
"name": "Preview destructive block",
"priority": 100,
"enabled": true,
"effect": "deny",
"match": { "capabilities": ["destructive"] }
},
"includeActivePolicies": true
}
The API passes the override to the gateway's internal simulator, which uses the same TypeScript engine and request detector as live traffic.
Propagation and audit
GATEWAY_CONTROL_PLANE=api is mandatory outside automated tests. After a successful
mutation, the API requests an immediate gateway refresh; the gateway's normal
refresh loop is the fallback if it is temporarily unavailable. The gateway
fails readiness when it cannot obtain a current API snapshot.
Create, update, toggle, pack install, and delete operations require an admin,
security, policy-admin, or tenant-admin identity. Every successful mutation
emits a hash-chained policy_changed evidence event with actor and policy
context.
Recommended rollout
- Install
pack-dev-observeand keep the gateway in observe mode. - Review Policy Test explanations, Sessions, Detections, and Approvals.
- Author custom rules disabled; simulate representative calls and identities.
- Enable the rule in development, then install the staging pack.
- Promote to production only after expected allow/deny/approval evidence is stable.
- Disable first when responding to a policy incident; delete only after review.
See Govern, API reference, and Detections for adjacent runtime controls.