clawft_kernel/licence/
binding.rs1pub use weft_licence_wire::{BindState, BindingRecord, SignedBinding, sign_binding};
4
5use super::{LicenceError, MeshId};
6use crate::workload_pkg::codec::hex_decode_exact;
7use crate::workload_pkg::{KeyOrigin, TrustAnchors};
8
9pub(crate) fn require_operator(anchors: &TrustAnchors, pk: &[u8; 32]) -> Result<(), LicenceError> {
11 match anchors.signer(pk) {
12 Some(k) if k.origin == KeyOrigin::Operator => Ok(()),
13 _ => Err(LicenceError::UntrustedKey),
14 }
15}
16
17pub fn verify_binding_member(
23 signed: &SignedBinding,
24 anchors: &TrustAnchors,
25 local: &MeshId,
26) -> Result<BindingRecord, LicenceError> {
27 let rec = verify_binding_signature(signed, anchors)?;
28 if rec.mesh_id != local.to_hex() {
29 return Err(LicenceError::WrongMesh);
30 }
31 Ok(rec)
32}
33
34pub(crate) fn verify_binding_signature(
36 signed: &SignedBinding,
37 anchors: &TrustAnchors,
38) -> Result<BindingRecord, LicenceError> {
39 let rec = weft_licence_wire::verify_binding_signature(signed, &|pk| {
40 require_operator(anchors, pk).is_ok()
41 })?;
42 for hex in [&rec.grant_pubkey, &rec.steward_pubkey] {
45 let pk = hex_decode_exact::<32>(hex).unwrap_or_default();
46 let anchored = anchors.signers.iter().chain(&anchors.cognitum).any(|k| k.public_key == pk);
47 if anchored {
48 return Err(LicenceError::Malformed("binding key is a trust anchor".into()));
49 }
50 }
51 Ok(rec)
52}
53
54pub trait BindingExtraCheck {
58 fn check(&self, record: &BindingRecord) -> Result<(), LicenceError>;
60}
61
62#[derive(Debug, Default, Clone, Copy)]
64pub struct NoExtraChecks;
65
66impl BindingExtraCheck for NoExtraChecks {
67 fn check(&self, _: &BindingRecord) -> Result<(), LicenceError> {
68 Ok(())
69 }
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
74pub struct AdmissionPosture {
75 pub enforce: bool,
77 pub verdict_source_bound: bool,
79 pub open_membership: bool,
81}
82
83impl AdmissionPosture {
84 pub fn check(&self) -> Result<(), LicenceError> {
87 if self.open_membership {
88 Err(LicenceError::BindingRefused("open_membership"))
89 } else if !self.enforce {
90 Err(LicenceError::BindingRefused("admission_not_enforce"))
91 } else if !self.verdict_source_bound {
92 Err(LicenceError::BindingRefused("no_verdict_source"))
93 } else {
94 Ok(())
95 }
96 }
97}