Skip to content

Guardrails policy ​

CRUD over the per-workspace guardrail policy that the gateway consults on every chat completion. A policy is a structured DSLPolicy document — input/output rules, redaction patterns, blocked-prompt lists — that load_policy_from_dict validates at upsert time. Hot-reload: the next chat completion sees the new policy without a process restart.

The router lives at packages/guardrails/policy_routes.py. The registry is PolicyRegistry (packages/guardrails/policy_repo.py).

Endpoints ​

MethodPathAuthSummary
GET/admin/guardrails/policyBearerRead the workspace policy; 404 when unset.
PUT/admin/guardrails/policyBearerReplace the workspace policy atomically.
DELETE/admin/guardrails/policyBearerDrop the workspace policy; 204 on success.

GET /admin/guardrails/policy ​

Returns the JSON-encoded DSLPolicy for the caller's workspace. Returns 404 with "no guardrail policy registered for this workspace" when no override is set — the gateway falls through to the default no-op policy in that case.

bash
curl -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  http://localhost:8000/admin/guardrails/policy

PUT /admin/guardrails/policy ​

Accepts the raw DSLPolicy document as the JSON request body. Validation runs at load time — a malformed document returns 400 with the underlying parser error in detail.

Example body (illustrative — fields driven by the in-tree DSL grammar):

json
{
  "version": 1,
  "workspace_id": "default",
  "input": [
    {"rule": "block_if_matches", "pattern": "(?i)credit card"}
  ],
  "output": [
    {"rule": "redact", "pattern": "\\b\\d{16}\\b", "replacement": "[REDACTED]"}
  ]
}

Returns {"status": "ok", "workspace_id": "default"} on success.

bash
curl -X PUT -H "Authorization: Bearer $BIGWAVE_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d @policy.json \
  http://localhost:8000/admin/guardrails/policy

DELETE /admin/guardrails/policy ​

Drops the override. Returns 204 No Content. Subsequent chat completions fall through to the default no-op policy until a new PUT arrives.

Operator notes ​

  • Workspace fence. All three routes scope to the bearer principal's workspace; you cannot read or replace another tenant's policy through this surface. See workspace fence.
  • Atomic replace. PUT is full-replace — there is no patch / partial-update. Pull the current document, edit, re-upload.
  • Hot-reload. Policy registry reads happen on every chat call; there is no cache that needs invalidation. A successful PUT takes effect on the very next request.
  • Blocked vs redacted. Blocked requests appear in /admin/inference with status="blocked" and contribute zero cost; redacted responses are surfaced as status="succeeded" with the post-redaction body. See /admin/inference and /admin/cost.
  • 503 causes. app.state.guardrail_policy_registry is wired in lifespan; routes return 503 with "guardrail policy registry not initialised" when the lifespan did not complete.
  • Audit. PUT and DELETE emit audit rows when an AuditLogRepository is wired. See Audit.

Dual-licensed: MIT OR Apache-2.0