Skip to content

crp.policy

Auto-generated reference for the crp.policy subpackage.

policy

crp.policy

CRP Safety Policy engine (CRP-SPEC-006).

A CSP-inspired declarative policy language for AI safety enforcement at the transport layer. Clients declare CRP-Safety-Policy directives; the gateway parses, merges, and enforces them against DPE output on every response.

Public API

parse_policy / resolve_policy - string → SafetyPolicy (with profiles) mode_policy / merge_policies - CRP-Safety-Mode shorthand + merging extract_signals / enforce_policy - evaluate a policy against DPE signals check_inheritance - multi-agent tightening rule build_report / deliver_report - violation reporting bind_policy / verify_policy - policy-nonce binding infer_from_text (+ with_llm) - natural-language instruction → SafetyControlPlane settings (SPEC-033)

SafetySignals dataclass

Normalised DPE signals consumed by the enforcer.

PolicySyntaxError

Bases: ValueError

Raised when a CRP-Safety-Policy value violates the grammar.

InheritanceResult dataclass

Outcome of comparing a child policy against its parent.

http_status property

Return the HTTP status.

headers property

Return the headers.

EnforcementAction

Bases: str, Enum

The action a policy decision recommends - ordered by severity.

severity property

Return the severity.

OversightMode

Bases: str, Enum

Human-oversight mode (CRP-SPEC-002 §5.10).

PolicyDecision dataclass

Result of evaluating a :class:SafetyPolicy against DPE signals.

halted property

Return whether the halted condition holds.

headers property

CRP headers describing this decision (violation + retry-after).

RepetitionLevel

Bases: str, Enum

DPE Stage 7 repetition classification - ordered NONE < … < SEVERE.

rank property

Return the rank.

RiskLevel

Bases: str, Enum

DPE risk classification - ordered LOW < MEDIUM < HIGH < CRITICAL.

rank property

Return the rank.

SafetyPolicy dataclass

A parsed CRP-Safety-Policy value.

Unset directives are None / False / empty. report_only is set when the policy arrived via the CRP-Safety-Policy-Report-Only header.

to_policy_string()

Render the policy back to canonical CRP-Safety-Policy syntax.

Strategy

Bases: str, Enum

Dispatch strategies allowed by upgrade-on-risk (CRP-SPEC-008).

Violation dataclass

A single directive that was violated by the analysed response.

ViolationType

Bases: str, Enum

Categorised policy-violation reasons (used in violation reports).

InferredPolicy dataclass

Result of inferring safety settings from natural language.

Attributes:

Name Type Description
settings dict[str, Any]

SafetyControlPlane capability name -> value.

oversight_required set[str]

Safety-class tokens (e.g. "destructive") that should require human approval before executing.

matched_rules list[str]

Human-readable description of every rule that fired - always surfaced so an inferred policy is auditable, never a black box (mirrors the Coverage Map's "honesty is a feature" design).

source str

"keyword", "llm", or "keyword+llm".

to_dict()

Serialise to a JSON-safe dict.

ViolationReport dataclass

A CRP-SPEC-006 §3.16 violation-report payload.

to_dict()

Return the violation report as a plain dict.

Returns:

Type Description
dict[str, Any]

Dict with all non-None report fields.

to_json()

Serialize the report to a JSON string.

Returns:

Type Description
str

JSON-encoded violation report.

enforce_policy(policy, signals)

Evaluate policy against signals → a :class:PolicyDecision.

extract_signals(*, provenance=None, quality=None, compliance=None, rqa=None)

Build :class:SafetySignals from engine outputs (all duck-typed/optional).

parse_policy(value, *, report_only=False)

Parse a CRP-Safety-Policy directive string into a :class:SafetyPolicy.

Parameters:

Name Type Description Default
value str

The raw header value (e.g. "default-src context; halt-on CRITICAL").

required
report_only bool

Set when parsed from CRP-Safety-Policy-Report-Only.

False

Raises:

Type Description
PolicySyntaxError

If any directive is malformed or unknown.

check_inheritance(parent, child)

Validate that child is at least as restrictive as parent (§5.1).

Returns an :class:InheritanceResult whose applied_policy is the most-restrictive merge of the two (used when the child is valid).

resolve_effective_policy(parent, child)

Resolve the effective child policy when the child may omit one (§5, C4d).

SPEC-012 §5: a sub-agent that sends no CRP-Safety-Policy of its own inherits the parent's policy verbatim. When both are present the result is the most-restrictive merge (delegated to :func:check_inheritance's caller).

Returns:

Type Description
SafetyPolicy | None
  • the parent's policy when child is None (full inheritance),
SafetyPolicy | None
  • the child's policy when parent is None,
SafetyPolicy | None
  • otherwise the most-restrictive merge of the two.

merge_policies(base, override)

Merge two policies with most-restrictive-wins (CRP-SPEC-006 §4.1/§4.2).

Used both for Mode+Policy combination and as the comparison primitive for inheritance. The result is a new :class:SafetyPolicy; inputs are unchanged.

mode_policy(mode)

Return the :class:SafetyPolicy for a CRP-Safety-Mode shorthand.

infer_from_text(text)

Infer SafetyControlPlane settings from a plain-English instruction.

Zero-cost, deterministic, always available - no model call. Every matching rule contributes its settings (later matches can add to, but never silently replace, earlier ones for different keys).

Parameters:

Name Type Description Default
text str

A natural-language safety instruction, e.g. "never let it delete files without asking me".

required

Returns:

Name Type Description
An InferredPolicy

class:InferredPolicy with source="keyword". Empty

InferredPolicy

settings/oversight_required (with matched_rules == [])

InferredPolicy

means no known pattern matched - callers should fall back to a

InferredPolicy

named profile ("balanced") rather than silently applying nothing.

infer_from_text_with_llm(text, model_call)

Infer settings using both the keyword layer and an LLM classifier.

Parameters:

Name Type Description Default
text str

The natural-language safety instruction.

required
model_call Callable[[str], str]

A single-argument callable (prompt) -> raw_text, typically the caller's already-resolved provider (no separate model load - reuses whatever LLM the agent is already using).

required

Returns:

Name Type Description
An InferredPolicy

class:InferredPolicy merging both layers. If the model call

InferredPolicy

raises or returns unparsable output, the keyword-only result is

InferredPolicy

returned unchanged (never raises - this is advisory enrichment,

InferredPolicy

not a required step).

looks_like_natural_language(value)

Heuristic: is value a free-text safety instruction, not a known profile name ("strict"/"balanced"/"permissive") or a CRP-Safety-Policy directive string ("default-src ...")?

Used by callers (e.g. crp.Agent(safety=...)) to decide whether a string argument should be parsed as a profile name or run through :func:infer_from_text.

bind_policy(policy_value, nonce, secret)

Return an HMAC-SHA256 tag binding policy_value to nonce.

The tag travels in CRP-Safety-Nonce (or a derived header) and is recomputed by the gateway from the trusted session secret.

generate_nonce(num_bytes=32)

Return a cryptographically-random URL-safe nonce.

verify_policy(policy_value, nonce, secret, tag)

Constant-time verification of a policy-nonce binding tag.

expand_profile(value)

Expand a profile=<name>[; extra-directives] value to a directive string.

Raises:

Type Description
PolicySyntaxError

If the profile name is unknown.

is_profile_policy(value)

True if value begins with a profile= token.

resolve_policy(value, *, report_only=False)

Parse a policy value, transparently expanding profile= references.

build_report(decision, signals, *, session_id=None, window_id=None, audit_trail_uri=None)

Construct a :class:ViolationReport from an enforcement decision.

deliver_report(policy, report, *, timeout=5.0)

Best-effort POST of report to policy.report_uri.

Returns True on a 2xx response, False otherwise (never raises). Does nothing (returns False) when no report-uri is configured.

policy.enforce

crp.policy.enforce

Safety Policy enforcement engine (CRP-SPEC-006 §3-4).

:func:enforce_policy evaluates a parsed :class:SafetyPolicy against the DPE analysis signals and returns a :class:PolicyDecision. Directive interactions follow most-restrictive-wins (CRP-SPEC-006 §4.1): the decision's final action is the most severe action recommended by any violated directive.

SafetySignals dataclass

Normalised DPE signals consumed by the enforcer.

extract_signals(*, provenance=None, quality=None, compliance=None, rqa=None)

Build :class:SafetySignals from engine outputs (all duck-typed/optional).

enforce_policy(policy, signals)

Evaluate policy against signals → a :class:PolicyDecision.

policy.grammar

crp.policy.grammar

Safety Policy grammar parser (CRP-SPEC-006 §2).

Parses CRP-Safety-Policy directive strings into a :class:SafetyPolicy, enforcing the ABNF grammar. Malformed policies raise :class:PolicySyntaxError (the gateway returns HTTP 400 for these - see CRP-SPEC-006 §7.1).

PolicySyntaxError

Bases: ValueError

Raised when a CRP-Safety-Policy value violates the grammar.

parse_policy(value, *, report_only=False)

Parse a CRP-Safety-Policy directive string into a :class:SafetyPolicy.

Parameters:

Name Type Description Default
value str

The raw header value (e.g. "default-src context; halt-on CRITICAL").

required
report_only bool

Set when parsed from CRP-Safety-Policy-Report-Only.

False

Raises:

Type Description
PolicySyntaxError

If any directive is malformed or unknown.

policy.inheritance

crp.policy.inheritance

Policy inheritance & tightening in multi-agent chains (CRP-SPEC-006 §5).

A child agent's Safety Policy MUST be equal to or more restrictive than its parent's. :func:check_inheritance detects any relaxation; the gateway rejects relaxing child requests with HTTP 403 and CRP-Safety-Policy-Violation: inheritance.

InheritanceResult dataclass

Outcome of comparing a child policy against its parent.

http_status property

Return the HTTP status.

headers property

Return the headers.

check_inheritance(parent, child)

Validate that child is at least as restrictive as parent (§5.1).

Returns an :class:InheritanceResult whose applied_policy is the most-restrictive merge of the two (used when the child is valid).

resolve_effective_policy(parent, child)

Resolve the effective child policy when the child may omit one (§5, C4d).

SPEC-012 §5: a sub-agent that sends no CRP-Safety-Policy of its own inherits the parent's policy verbatim. When both are present the result is the most-restrictive merge (delegated to :func:check_inheritance's caller).

Returns:

Type Description
SafetyPolicy | None
  • the parent's policy when child is None (full inheritance),
SafetyPolicy | None
  • the child's policy when parent is None,
SafetyPolicy | None
  • otherwise the most-restrictive merge of the two.

policy.mode

crp.policy.mode

CRP-Safety-Mode shorthand + policy merging (CRP-SPEC-006 §4.2).

CRP-Safety-Mode is a shorthand for common policy combinations. When both CRP-Safety-Mode and CRP-Safety-Policy are supplied, the two are merged per-directive with most-restrictive-wins semantics.

mode_policy(mode)

Return the :class:SafetyPolicy for a CRP-Safety-Mode shorthand.

merge_policies(base, override)

Merge two policies with most-restrictive-wins (CRP-SPEC-006 §4.1/§4.2).

Used both for Mode+Policy combination and as the comparison primitive for inheritance. The result is a new :class:SafetyPolicy; inputs are unchanged.

policy.model

crp.policy.model

Safety Policy data model (CRP-SPEC-006).

Dataclasses and enums for the CRP-Safety-Policy directive language - a CSP-inspired declarative syntax for AI safety enforcement at the transport layer. This module defines the structure; :mod:crp.policy.grammar parses strings into it and :mod:crp.policy.enforce evaluates it against DPE output.

RiskLevel

Bases: str, Enum

DPE risk classification - ordered LOW < MEDIUM < HIGH < CRITICAL.

rank property

Return the rank.

RepetitionLevel

Bases: str, Enum

DPE Stage 7 repetition classification - ordered NONE < … < SEVERE.

rank property

Return the rank.

OversightMode

Bases: str, Enum

Human-oversight mode (CRP-SPEC-002 §5.10).

Strategy

Bases: str, Enum

Dispatch strategies allowed by upgrade-on-risk (CRP-SPEC-008).

SafetyPolicy dataclass

A parsed CRP-Safety-Policy value.

Unset directives are None / False / empty. report_only is set when the policy arrived via the CRP-Safety-Policy-Report-Only header.

to_policy_string()

Render the policy back to canonical CRP-Safety-Policy syntax.

EnforcementAction

Bases: str, Enum

The action a policy decision recommends - ordered by severity.

severity property

Return the severity.

ViolationType

Bases: str, Enum

Categorised policy-violation reasons (used in violation reports).

Violation dataclass

A single directive that was violated by the analysed response.

PolicyDecision dataclass

Result of evaluating a :class:SafetyPolicy against DPE signals.

halted property

Return whether the halted condition holds.

headers property

CRP headers describing this decision (violation + retry-after).

policy.nl_infer

crp.policy.nl_infer

Natural-language safety policy inference (CRP-SPEC-033/034 extension).

Safety in CRP was only declarable through the CSP-like CRP-Safety-Policy directive grammar (:mod:crp.policy.grammar) or raw SafetyControlPlane capability tuning (:func:crp.security.control_plane.SafetyControlPlane.tune). Neither accepts a plain English instruction such as "never let it delete files without asking me first". This module bridges that gap:

  1. A deterministic keyword/pattern layer (:func:infer_from_text) - zero cost, always available, covers the common safety intents a user is likely to write.
  2. An optional LLM-assisted layer (pass model_call) that asks the already-resolved model itself to classify the sentence against the Safety Control Plane's known tunable capabilities, for phrasing the deterministic layer does not recognise.

Both layers return the SAME shape: a dict of SafetyControlPlane capability names to values, plus an oversight_required set of :class:SafetyClass names when the text implies gating specific action classes, and a matched_rules list for auditability (never apply an inferred policy the user cannot inspect).

InferredPolicy dataclass

Result of inferring safety settings from natural language.

Attributes:

Name Type Description
settings dict[str, Any]

SafetyControlPlane capability name -> value.

oversight_required set[str]

Safety-class tokens (e.g. "destructive") that should require human approval before executing.

matched_rules list[str]

Human-readable description of every rule that fired - always surfaced so an inferred policy is auditable, never a black box (mirrors the Coverage Map's "honesty is a feature" design).

source str

"keyword", "llm", or "keyword+llm".

to_dict()

Serialise to a JSON-safe dict.

infer_from_text(text)

Infer SafetyControlPlane settings from a plain-English instruction.

Zero-cost, deterministic, always available - no model call. Every matching rule contributes its settings (later matches can add to, but never silently replace, earlier ones for different keys).

Parameters:

Name Type Description Default
text str

A natural-language safety instruction, e.g. "never let it delete files without asking me".

required

Returns:

Name Type Description
An InferredPolicy

class:InferredPolicy with source="keyword". Empty

InferredPolicy

settings/oversight_required (with matched_rules == [])

InferredPolicy

means no known pattern matched - callers should fall back to a

InferredPolicy

named profile ("balanced") rather than silently applying nothing.

infer_from_text_with_llm(text, model_call)

Infer settings using both the keyword layer and an LLM classifier.

Parameters:

Name Type Description Default
text str

The natural-language safety instruction.

required
model_call Callable[[str], str]

A single-argument callable (prompt) -> raw_text, typically the caller's already-resolved provider (no separate model load - reuses whatever LLM the agent is already using).

required

Returns:

Name Type Description
An InferredPolicy

class:InferredPolicy merging both layers. If the model call

InferredPolicy

raises or returns unparsable output, the keyword-only result is

InferredPolicy

returned unchanged (never raises - this is advisory enrichment,

InferredPolicy

not a required step).

looks_like_natural_language(value)

Heuristic: is value a free-text safety instruction, not a known profile name ("strict"/"balanced"/"permissive") or a CRP-Safety-Policy directive string ("default-src ...")?

Used by callers (e.g. crp.Agent(safety=...)) to decide whether a string argument should be parsed as a profile name or run through :func:infer_from_text.

policy.nonce

crp.policy.nonce

Policy-nonce binding (CRP-SPEC-006 §7.1, CRP-SPEC-002 §5.16).

CRP-Safety-Nonce binds a policy to a session nonce so that an attacker who can inject a CRP-Safety-Policy header cannot relax enforcement without also forging the nonce. The gateway issues a nonce at session start and verifies it on every subsequent policy-bearing request.

generate_nonce(num_bytes=32)

Return a cryptographically-random URL-safe nonce.

bind_policy(policy_value, nonce, secret)

Return an HMAC-SHA256 tag binding policy_value to nonce.

The tag travels in CRP-Safety-Nonce (or a derived header) and is recomputed by the gateway from the trusted session secret.

verify_policy(policy_value, nonce, secret, tag)

Constant-time verification of a policy-nonce binding tag.

policy.profiles

crp.policy.profiles

Industry-specific policy profiles (CRP-SPEC-006 §6).

Named profiles expand to full directive strings. A policy value may be a bare profile (profile=medical) or a profile plus additional directives (profile=medical; report-uri https://hospital.example/audit).

is_profile_policy(value)

True if value begins with a profile= token.

expand_profile(value)

Expand a profile=<name>[; extra-directives] value to a directive string.

Raises:

Type Description
PolicySyntaxError

If the profile name is unknown.

resolve_policy(value, *, report_only=False)

Parse a policy value, transparently expanding profile= references.

policy.report

crp.policy.report

Violation report payloads + delivery (CRP-SPEC-006 §3.16).

Builds the JSON violation-report payload and POSTs it to a policy's report-uri when configured. Delivery is best-effort and dependency-light: the standard-library urllib is used so the core package gains no new deps.

ViolationReport dataclass

A CRP-SPEC-006 §3.16 violation-report payload.

to_dict()

Return the violation report as a plain dict.

Returns:

Type Description
dict[str, Any]

Dict with all non-None report fields.

to_json()

Serialize the report to a JSON string.

Returns:

Type Description
str

JSON-encoded violation report.

build_report(decision, signals, *, session_id=None, window_id=None, audit_trail_uri=None)

Construct a :class:ViolationReport from an enforcement decision.

deliver_report(policy, report, *, timeout=5.0)

Best-effort POST of report to policy.report_uri.

Returns True on a 2xx response, False otherwise (never raises). Does nothing (returns False) when no report-uri is configured.