SentnelOpsSentnelOpsbeta
LAYER 4 · RUNTIME ENFORCEMENT

Enforcement reference

The enforcement YAML schema, the approvals API, the approval record, alert event types, and the server-side configuration knobs.

Enforcement YAML schema

Everything lives under the top-level enforcement: key of the policy file, next to the layer-2 tool rules. Omitting the section entirely means every call observes.

KeyValuesMeaning
enforcement.<env>observe | enforce | require_approvalMode for every call from agents in that environment. An unlisted environment is observe.
enforcement.rules.<tool>same three modesPer-tool override — wins over the environment mode for that tool, in every environment.
approval.defaults.window_secondsnumber > 0 (default 60)How long a held call waits for a decision before timing out (timeout = deny).
approval.defaults.blast_radius_threshold0–1 (default 0.7)In an enforcing mode, a permitted call whose declared blast radius meets this is held for approval.
approval.<env>{window_seconds, blast_radius_threshold, channel}Per-environment override of the defaults; channel routes that environment's approval alerts to a Slack channel.
fail_mode.<env>open | closed (default open)What a policy-engine error does in that environment: open = pass + warn, closed = 403 + fail_closed alert.

Approvals API

EndpointMin roleBehavior
GET /approvals?status=&limit=viewerOrg-scoped list, newest first. status filters on pending / approved / denied / timeout; limit defaults 100, max 1000.
POST /approvals/{id}/approvesecurityApproves a pending approval and releases the held call. Body: {approver?, note?}. A session user always decides as themselves — the body approver is ignored; an org API key must supply approver (422 otherwise).
POST /approvals/{id}/denysecuritySame body and approver semantics; the held call returns 403 with the denial and approver in the reason.
Errors (both decisions)404 unknown (or malformed) id or another org's approval; 409 approval already <status> when it was already decided or timed out — decisions are claimed atomically, so exactly one wins.

The approval record

Every hold writes one row to mcp_approvals (migration 004_r4_enforcement.sql) — the tamper-evident record of who decided what. Fields as returned by GET /approvals:

FieldTypeMeaning
iduuidThe approval id — appears in the alert and the decide URLs.
agent_id / agent_name / environmenttextWhich agent's call is held, and where it runs.
mcp_server / tool_name / paramstext / jsonExactly what the agent was about to do, arguments included.
blast_radiusnumber 0–1 | nullThe tool's declared blast-radius score, if the policy declares one.
reasontextWhy approval was required — the explicit rule, or the blast-threshold comparison.
statuspending | approved | denied | timeoutThe lifecycle of the hold. Only pending rows can be decided.
requested_at / window_secondstimestamp / numberWhen the hold started and how long it will wait — together, the countdown.
decided_at / approver / decision_notetimestamp / text / textWho decided, when, and their note. The approver is always a named human identity (or the name an API-key caller was required to supply).

Alert event types

TypeFired when
blockAn enforcing mode blocked a policy-denied call before the upstream.
approval_requestA call was held — carries the approval id and the environment's channel override.
approval_decidedA held call was denied or timed out (an approved call simply proceeds; the decision lives in the call log and the approval row).
fail_closedThe policy engine errored in an environment with fail_mode: closed, and the call was blocked.

Server configuration knobs

All optional; with no channel configured, alerts stay local (zero egress).

VariableDefaultMeaning
SNOPS_SLACK_WEBHOOK_URLunsetSlack incoming-webhook URL; unset disables the Slack channel.
SNOPS_SMTP_HOST / SNOPS_SMTP_PORTunset / 587SMTP relay for email alerts (STARTTLS); unset host disables email.
SNOPS_SMTP_USER / SNOPS_SMTP_PASSWORDunsetSMTP credentials, if your relay requires login.
SNOPS_ALERT_EMAIL_TO / SNOPS_ALERT_EMAIL_FROMunset / sentnelops-alerts@localhostRecipient and sender for email alerts; email needs both a host and a recipient.
SNOPS_ENFORCEMENT_FAIL_MODE_DEFAULTopenLast-resort fail mode when the policy store itself cannot be read — the per-env fail_mode lives in the YAML that failed to load.