aura_core/effects/
runtime_capability.rs1use async_trait::async_trait;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default)]
11pub struct CapabilityKey(String);
12
13impl CapabilityKey {
14 pub fn new(key: impl Into<String>) -> Self {
16 Self(key.into())
17 }
18
19 pub fn as_str(&self) -> &str {
21 &self.0
22 }
23}
24
25impl std::fmt::Display for CapabilityKey {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 f.write_str(&self.0)
28 }
29}
30
31impl From<String> for CapabilityKey {
32 fn from(value: String) -> Self {
33 Self::new(value)
34 }
35}
36
37impl From<&str> for CapabilityKey {
38 fn from(value: &str) -> Self {
39 Self::new(value)
40 }
41}
42
43#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, Serialize, Deserialize)]
45pub enum AdmissionError {
46 #[error("missing runtime capability: {capability}")]
48 MissingCapability { capability: CapabilityKey },
49 #[error("missing required theorem pack: {theorem_pack}")]
51 MissingTheoremPack { theorem_pack: String },
52 #[error("missing theorem-pack capability `{capability}` for `{theorem_pack}`")]
54 MissingTheoremPackCapability {
55 theorem_pack: String,
56 capability: CapabilityKey,
57 },
58 #[error("runtime capability inventory unavailable: {reason}")]
60 InventoryUnavailable { reason: String },
61 #[error("missing runtime contracts for capability admission")]
63 MissingRuntimeContracts,
64 #[error("runtime capability admission internal error: {reason}")]
66 Internal { reason: String },
67}
68
69#[async_trait]
71pub trait RuntimeCapabilityEffects: Send + Sync {
72 async fn capability_inventory(&self) -> Result<Vec<(CapabilityKey, bool)>, AdmissionError>;
74
75 async fn require_capabilities(&self, required: &[CapabilityKey]) -> Result<(), AdmissionError> {
77 let inventory = self.capability_inventory().await?;
78 for required_key in required {
79 let admitted = inventory
80 .iter()
81 .find(|(present_key, _)| present_key == required_key)
82 .is_some_and(|(_, admitted)| *admitted);
83 if !admitted {
84 return Err(AdmissionError::MissingCapability {
85 capability: required_key.clone(),
86 });
87 }
88 }
89 Ok(())
90 }
91}
92
93#[async_trait]
94impl<T: RuntimeCapabilityEffects + ?Sized> RuntimeCapabilityEffects for std::sync::Arc<T> {
95 async fn capability_inventory(&self) -> Result<Vec<(CapabilityKey, bool)>, AdmissionError> {
96 (**self).capability_inventory().await
97 }
98
99 async fn require_capabilities(&self, required: &[CapabilityKey]) -> Result<(), AdmissionError> {
100 (**self).require_capabilities(required).await
101 }
102}