enforcement
Module: enforcement
Section titled “Module: enforcement”Contents
Section titled “Contents”Modules
capability_map- Capability token selection map.capability_validation- Stage 1 — Capability Validation.cedar_evaluator- Concrete Cedar policy evaluator for Sidecar Stage 2.constraint_enforcement- Stage 2 — Constraint Enforcement Engine (CEE).decision- Enforcement decision types.error- Internal enforcement errors.registry- Canonical Action Class Registry v0.1.revocation- Revocation cache: bloom filter + LRU store.session- Session-state store: per-session runtime context for Stage 2.
Module: capability_map
Section titled “Module: capability_map”Capability token selection map.
Holds pre-provisioned capability tokens issued by the Authority at pre-flight and selects the best match for each intercepted request based on action class and resource scope (ADR-002).
Tokens are indexed by action class at construction time so that per-request lookups avoid a full linear scan. The agent knows nothing about Firma — the sidecar selects the correct token internally after intent normalization.
Module: capability_validation
Section titled “Module: capability_validation”Stage 1 — Capability Validation.
First enforcement phase. Selects the best-matching capability token and validates it:
- Capability token selection — selects the best-matching pre-provisioned
token from the [
CapabilityMap] by action class and resource scope (ADR-002). The agent knows nothing about Firma; the sidecar selects the correct token internally. - Token validation — parse PASETO v4, verify Ed25519 signature, check expiry (with configurable clock skew tolerance), and check revocation via bloom filter + LRU cache.
All operations are fully local — the Authority is never contacted on the hot path. Target latency: < 1 ms p95.
Security properties
Section titled “Security properties”Stage 1 prevents forged, tampered, expired, or revoked capabilities from entering the execution path:
- Token forgery — cryptographic signature verification rejects tokens not signed by a trusted Authority.
- Token tampering — any modification to scope, expiry, agent ID, or resource scope invalidates the signature.
- Expired credential reuse — expiry check rejects tokens whose TTL has elapsed.
- Revoked token reuse — bloom filter + LRU cache check rejects tokens that have been explicitly invalidated.
Module: cedar_evaluator
Section titled “Module: cedar_evaluator”Concrete Cedar policy evaluator for Sidecar Stage 2.
Implements [PolicyEvaluation] by evaluating a compiled Cedar policy set
against the context produced by
[ConstraintEnforcer::build_context][super::constraint_enforcement::ConstraintEnforcer].
Evaluation is fully local — no network calls. [CedarPolicyEvaluator] is
constructed from a [PolicyBundle] received from the Authority and tracks
freshness against the bundle TTL.
Entity UID conventions (must match Authority’s service.rs)
Section titled “Entity UID conventions (must match Authority’s service.rs)”| Cedar role | Format |
|---|---|
principal | Firma::Agent::"<agent_id>" |
action | Firma::Action::"<action_class>" |
resource | Firma::Resource::"<resource_uri>" |
Module: constraint_enforcement
Section titled “Module: constraint_enforcement”Stage 2 — Constraint Enforcement Engine (CEE).
Second enforcement phase. The semantic layer where Cedar policies and
quantitative constraints are evaluated. Operates on a previously normalized
ExecutionEnvelope produced by Stage 1 — it must not infer the canonical
action class from raw transport-specific input.
Steps:
- Scope check — verifies that the requested
action_classis within the token’s allowedaction_set. Wildcard"*"permits all actions. - Policy bundle freshness — if the bundle TTL has expired without a successful refresh, the Sidecar enters fail-closed mode and denies all new requests.
- Context build — assembles the Cedar request context from envelope fields, claims, and runtime signals such as risk score.
- Cedar eval — evaluates against the current policy bundle. Deterministic: same context + same bundle = same decision. Fully local, no external calls.
Target latency: < 200 µs p95.
Security properties
Section titled “Security properties”Stage 2 prevents valid capabilities from being misused for out-of-policy, contextually disallowed actions:
- Privilege escalation within token — a valid token does not imply all calls are allowed; Cedar eval checks the specific call against policy.
- Scope misuse at runtime — a valid capability for action class X cannot be used for action class Y.
- Non-deterministic authorization — same context + same bundle always produces the same decision.
Module: decision
Section titled “Module: decision”Enforcement decision types.
Every enforce() call produces exactly one [EnforcementDecision]:
the AARM R4 five-decision set — ALLOW, DENY, MODIFY, STEP_UP,
DEFER — plus ABORT (post-ALLOW local failure) and PASSTHROUGH
(non-protected traffic). ALLOW carries the verified claims, immutable
envelope, and injected credentials for downstream use (connector
dispatch, audit). DENY carries a structured reason, the originating
stage, and a detail message for audit and agent error reporting.
MODIFY, STEP_UP, and DEFER are sourced from the @modify("…") /
@step_up("…") / @defer("…") Cedar policy annotations and lifted
into the corresponding variants.
ABORT may be produced by the pipeline only for post-ALLOW local
failures such as credential injection. Authority-pushed ABORT remains
out of scope for V1.
Module: error
Section titled “Module: error”Internal enforcement errors.
Every variant maps to a [DenyReason] via [EnforcementError::into_deny].
This is the fail-closed boundary: errors become DENY decisions.
These types are never exposed to external callers.
Module: registry
Section titled “Module: registry”Canonical Action Class Registry v0.1.
Contains the 52 action classes of registry v0.1: the 15 canonical classes
defined by FEP v0.1 §2.3.5 plus 37 in-place provider-surface additions.
Every intent.action_class field in an ExecutionEnvelope MUST be one
of these identifiers. Unknown protected actions that cannot be
deterministically mapped to a registry entry fail closed with
DENY: UNCLASSIFIED_INTENT (FEP [I-N1]).
Identifiers follow the naming rules in FEP §2.3.2: lowercase ASCII,
dot-separated, describing semantic meaning only. Transport, provider,
and connector names MUST NOT appear in identifiers. See
docs/markdown/firma_action_class_registry.md for the implementation
notes and default mapping strategy.
The same canonical class is produced regardless of whether the underlying action arrives as a native tool call, a CLI invocation, an HTTP request, or an MCP call. Policies and HITL conditions bind to the canonical action class, not to transport-specific names.
Module: revocation
Section titled “Module: revocation”Revocation cache: bloom filter + LRU store.
Implements [firma_core::RevocationStore] for the sidecar. See
docs/tasks/006-revocation-cache.md.
Behavior
Section titled “Behavior”is_revoked: bloom-miss ->Ok(false)fast path. Bloom-hit -> LRU lookup. LRU-hit ->Ok(true). LRU-miss on bloom-positive (either a bloom false positive or an evicted LRU entry) ->Ok(true), to honor the spec’s “REVOKED is terminal” invariant.add_revocation: bloom insert + LRU insert. Idempotent.- V1 never returns
Err; the trait’sResultis kept for forward compatibility.
Module: session
Section titled “Module: session”Session-state store: per-session runtime context for Stage 2.
Contains the [SessionStateStore] trait, the in-memory [LruSessionStateStore]
(default), and the file-backed [PersistentSessionStateStore] (opt-in via
constraint_enforcement.session_state_backend = "persistent").
Module layout
Section titled “Module layout”- [
state] — trait, types (RuntimeSignals,Outcome,ActionOutcome,SessionRecord), and the LRU backend. - [
persistent] — JSONL-backed persistent backend.