Runtime Assurance Tiers
Tie a grant’s lifetime and scope to the runtime evidence behind it, and have the executing kernel check that evidence again.
On this page
Baseline workloads can hold short, narrow grants while longer or costlier authority goes only to workloads with stronger runtime evidence. The issuing node turns that evidence into a tier, caps the grant at the tier's ceiling, and signs the required minimum into the grant.
The tier order is none < basic < attested < verified. Tiers are policy classifications an operator defines, and the effective tier a node assigns can differ from the tier the evidence declares.
The issuer and the executing kernel each appraise the evidence
Issuance and execution are two decisions under two trust policies, on evidence presented twice.
The issuer’s rules set the tier, and the tier sets the ceiling
A matching trust rule assigns the evidence an effective tier of verified. The highest tier that accepts it, elevated, permits 300 seconds, so the 120-second request passes. The capability authority signs the grant with MinimumRuntimeAssurance set to the selected tier’s minimum. Capabilities.
A capability issued by one node can be refused at another whose trust rules accept less of the presented evidence. Replicating the signing authority leaves each kernel's runtime policy local, so the trust rules belong on every node where the grant will run.
Read more in Policy Rollout, which deploys trust rules with the binary and the rest of the policy.
A trust rule turns normalized evidence into an effective tier
The request carries normalized runtime attestation evidence. An operator-configured trust rule matches its schema and canonical verifier, optionally refined by family, age, type, and normalized assertions, and assigns the effective tier.
- No evidence. No appraised record exists, and tier selection uses
none. - Evidence, no rules. A recognized, live record is unaccepted at effective tier
none, whatever it declares. - Rules, no match. Appraisal fails with
UntrustedEvidence, with no fallback to a baseline tier. - A matching rule. The first rule in name order that matches schema, canonical verifier, and any family restriction supplies the further checks. A failed age, type, or assertion requirement fails at that rule; a full pass accepts the evidence at the rule's tier.
- Unknown or stale. An unknown schema, stale evidence, or an invalid identity binding fails appraisal. An unknown schema never becomes a lower tier.
Validity uses Unix seconds, start included and expiry excluded, and a rule can add a maximum evidence age. HushSpec materializes rules in name order, so file order carries no precedence. A rule can accept a record at none, and evidence that declares verified can end with no accepted tier.
Appraisal reads the values the request carries: a rule naming a verifier URL and a secure-boot assertion matches those fields. Their authenticity comes from the verification adapter that checked the raw artifact before the evidence reached the issue route, and that integration keeps the original artifact and its subject binding.
The policy outcome in Rust
fn verify_runtime_attestation_policy_outcome(
evidence: &RuntimeAttestationEvidence,
trust_policy: Option<&AttestationTrustPolicy>,
now: u64,
) -> Result<VerifiedRuntimeAttestationPolicyVerification, RuntimeAttestationVerificationError> {
let trust_policy_configured = trust_policy.is_some_and(|policy| !policy.rules.is_empty());
if trust_policy_configured {
let resolved = evidence
.resolve_effective_runtime_assurance(trust_policy, now)
.map_err(RuntimeAttestationVerificationError::TrustPolicy)?;
let matched_trust_rule = resolved.matched_rule.clone();
return Ok(VerifiedRuntimeAttestationPolicyVerification {
outcome: RuntimeAttestationPolicyOutcome {
trust_policy_configured: true,
accepted: true,
effective_tier: resolved.effective_tier,
reason: matched_trust_rule
.as_ref()
.map(|rule| format!("matched attestation trust rule `{rule}`")),
},
matched_trust_rule,
});
}
evidence.validate_workload_identity_binding()?;
if !evidence.is_valid_at(now) {
return Err(RuntimeAttestationVerificationError::StaleEvidence {
now,
issued_at: evidence.issued_at,
expires_at: evidence.expires_at,
});
}
Ok(VerifiedRuntimeAttestationPolicyVerification {
outcome: RuntimeAttestationPolicyOutcome {
trust_policy_configured: false,
accepted: false,
effective_tier: RuntimeAssuranceTier::None,
reason: Some(
"runtime attestation evidence did not cross a local verified trust boundary"
.to_string(),
),
},
matched_trust_rule: None,
})
}The issuance wrapper applies this stricter outcome. The lower-level evidence resolver, called directly with no rules, returns the declared tier.
The highest tier the evidence satisfies sets the ceiling
Loaded tiers sort by minimum assurance, and the highest minimum the effective tier satisfies wins. When no tier accepts the effective level, issuance fails, so a baseline tier at none is an explicit choice. This HushSpec fragment defines two tiers and one trust rule:
extensions:
runtime_assurance:
tiers:
baseline:
minimum_attestation_tier: none
max_scope:
operations: [invoke]
ttl_seconds: 60
elevated:
minimum_attestation_tier: verified
max_scope:
operations: [invoke]
ttl_seconds: 300
trusted_verifiers:
operator_verifier:
schema: chio.runtime-attestation.enterprise-verifier.json.v1
verifier: https://verifier.larkfield.example
verifier_family: enterprise_verifier
effective_tier: verified
max_evidence_age_seconds: 120A 120-second request with no matching rule selects baseline and is refused at its 60-second ceiling; a lifetime above ttl_seconds is refused rather than shortened. When the rule assigns verified, the same request selects elevated and passes its 300-second ceiling. Grants must also request a subset of the permitted operations and carry caps at or below the ceiling's.
The standard loader materializes this policy from HushSpec's extensions.runtime_assurance; Chio YAML leaves it unset, and evidence in a request enables no gating by itself. Replace the example verifier with your evidence integration's identity. A loaded-policy node also installs these trust rules into its kernel for governed-call appraisal, so deploy them on every enforcing kernel.
A sensitive grant carries its minimum tier into the signed scope
After the ceiling passes, a tier above none adds MinimumRuntimeAssurance to economically sensitive tool grants. The value is the selected tier's minimum, which can sit below the evidence's effective tier.
A tool grant is sensitive when it carries a per-call or total cost cap, or a constraint that requires governed intent, approval above an amount, an exact seller, or a minimum autonomy tier. Resource and prompt grants keep their shape. The inner authority signs the narrowed scope, the wrapper validates the token against it, and the response returns the capability with that scope, so compare it with the request to see what changed.
A call under the constrained grant runs through governed validation with evidence in governed_intent.runtime_attestation, which the executing kernel appraises under its own rules. Missing evidence, a result it does not accept, or an effective tier below the minimum ends in a governed-transaction denial. The kernel's capability, policy, approval, and economic checks still apply.
Read more in Capabilities, which covers reading and constraining a signed grant.
Issuance checks identity first, then evidence, reputation, and tier
POST /v1/capabilities/issue authenticates the authority mutation, forwards to the leader when necessary, and applies the authority fence. The request carries the subject public key, the requested scope, the TTL, and an optional runtimeAttestation.
Before loading the issuer, the handler validates the subject-key encoding and checks that the evidence's workload identity and runtime identity agree. A conflicting SPIFFE identity, or an explicit workload identity paired with an opaque runtime identity, answers 400. Possession of the workload identity and the binding of a hardware quote to the subject key come from the verification integration.
Inside the policy wrapper, attestation appraisal runs first, reputation gating second, and runtime tier enforcement third, and the inner authority then signs the scope. A refusal at any stage answers 403 with its reason.
Read more in Leader & Failover and Authority & Rotation, which cover the admission and signing state around issuance.
Runtime assurance records, ceilings, and adapters
Try baseline lifetime, max_delegation_depth, or AWS Nitro.
Records
- Runtime attestation evidence. Requester-supplied schema, verifier, declared tier, validity times, evidence digest, identities, and optional claims, in normalized form. Appraisal derives normalized assertions from the claims of four recognized schema families and takes
evidence_sha256as supplied. - Attestation trust rule. An operator-configured match on schema and canonical verifier, optionally refined by family, age, type, and normalized assertions. A successful rule assigns the effective tier.
- Assurance tier policy. A named minimum tier and scope ceiling: permitted operations, lifetime, invocation and cost limits, and constraint requirements.
- Appraised record. Evidence, normalized subject, verifier provenance, matched rule, and a policy outcome with
acceptedandeffective_tier. - Signed capability. The authority the agent presents. A sensitive tool grant can carry
MinimumRuntimeAssuranceafter tier enforcement.
Ceiling fields
ttl_seconds. A requested lifetime above it is refused, never shortened.- Operations. Each tool, resource, and prompt grant must request a subset of the permitted operations. The ceiling copies the requested target, so it leaves the choice of reachable tool or resource to the grant.
- Invocation and cost caps. Tool grants carry caps at or below the configured ceiling, and an uncapped request fails a capped ceiling. Cost comparison requires one currency, with no conversion.
max_delegation_depth. A value of zero refuses the delegate operation on tool grants; the ceiling check reads no other value of it.constraints_required. Requires a nonempty tool-constraint list and copies those constraints into the comparison grant, accepting any constraint. A cumulative-approval constraint must also survive in the parent comparison grant, so withconstraints_required: falsethe comparison list is empty and a request carryingRequireCumulativeApprovalAbovefails the ceiling.- DPoP. The synthetic ceiling carries no DPoP requirement; DPoP is configured through the grant and its runtime path.
A declared verified tier still fails the baseline lifetime
Two tiers are configured: baseline permits 60 seconds at none, and elevated permits 300 seconds at verified. A request asks for 120 seconds and supplies recognized, live evidence that declares verified; its other fields pass their checks. The values are chosen to show the tier stage.
- No trust rules. Effective tier
noneselects baseline. The 120-second request exceeds its 60-second ceiling and is refused. - A matching rule assigns
verified. Elevated is selected. The request passes its 300-second TTL check; the remaining ceiling and issuance checks still apply. - Rules configured, verifier unmatched. Appraisal fails with
UntrustedEvidencebefore tier selection.
Verification adapters
The control-plane library exposes four adapters that verify raw artifacts and produce normalized evidence, separately from the schema-based appraisal on the issue route.
- Azure MAA. A supported RSA-signed JWT checked against supplied JWKs, the expected issuer, token lifetime, and the configured attestation claim requirements.
- AWS Nitro. An ES384 COSE document and certificate chain checked against configured roots, with document validation including measurement and age requirements.
- Google Confidential VM. An RS256 JWT checked against supplied JWKs, issuer, and lifetime, with hardware claims and configured audience or workload requirements.
- Enterprise verifier. A signed evidence envelope checked against configured trusted signer keys, schema and verifier, lifetime, maximum age, and allowed declared tier. Its signing-key trust set is configured in the verification integration.
The adapter policies cap their output at attested. A trust rule can then assign verified, an operator classification that adds no cryptographic check of its own.
Enclave verification
Confidential Node covers enclave deployment with its own quote and key-custody contracts. A normalized runtime tier stands apart from those contracts, so keep the original verification evidence and the integration that connects it to the request you authorize.
Refusal diagnosis
- 400 on issue. The subject-key encoding and the consistency of the supplied workload and runtime identities. Malformed input can fail before appraisal.
- 403 on issue. The returned reason: evidence schema, lifetime, trust-rule matching, selected tier, TTL, or scope ceiling. A declared tier never overrides local rules.
- 500 on issue. An authority or policy error. Errors other than
CapabilityIssuanceDenied, including returned-token validation failures, map to 500. - Governed call refused after issuance. The governed intent, the evidence on this call, and the executing kernel's accepted outcome and minimum tier.
Source locations
crates/platform/chio-control-plane/src/issuance/authority.rsandscope.rs: gate order, ceilings, and the signed scope.crates/economy/chio-appraisal/src/appraisal.rs: normalized evidence and the local policy outcome.crates/kernel/chio-kernel/src/kernel/governed_validation.rs: intent, local acceptance, and the minimum-tier comparison.