clawft_kernel/licence/
policy.rs1use std::sync::Arc;
13
14use super::{CheckoutGrantStore, VerifiedCheckoutGrant};
15use crate::mesh_artifact::ArtifactExchange;
16use crate::mesh_swarm_state::{
17 Audience, GrantInfo, GrantOrigin, ManifestPolicy, RedistributionPolicy,
18};
19use crate::workload_pkg::codec::hex_encode;
20
21pub const CHECKOUT_PACKAGE_PREFIX: &str = "checkout:";
23
24#[derive(Debug)]
26pub struct MeshCheckoutPolicy {
27 base: ManifestPolicy,
28 store: Arc<CheckoutGrantStore>,
29}
30
31impl MeshCheckoutPolicy {
32 pub fn new(store: Arc<CheckoutGrantStore>) -> Self {
34 Self { base: ManifestPolicy, store }
35 }
36
37 pub fn open(
43 dir: &std::path::Path,
44 anchors: crate::workload_pkg::TrustAnchors,
45 revocations: Arc<crate::revocation::RevocationList>,
46 local: super::LocalMeshId,
47 ) -> Arc<Self> {
48 let store = CheckoutGrantStore::open_or_poisoned(
49 &dir.join("licence"),
50 Arc::new(anchors),
51 local,
52 super::system_clock(),
53 );
54 if let Some(why) = store.poisoned() {
55 tracing::warn!(%why, "licence store unreadable; checkout policy stays off");
56 }
57 store.attach_revocations(revocations);
58 Arc::new(Self::new(Arc::new(store)))
59 }
60
61 pub fn store(&self) -> &Arc<CheckoutGrantStore> {
63 &self.store
64 }
65}
66
67impl RedistributionPolicy for MeshCheckoutPolicy {
68 fn allows(&self, hash: &[u8; 32], grants: &[GrantInfo], audience: &Audience<'_>) -> bool {
69 if self.base.allows(hash, grants, audience) {
70 return true;
71 }
72 match audience {
73 Audience::Advertise => return false,
74 Audience::Serve(peer) if !peer.verified => return false,
75 _ => {}
76 }
77 if grants.is_empty() {
78 return false;
79 }
80 let hex = hex_encode(hash);
81 grants.iter().filter(|g| !g.is_opt_in()).all(|g| match &g.origin {
82 GrantOrigin::Cognitum { cog_id, version } => {
83 self.store.valid_grant_covering(&hex, cog_id, version).is_some()
84 }
85 _ => false,
86 })
87 }
88}
89
90impl ArtifactExchange {
91 pub fn grant_checkout(&self, v: &VerifiedCheckoutGrant) {
97 let g = v.grant();
98 let package = format!("{CHECKOUT_PACKAGE_PREFIX}{}@{}", g.cog_id, g.version);
99 for a in &g.artifacts {
100 let Some(hash) = crate::workload_pkg::codec::hex_decode_exact::<32>(&a.blake3) else {
101 continue;
102 };
103 self.grant_with(
104 hash,
105 &package,
106 vec![v.grant_pubkey_hex().to_owned()],
107 GrantOrigin::Cognitum { cog_id: g.cog_id.clone(), version: g.version.clone() },
108 );
109 }
110 }
111}