use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{
AxiomConstraint, ClaimCeiling, ContextPackId, ProofClosureReport, ProvenanceClass,
SemanticTrustClass,
};
pub const BOUNDARY_SCHEMA_VERSION: u16 = 1;
pub const CORTEX_TO_AXIOM_CONSTRAINT_ENVELOPE_V1: &str = "cortex.boundary.constraint_envelope.v1";
pub const PAI_AXIOM_TO_CORTEX_EXECUTION_RECEIPT_V1: &str =
"pai_axiom.boundary.execution_receipt.v1";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum BoundaryContradictionState {
Resolved,
MultiHypothesis,
Unknown,
Blocked,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum BoundaryQuarantineState {
Clean,
DiagnosticOnly,
Quarantined,
Contaminated,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum BoundaryRedactionState {
RawOperatorOptIn,
Redacted,
Abstracted,
ExportSafe,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AllowedClaimLanguage {
CandidateClaim,
EvidenceReference,
Constraint,
ResidualRisk,
VerificationRequest,
Refusal,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ForbiddenBoundaryUse {
Promotion,
TrustedHistory,
ComplianceEvidence,
Export,
Release,
ExternalReporting,
ExecutionAuthority,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct CortexAxiomConstraintEnvelopeV1 {
pub schema_version: u16,
pub envelope_type: String,
pub context_pack_id: ContextPackId,
pub proof_state: ProofClosureReport,
pub truth_ceiling: ClaimCeiling,
pub semantic_trust: SemanticTrustClass,
pub provenance_class: ProvenanceClass,
pub contradiction_state: BoundaryContradictionState,
pub quarantine_state: BoundaryQuarantineState,
pub redaction_state: BoundaryRedactionState,
pub allowed_claim_language: Vec<AllowedClaimLanguage>,
pub forbidden_uses: Vec<ForbiddenBoundaryUse>,
pub constraints: Vec<AxiomConstraint>,
}
impl CortexAxiomConstraintEnvelopeV1 {
#[must_use]
pub fn new(
context_pack_id: ContextPackId,
proof_state: ProofClosureReport,
truth_ceiling: ClaimCeiling,
semantic_trust: SemanticTrustClass,
provenance_class: ProvenanceClass,
) -> Self {
Self {
schema_version: BOUNDARY_SCHEMA_VERSION,
envelope_type: CORTEX_TO_AXIOM_CONSTRAINT_ENVELOPE_V1.to_string(),
context_pack_id,
proof_state,
truth_ceiling,
semantic_trust,
provenance_class,
contradiction_state: BoundaryContradictionState::Unknown,
quarantine_state: BoundaryQuarantineState::DiagnosticOnly,
redaction_state: BoundaryRedactionState::Abstracted,
allowed_claim_language: default_allowed_claim_language(),
forbidden_uses: default_forbidden_boundary_uses(),
constraints: Vec::new(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum CapabilityTokenDecision {
Allowed,
Warned,
Rejected,
Expired,
Revoked,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct CapabilityTokenState {
pub decision: CapabilityTokenDecision,
pub valid_structure: bool,
pub audience_bound: bool,
pub scope_bound: bool,
pub operation_bound: bool,
pub not_expired: bool,
pub not_revoked: bool,
pub policy_allowed: bool,
pub attestation_linked: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum RuntimeIntegrityState {
Unverified,
VerifiedRelease,
VerifiedProvenance,
Compromised,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct ExecutionTrustState {
pub runtime_integrity: RuntimeIntegrityState,
pub evidence_ref: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum OperatorApprovalState {
NotRequired,
RequiredMissing,
ApprovedBound,
ApprovedUnbound,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum BoundaryToolOutcome {
Succeeded,
Failed,
Blocked,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct BoundaryToolInvocation {
pub tool_name: String,
pub invocation_id: String,
pub input_ref: Option<String>,
pub output_ref: Option<String>,
pub outcome: BoundaryToolOutcome,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct BoundarySourceAnchor {
pub reference: String,
pub kind: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct PaiAxiomExecutionReceiptV1 {
pub schema_version: u16,
pub receipt_type: String,
pub runtime_id: String,
pub capability_token_state: CapabilityTokenState,
pub execution_trust_state: ExecutionTrustState,
pub tool_provenance: Vec<BoundaryToolInvocation>,
pub operator_approval_state: OperatorApprovalState,
pub quarantine_state: BoundaryQuarantineState,
pub source_anchors: Vec<BoundarySourceAnchor>,
pub residual_risk: Vec<String>,
pub explicit_non_promotion: bool,
}
impl PaiAxiomExecutionReceiptV1 {
#[must_use]
pub fn new(
runtime_id: impl Into<String>,
capability_token_state: CapabilityTokenState,
execution_trust_state: ExecutionTrustState,
operator_approval_state: OperatorApprovalState,
) -> Self {
Self {
schema_version: BOUNDARY_SCHEMA_VERSION,
receipt_type: PAI_AXIOM_TO_CORTEX_EXECUTION_RECEIPT_V1.to_string(),
runtime_id: runtime_id.into(),
capability_token_state,
execution_trust_state,
tool_provenance: Vec::new(),
operator_approval_state,
quarantine_state: BoundaryQuarantineState::DiagnosticOnly,
source_anchors: Vec::new(),
residual_risk: Vec::new(),
explicit_non_promotion: true,
}
}
}
#[must_use]
pub fn default_allowed_claim_language() -> Vec<AllowedClaimLanguage> {
vec![
AllowedClaimLanguage::CandidateClaim,
AllowedClaimLanguage::EvidenceReference,
AllowedClaimLanguage::Constraint,
AllowedClaimLanguage::ResidualRisk,
AllowedClaimLanguage::VerificationRequest,
AllowedClaimLanguage::Refusal,
]
}
#[must_use]
pub fn default_forbidden_boundary_uses() -> Vec<ForbiddenBoundaryUse> {
vec![
ForbiddenBoundaryUse::Promotion,
ForbiddenBoundaryUse::TrustedHistory,
ForbiddenBoundaryUse::ComplianceEvidence,
ForbiddenBoundaryUse::Export,
ForbiddenBoundaryUse::Release,
ForbiddenBoundaryUse::ExternalReporting,
ForbiddenBoundaryUse::ExecutionAuthority,
]
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
fn token_state(decision: CapabilityTokenDecision) -> CapabilityTokenState {
CapabilityTokenState {
decision,
valid_structure: true,
audience_bound: true,
scope_bound: true,
operation_bound: true,
not_expired: true,
not_revoked: true,
policy_allowed: true,
attestation_linked: true,
}
}
#[test]
fn boundary_type_strings_are_stable() {
assert_eq!(
CORTEX_TO_AXIOM_CONSTRAINT_ENVELOPE_V1,
"cortex.boundary.constraint_envelope.v1"
);
assert_eq!(
PAI_AXIOM_TO_CORTEX_EXECUTION_RECEIPT_V1,
"pai_axiom.boundary.execution_receipt.v1"
);
}
#[test]
fn boundary_enum_wire_strings_are_stable() {
assert_eq!(
serde_json::to_value(BoundaryContradictionState::MultiHypothesis).unwrap(),
json!("multi_hypothesis")
);
assert_eq!(
serde_json::to_value(BoundaryQuarantineState::DiagnosticOnly).unwrap(),
json!("diagnostic_only")
);
assert_eq!(
serde_json::to_value(BoundaryRedactionState::RawOperatorOptIn).unwrap(),
json!("raw_operator_opt_in")
);
assert_eq!(
serde_json::to_value(AllowedClaimLanguage::VerificationRequest).unwrap(),
json!("verification_request")
);
assert_eq!(
serde_json::to_value(ForbiddenBoundaryUse::TrustedHistory).unwrap(),
json!("trusted_history")
);
assert_eq!(
serde_json::to_value(CapabilityTokenDecision::Revoked).unwrap(),
json!("revoked")
);
assert_eq!(
serde_json::to_value(RuntimeIntegrityState::VerifiedProvenance).unwrap(),
json!("verified_provenance")
);
assert_eq!(
serde_json::to_value(OperatorApprovalState::ApprovedBound).unwrap(),
json!("approved_bound")
);
assert_eq!(
serde_json::to_value(BoundaryToolOutcome::Blocked).unwrap(),
json!("blocked")
);
}
#[test]
fn constraint_envelope_defaults_forbid_authority_bearing_uses() {
let envelope = CortexAxiomConstraintEnvelopeV1::new(
ContextPackId::new(),
ProofClosureReport::full_chain_verified(Vec::new()),
ClaimCeiling::LocalUnsigned,
SemanticTrustClass::CandidateOnly,
ProvenanceClass::RuntimeDerived,
);
assert_eq!(envelope.schema_version, BOUNDARY_SCHEMA_VERSION);
assert_eq!(
envelope.envelope_type,
CORTEX_TO_AXIOM_CONSTRAINT_ENVELOPE_V1
);
assert!(envelope
.forbidden_uses
.contains(&ForbiddenBoundaryUse::ExecutionAuthority));
assert!(envelope
.allowed_claim_language
.contains(&AllowedClaimLanguage::Refusal));
}
#[test]
fn execution_receipt_defaults_to_candidate_only_non_promotion() {
let receipt = PaiAxiomExecutionReceiptV1::new(
"axiom-runtime:v3.1",
token_state(CapabilityTokenDecision::Allowed),
ExecutionTrustState {
runtime_integrity: RuntimeIntegrityState::Unverified,
evidence_ref: None,
},
OperatorApprovalState::NotRequired,
);
assert_eq!(receipt.schema_version, BOUNDARY_SCHEMA_VERSION);
assert_eq!(
receipt.receipt_type,
PAI_AXIOM_TO_CORTEX_EXECUTION_RECEIPT_V1
);
assert!(receipt.explicit_non_promotion);
assert_eq!(
receipt.quarantine_state,
BoundaryQuarantineState::DiagnosticOnly
);
}
}