1use chio_core::capability::{
2 CapabilityToken, CapabilityTokenBody, ChioScope, RuntimeAttestationEvidence,
3};
4use chio_core::crypto::{Keypair, PublicKey};
5use uuid::Uuid;
6
7use crate::KernelError;
8
9pub trait CapabilityAuthority: Send + Sync {
10 fn authority_public_key(&self) -> PublicKey;
11
12 fn trusted_public_keys(&self) -> Vec<PublicKey> {
13 vec![self.authority_public_key()]
14 }
15
16 fn issue_capability(
17 &self,
18 subject: &PublicKey,
19 scope: ChioScope,
20 ttl_seconds: u64,
21 ) -> Result<CapabilityToken, KernelError>;
22
23 fn issue_capability_with_attestation(
24 &self,
25 subject: &PublicKey,
26 scope: ChioScope,
27 ttl_seconds: u64,
28 _runtime_attestation: Option<RuntimeAttestationEvidence>,
29 ) -> Result<CapabilityToken, KernelError> {
30 self.issue_capability(subject, scope, ttl_seconds)
31 }
32}
33
34pub struct LocalCapabilityAuthority {
35 keypair: Keypair,
36}
37
38impl LocalCapabilityAuthority {
39 pub fn new(keypair: Keypair) -> Self {
40 Self { keypair }
41 }
42}
43
44impl CapabilityAuthority for LocalCapabilityAuthority {
45 fn authority_public_key(&self) -> PublicKey {
46 self.keypair.public_key()
47 }
48
49 fn issue_capability(
50 &self,
51 subject: &PublicKey,
52 scope: ChioScope,
53 ttl_seconds: u64,
54 ) -> Result<CapabilityToken, KernelError> {
55 let now = std::time::SystemTime::now()
56 .duration_since(std::time::UNIX_EPOCH)
57 .map(|duration| duration.as_secs())
58 .unwrap_or(0);
59 let body = CapabilityTokenBody {
60 id: format!("cap-{}", Uuid::now_v7()),
61 issuer: self.keypair.public_key(),
62 subject: subject.clone(),
63 scope,
64 issued_at: now,
65 expires_at: now.saturating_add(ttl_seconds),
66 delegation_chain: vec![],
67 };
68
69 CapabilityToken::sign(body, &self.keypair)
70 .map_err(|error| KernelError::CapabilityIssuanceFailed(error.to_string()))
71 }
72}
73
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct AuthorityStatus {
76 pub public_key: PublicKey,
77 pub generation: u64,
78 pub rotated_at: u64,
79 pub trusted_public_keys: Vec<PublicKey>,
80}
81
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub struct AuthorityTrustedKeySnapshot {
84 pub public_key_hex: String,
85 pub generation: u64,
86 pub activated_at: u64,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct AuthoritySnapshot {
91 pub public_key_hex: String,
92 pub generation: u64,
93 pub rotated_at: u64,
94 pub trusted_keys: Vec<AuthorityTrustedKeySnapshot>,
95}
96
97#[derive(Debug, thiserror::Error)]
98pub enum AuthorityStoreError {
99 #[error("sqlite error: {0}")]
100 Sqlite(#[from] rusqlite::Error),
101
102 #[error("failed to prepare authority store directory: {0}")]
103 Io(#[from] std::io::Error),
104
105 #[error("invalid authority seed: {0}")]
106 Core(#[from] chio_core::error::Error),
107
108 #[error("authority fence rejected mutation: {0}")]
109 Fence(String),
110}