use cortex_core::{
AuthorityClass, ClaimCeiling, ClaimProofState, PolicyDecision, PolicyOutcome, ReportableClaim,
RuntimeMode,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RuntimeClaimKind {
Diagnostic,
Advisory,
TrustedHistory,
Export,
Promotion,
ReleaseReadiness,
ComplianceEvidence,
CrossSystemTrust,
}
impl RuntimeClaimKind {
#[must_use]
pub const fn required_ceiling(self) -> ClaimCeiling {
match self {
Self::Diagnostic | Self::Advisory => ClaimCeiling::DevOnly,
Self::TrustedHistory => ClaimCeiling::SignedLocalLedger,
Self::Export => ClaimCeiling::ExternallyAnchored,
Self::Promotion
| Self::ReleaseReadiness
| Self::ComplianceEvidence
| Self::CrossSystemTrust => ClaimCeiling::AuthorityGrade,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CompiledRuntimeClaim {
pub claim: String,
pub kind: RuntimeClaimKind,
pub runtime_mode: RuntimeMode,
pub authority_class: AuthorityClass,
pub proof_state: ClaimProofState,
pub requested_ceiling: ClaimCeiling,
pub effective_ceiling: ClaimCeiling,
pub required_ceiling: ClaimCeiling,
pub allowed: bool,
pub reasons: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum DevelopmentLedgerUse {
LocalDiagnostic,
AuditExport,
ComplianceEvidence,
CrossSystemTrustDecision,
ExternalReporting,
}
impl DevelopmentLedgerUse {
#[must_use]
pub const fn wire_str(self) -> &'static str {
match self {
Self::LocalDiagnostic => "local_diagnostic",
Self::AuditExport => "audit_export",
Self::ComplianceEvidence => "compliance_evidence",
Self::CrossSystemTrustDecision => "cross_system_trust_decision",
Self::ExternalReporting => "external_reporting",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DevelopmentLedgerUseDecision {
pub requested_use: DevelopmentLedgerUse,
pub allowed: bool,
pub reason: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RuntimeClaimPreflight {
pub claim: CompiledRuntimeClaim,
pub allowed: bool,
pub reason: String,
}
#[must_use]
pub fn development_ledger_use_decision(
payload: &Value,
requested_use: DevelopmentLedgerUse,
) -> DevelopmentLedgerUseDecision {
let ledger_authority = payload.get("ledger_authority").and_then(Value::as_str);
let signed_ledger_authority = payload
.get("signed_ledger_authority")
.and_then(Value::as_bool);
let forbidden = payload
.get("forbidden_uses")
.and_then(Value::as_array)
.is_some_and(|uses| {
uses.iter()
.any(|value| value.as_str() == Some(requested_use.wire_str()))
});
if requested_use == DevelopmentLedgerUse::LocalDiagnostic {
return DevelopmentLedgerUseDecision {
requested_use,
allowed: true,
reason: "local diagnostics do not upgrade development-ledger authority".into(),
};
}
if forbidden {
DevelopmentLedgerUseDecision {
requested_use,
allowed: false,
reason: format!("ledger data is forbidden for {}", requested_use.wire_str()),
}
} else if ledger_authority == Some("development") || signed_ledger_authority == Some(false) {
DevelopmentLedgerUseDecision {
requested_use,
allowed: false,
reason: format!(
"development-ledger data is forbidden for {}",
requested_use.wire_str()
),
}
} else if ledger_authority == Some("signed_local")
|| (signed_ledger_authority == Some(true)
&& !matches!(
ledger_authority,
Some("externally_anchored" | "authority_grade")
))
{
DevelopmentLedgerUseDecision {
requested_use,
allowed: false,
reason: format!(
"signed-local ledger data is forbidden for {} without external authority",
requested_use.wire_str()
),
}
} else {
DevelopmentLedgerUseDecision {
requested_use,
allowed: true,
reason: "payload does not declare this requested use as forbidden".into(),
}
}
}
#[must_use]
pub fn compile_runtime_claim(
claim: impl Into<String>,
kind: RuntimeClaimKind,
runtime_mode: RuntimeMode,
authority_class: AuthorityClass,
proof_state: ClaimProofState,
requested_ceiling: ClaimCeiling,
) -> CompiledRuntimeClaim {
let reportable = ReportableClaim::new(
claim,
runtime_mode,
authority_class,
proof_state,
requested_ceiling,
);
let required_ceiling = kind.required_ceiling();
let effective_ceiling = reportable.effective_ceiling();
let allowed = effective_ceiling >= required_ceiling;
let mut reasons = reportable.downgrade_reasons().to_vec();
if !allowed {
reasons.push(format!(
"{kind:?} requires {required_ceiling:?}, but effective ceiling is {effective_ceiling:?}"
));
}
CompiledRuntimeClaim {
claim: reportable.claim().to_string(),
kind,
runtime_mode: reportable.runtime_mode(),
authority_class: reportable.authority_class(),
proof_state: reportable.proof_state(),
requested_ceiling: reportable.requested_ceiling(),
effective_ceiling,
required_ceiling,
allowed,
reasons,
}
}
#[must_use]
pub fn runtime_claim_preflight(
claim: impl Into<String>,
kind: RuntimeClaimKind,
runtime_mode: RuntimeMode,
authority_class: AuthorityClass,
proof_state: ClaimProofState,
requested_ceiling: ClaimCeiling,
) -> RuntimeClaimPreflight {
let compiled = compile_runtime_claim(
claim,
kind,
runtime_mode,
authority_class,
proof_state,
requested_ceiling,
);
let reason = if compiled.allowed {
let effective_ceiling = compiled.effective_ceiling;
format!("{kind:?} allowed at effective ceiling {effective_ceiling:?}")
} else {
compiled.reasons.last().cloned().unwrap_or_else(|| {
let effective_ceiling = compiled.effective_ceiling;
let required_ceiling = compiled.required_ceiling;
format!("{kind:?} denied because effective ceiling {effective_ceiling:?} is below required {required_ceiling:?}")
})
};
RuntimeClaimPreflight {
allowed: compiled.allowed,
claim: compiled,
reason,
}
}
#[must_use]
pub fn runtime_claim_preflight_with_policy(
claim: impl Into<String>,
kind: RuntimeClaimKind,
runtime_mode: RuntimeMode,
authority_class: AuthorityClass,
proof_state: ClaimProofState,
requested_ceiling: ClaimCeiling,
policy: &PolicyDecision,
) -> RuntimeClaimPreflight {
let mut preflight = runtime_claim_preflight(
claim,
kind,
runtime_mode,
authority_class,
proof_state,
requested_ceiling,
);
let policy_ceiling = policy.final_outcome.claim_ceiling();
if policy_ceiling < preflight.claim.effective_ceiling {
preflight.claim.effective_ceiling = policy_ceiling;
let final_outcome = policy.final_outcome;
preflight.claim.reasons.push(format!(
"policy outcome {final_outcome:?} limits authority claims"
));
}
if matches!(
policy.final_outcome,
PolicyOutcome::Reject | PolicyOutcome::Quarantine
) {
preflight.allowed = false;
let final_outcome = policy.final_outcome;
preflight.reason = format!("policy outcome {final_outcome:?} fails closed for {kind:?}");
} else {
preflight.allowed = preflight.claim.effective_ceiling >= preflight.claim.required_ceiling;
if !preflight.allowed {
let required_ceiling = preflight.claim.required_ceiling;
let effective_ceiling = preflight.claim.effective_ceiling;
preflight.reason = format!(
"{kind:?} requires {required_ceiling:?}, but effective ceiling is {effective_ceiling:?}"
);
}
}
preflight
}
pub fn require_runtime_claim(
claim: impl Into<String>,
kind: RuntimeClaimKind,
runtime_mode: RuntimeMode,
authority_class: AuthorityClass,
proof_state: ClaimProofState,
requested_ceiling: ClaimCeiling,
) -> Result<RuntimeClaimPreflight, RuntimeClaimPreflight> {
let preflight = runtime_claim_preflight(
claim,
kind,
runtime_mode,
authority_class,
proof_state,
requested_ceiling,
);
if preflight.allowed {
Ok(preflight)
} else {
Err(preflight)
}
}
pub fn require_runtime_claim_with_policy(
claim: impl Into<String>,
kind: RuntimeClaimKind,
runtime_mode: RuntimeMode,
authority_class: AuthorityClass,
proof_state: ClaimProofState,
requested_ceiling: ClaimCeiling,
policy: &PolicyDecision,
) -> Result<RuntimeClaimPreflight, RuntimeClaimPreflight> {
let preflight = runtime_claim_preflight_with_policy(
claim,
kind,
runtime_mode,
authority_class,
proof_state,
requested_ceiling,
policy,
);
if preflight.allowed {
Ok(preflight)
} else {
Err(preflight)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dev_fixture_cannot_emit_release_claim() {
let claim = compile_runtime_claim(
"ready for release",
RuntimeClaimKind::ReleaseReadiness,
RuntimeMode::Dev,
AuthorityClass::Operator,
ClaimProofState::FullChainVerified,
ClaimCeiling::AuthorityGrade,
);
assert!(!claim.allowed);
assert_eq!(claim.effective_ceiling, ClaimCeiling::DevOnly);
assert!(claim
.reasons
.iter()
.any(|reason| reason.contains("ReleaseReadiness requires AuthorityGrade")));
}
#[test]
fn local_unsigned_run_cannot_emit_trusted_history() {
let claim = compile_runtime_claim(
"trusted run history",
RuntimeClaimKind::TrustedHistory,
RuntimeMode::LocalUnsigned,
AuthorityClass::Operator,
ClaimProofState::FullChainVerified,
ClaimCeiling::AuthorityGrade,
);
assert!(!claim.allowed);
assert_eq!(claim.effective_ceiling, ClaimCeiling::LocalUnsigned);
}
#[test]
fn unknown_runtime_cannot_emit_authority_claims() {
for kind in [
RuntimeClaimKind::Promotion,
RuntimeClaimKind::TrustedHistory,
RuntimeClaimKind::Export,
RuntimeClaimKind::ComplianceEvidence,
RuntimeClaimKind::ReleaseReadiness,
RuntimeClaimKind::CrossSystemTrust,
] {
let claim = compile_runtime_claim(
"authority claim",
kind,
RuntimeMode::Unknown,
AuthorityClass::Operator,
ClaimProofState::FullChainVerified,
ClaimCeiling::AuthorityGrade,
);
assert!(!claim.allowed, "{kind:?} must fail in unknown runtime");
assert_eq!(claim.effective_ceiling, ClaimCeiling::DevOnly);
}
}
#[test]
fn signed_full_chain_can_emit_trusted_history() {
let claim = compile_runtime_claim(
"trusted run history",
RuntimeClaimKind::TrustedHistory,
RuntimeMode::SignedLocalLedger,
AuthorityClass::Verified,
ClaimProofState::FullChainVerified,
ClaimCeiling::SignedLocalLedger,
);
assert!(claim.allowed);
assert_eq!(claim.effective_ceiling, ClaimCeiling::SignedLocalLedger);
}
#[test]
fn preflight_fails_closed_for_authority_surfaces_above_ceiling() {
for kind in [
RuntimeClaimKind::ReleaseReadiness,
RuntimeClaimKind::Export,
RuntimeClaimKind::Promotion,
RuntimeClaimKind::ComplianceEvidence,
] {
let preflight = runtime_claim_preflight(
"authority surface",
kind,
RuntimeMode::LocalUnsigned,
AuthorityClass::Observed,
ClaimProofState::Partial,
ClaimCeiling::AuthorityGrade,
);
assert!(!preflight.allowed, "{kind:?} must fail closed");
assert_eq!(
preflight.claim.effective_ceiling,
ClaimCeiling::LocalUnsigned
);
assert!(
preflight.reason.contains("requires")
|| preflight.reason.contains("below required"),
"preflight reason should explain the ceiling failure"
);
}
}
#[test]
fn preflight_allows_promotion_only_at_authority_grade() {
let preflight = runtime_claim_preflight(
"attested doctrine promotion",
RuntimeClaimKind::Promotion,
RuntimeMode::AuthorityGrade,
AuthorityClass::Operator,
ClaimProofState::FullChainVerified,
ClaimCeiling::AuthorityGrade,
);
assert!(preflight.allowed);
assert_eq!(
preflight.claim.effective_ceiling,
ClaimCeiling::AuthorityGrade
);
}
#[test]
fn policy_reject_and_quarantine_downgrade_claim_preflight() {
for outcome in [PolicyOutcome::Reject, PolicyOutcome::Quarantine] {
let policy = PolicyDecision {
final_outcome: outcome,
contributing: Vec::new(),
discarded: Vec::new(),
break_glass: None,
};
let preflight = runtime_claim_preflight_with_policy(
"trusted export",
RuntimeClaimKind::Export,
RuntimeMode::ExternallyAnchored,
AuthorityClass::Operator,
ClaimProofState::FullChainVerified,
ClaimCeiling::ExternallyAnchored,
&policy,
);
assert!(!preflight.allowed);
assert_eq!(preflight.claim.effective_ceiling, ClaimCeiling::DevOnly);
assert!(preflight.reason.contains("policy outcome"));
}
}
#[test]
fn policy_warn_does_not_soften_ceiling_failure() {
let policy = PolicyDecision {
final_outcome: PolicyOutcome::Warn,
contributing: Vec::new(),
discarded: Vec::new(),
break_glass: None,
};
let preflight = runtime_claim_preflight_with_policy(
"trusted history",
RuntimeClaimKind::TrustedHistory,
RuntimeMode::LocalUnsigned,
AuthorityClass::Observed,
ClaimProofState::Partial,
ClaimCeiling::AuthorityGrade,
&policy,
);
assert!(!preflight.allowed);
assert_eq!(
preflight.claim.effective_ceiling,
ClaimCeiling::LocalUnsigned
);
}
#[test]
fn development_ledger_denies_all_forbidden_external_uses() {
let payload = serde_json::json!({
"ledger_authority": "development",
"signed_ledger_authority": false,
"forbidden_uses": [
"audit_export",
"compliance_evidence",
"cross_system_trust_decision",
"external_reporting"
]
});
for requested_use in [
DevelopmentLedgerUse::AuditExport,
DevelopmentLedgerUse::ComplianceEvidence,
DevelopmentLedgerUse::CrossSystemTrustDecision,
DevelopmentLedgerUse::ExternalReporting,
] {
let decision = development_ledger_use_decision(&payload, requested_use);
assert!(
!decision.allowed,
"{requested_use:?} should be forbidden for development ledger"
);
}
}
#[test]
fn development_ledger_allows_local_diagnostic_only() {
let payload = serde_json::json!({
"ledger_authority": "development",
"signed_ledger_authority": false,
"forbidden_uses": ["audit_export"]
});
let decision =
development_ledger_use_decision(&payload, DevelopmentLedgerUse::LocalDiagnostic);
assert!(decision.allowed);
assert!(decision.reason.contains("do not upgrade"));
}
#[test]
fn externally_anchored_payload_is_not_blocked_by_ledger_gate() {
let payload = serde_json::json!({
"ledger_authority": "externally_anchored",
"signed_ledger_authority": true,
"forbidden_uses": []
});
let decision = development_ledger_use_decision(&payload, DevelopmentLedgerUse::AuditExport);
assert!(decision.allowed);
}
#[test]
fn signed_local_payload_still_honors_explicit_forbidden_uses() {
let payload = serde_json::json!({
"ledger_authority": "signed_local",
"signed_ledger_authority": true,
"trusted_run_history": true,
"forbidden_uses": ["audit_export", "compliance_evidence"]
});
let audit = development_ledger_use_decision(&payload, DevelopmentLedgerUse::AuditExport);
let compliance =
development_ledger_use_decision(&payload, DevelopmentLedgerUse::ComplianceEvidence);
let local =
development_ledger_use_decision(&payload, DevelopmentLedgerUse::LocalDiagnostic);
assert!(!audit.allowed);
assert!(!compliance.allowed);
assert!(local.allowed);
}
#[test]
fn signed_local_payload_cannot_be_used_for_external_surfaces_without_forbidden_uses() {
let payload = serde_json::json!({
"ledger_authority": "signed_local",
"signed_ledger_authority": true,
"trusted_run_history": true
});
for requested_use in [
DevelopmentLedgerUse::AuditExport,
DevelopmentLedgerUse::ComplianceEvidence,
DevelopmentLedgerUse::CrossSystemTrustDecision,
DevelopmentLedgerUse::ExternalReporting,
] {
let decision = development_ledger_use_decision(&payload, requested_use);
assert!(
!decision.allowed,
"{requested_use:?} should be forbidden for signed-local ledger"
);
assert!(
decision.reason.contains("signed-local ledger"),
"reason should name signed-local boundary: {}",
decision.reason
);
}
}
}