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 ¶
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 ¶
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. |
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 |
|
to_dict() ¶
Serialise to a JSON-safe dict.
ViolationReport dataclass ¶
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. | required |
report_only | bool | Set when parsed from | 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 |
|
SafetyPolicy | None |
|
SafetyPolicy | None |
|
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. | required |
Returns:
| Name | Type | Description |
|---|---|---|
An | InferredPolicy | class: |
InferredPolicy |
| |
InferredPolicy | means no known pattern matched - callers should fall back to a | |
InferredPolicy | named profile ( |
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 | required |
Returns:
| Name | Type | Description |
|---|---|---|
An | InferredPolicy | class: |
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. | required |
report_only | bool | Set when parsed from | 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 ¶
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 |
|
SafetyPolicy | None |
|
SafetyPolicy | None |
|
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.
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:
- A deterministic keyword/pattern layer (:func:
infer_from_text) - zero cost, always available, covers the common safety intents a user is likely to write. - 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. |
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 |
|
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. | required |
Returns:
| Name | Type | Description |
|---|---|---|
An | InferredPolicy | class: |
InferredPolicy |
| |
InferredPolicy | means no known pattern matched - callers should fall back to a | |
InferredPolicy | named profile ( |
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 | required |
Returns:
| Name | Type | Description |
|---|---|---|
An | InferredPolicy | class: |
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 ¶
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.