1mod approval;
25mod approval_store;
26mod binding;
27mod chain_sink;
28mod client;
29mod exchange;
30mod exchange_sync;
31mod exchange_retry;
32mod exchange_types;
33mod floor;
34mod floor_preview;
35mod gate;
36#[cfg(all(feature = "workload-runtime", unix))]
37mod http_transport;
38mod links;
39mod mesh_config;
40mod persist;
41mod policy;
42mod relay;
43mod renewal;
44mod request;
45mod run_gate;
46mod store;
47mod steward;
48mod steward_client;
49mod store_accept;
50mod store_load;
51mod store_status;
52mod store_sync;
53mod service_links;
54
55#[cfg(test)]
56mod tests_common;
57#[cfg(test)]
58mod tests_exchange;
59#[cfg(test)]
60mod tests_fixes;
61#[cfg(test)]
62mod tests_sync;
63#[cfg(test)]
64mod tests_service_links;
65#[cfg(test)]
66mod tests_policy;
67#[cfg(test)]
68mod tests_relay;
69#[cfg(test)]
70mod tests_relay_local;
71#[cfg(test)]
72mod tests_request;
73#[cfg(test)]
74mod tests_stub;
75#[cfg(test)]
76mod tests_review;
77#[cfg(test)]
78mod tests_seed_service;
79#[cfg(test)]
80mod tests_store;
81#[cfg(test)]
82mod tests_types;
83#[cfg(test)]
84mod tests_run_gate;
85#[cfg(all(test, feature = "workload-runtime", unix))]
86mod tests_http;
87#[cfg(all(test, feature = "workload-runtime", unix))]
88mod tests_http_e2e;
89#[cfg(all(test, feature = "workload-runtime", unix))]
90mod tests_renewal;
91#[cfg(test)]
92mod tests_renewal_cursor;
93
94use std::sync::{Arc, Mutex, RwLock};
95
96#[allow(unused_imports)]
97use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey};
98#[allow(unused_imports)]
99use serde::{Deserialize, Serialize};
100
101#[allow(unused_imports)]
102use crate::workload_pkg::codec::{hex_decode_exact, hex_encode};
103
104pub use approval::{Approval, SignedApproval, sign_approval, verify_approval, verify_approval_signature};
105pub use approval_store::{APPROVALS_FILE, ApprovalStore};
106pub use binding::{
107 AdmissionPosture, BindState, BindingExtraCheck, BindingRecord, NoExtraChecks, SignedBinding,
108 sign_binding, verify_binding_member,
109};
110pub use chain_sink::{ChainLicenceSink, LICENCE_EVENT_PREFIX};
111pub use client::{
112 ARTIFACT_PATH, CHECKOUT_PATH, CheckoutWire, ClockMs, system_clock_ms, GRANTS_PATH, GrantsPage, RENEW_PATH, LicenceClient, LicenceClientError,
113 LicenceResponse, LicenceTransport, SignedLicenceClient,
114};
115pub use exchange::{
116 CtxAdmission, ExchangeError, LicenceExchange, LicenceExchangeConfig, LicenceExchangeParts,
117 PeerAdmission, PostureFn, Receipt, Spend, sign_unbind,
118};
119pub use exchange_retry::MAX_SYNC_RETRIES;
120pub use exchange_sync::{GrantCursor, SYNC_MAX_BYTES, SYNC_MAX_ENTRIES, SyncMsg};
121pub use floor::FloorState;
122pub use floor_preview::{FloorPreview, RevivedGrant};
123pub use gate::{RunDenied, RunPermit, RunRequest, may_run};
124#[cfg(all(feature = "workload-runtime", unix))]
125pub use http_transport::{
126 DEFAULT_MAX_ARTIFACT_BYTES, HttpLicenceTransport, LicenceLinkConfig, TransportLimits,
127};
128pub use renewal::{
129 EVENT_KIND_CHECKOUT_LAPSED, EVENT_KIND_CHECKOUT_RENEWED, RenewalConfig, RenewalReport, Renewer,
130};
131pub use run_gate::{CognitumRunGate, RunRefusal, RunVerdict, StoreRunGate, check_run};
132pub use steward_client::{SharedTransport, StewardLicenceClient};
133pub use store_status::{ApprovalRow, BOUND_MARKER, GrantRow};
134pub use links::LicenceLinks;
135pub use service_links::{
136 LICENCE_TOPICS, MAX_REPLY_SENDS, MAX_REPLY_SENDS_PER_PEER, PEER_REFRESH, PeerDirectory, PeerSnapshot, ServiceLicenceLinks, ServiceLinksCounters,
137 is_licence_topic,
138};
139pub use weft_licence_wire::{
140 APPROVAL_DOMAIN, BINDING_DOMAIN, CheckoutGrant, FAR_FUTURE_CLAMP_SECS, GRANT_DOMAIN,
141 GRANT_SKEW_SECS, GrantArtifact, LicenceError, LicenceRef, MAX_APPROVALS, MAX_GRANT_SLOTS,
142 MAX_ARTIFACT_BYTES, MAX_FLOORS, MAX_GRANT_TTL_SECS, MAX_PAYLOAD_BYTES, MAX_STORE_BYTES, MAX_UNIX_TIME, MESH_ID_DOMAIN, MeshId,
143 SignedEnvelope, SignedGrant, key_id, sha256_hex, sign_grant, verify_grant,
144};
145#[allow(unused_imports)]
146pub(crate) use weft_licence_wire::{
147 envelope_key, parse_canonical, sign_envelope, signed_bytes, valid_hex32, valid_token,
148 verify_envelope, verify_grant_signature,
149};
150pub use mesh_config::{MeshIdConfigError, mesh_id_from_config};
151pub use policy::MeshCheckoutPolicy;
152pub use relay::{
153 CheckoutCaller, CheckoutRefusal, CheckoutRelay, RelayLimits, EVENT_KIND_CHECKOUT_GRANTED,
154 EVENT_KIND_CHECKOUT_REFUSED, GATE_ACTION, GrantFlood, NoFlood, install_grant,
155};
156pub use request::{
157 CLOCK_FLOOR_SECS, LicenceRequest, REQUEST_DOMAIN, REQUEST_WINDOW_MS, ReplayGuard,
158 RequestAuth, RequestRefused, sign_request, signing_string, valid_nonce, verify_request,
159};
160pub use steward::StewardCheck;
161pub use store::{CheckoutGrantStore, GRANTS_FILE, VerifiedCheckoutGrant};
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq)]
165pub enum Outcome {
166 Applied,
168 AppliedUnsaved,
171 Duplicate,
173 Ignored,
175}
176
177#[derive(Clone, Default)]
180pub struct LocalMeshId(Arc<RwLock<Option<MeshId>>>);
181
182impl LocalMeshId {
183 pub fn new(id: MeshId) -> Self {
185 Self(Arc::new(RwLock::new(Some(id))))
186 }
187
188 pub fn unset() -> Self {
190 Self::default()
191 }
192
193 pub fn get(&self) -> Option<MeshId> {
195 *self.0.read().unwrap_or_else(|p| p.into_inner())
196 }
197
198 pub fn set(&self, id: Option<MeshId>) {
200 *self.0.write().unwrap_or_else(|p| p.into_inner()) = id;
201 }
202}
203
204pub type Clock = Arc<dyn Fn() -> u64 + Send + Sync>;
206
207pub fn system_clock() -> Clock {
209 Arc::new(|| {
210 std::time::SystemTime::now()
211 .duration_since(std::time::UNIX_EPOCH)
212 .map(|d| d.as_secs())
213 .unwrap_or(0)
214 })
215}
216
217#[derive(Debug, Clone, PartialEq, Eq)]
220pub enum LicenceEvent {
221 BindingRefused(String),
223 BindingConflict(u64),
225 BindingOrphaned {
227 stored: String,
229 local: String,
231 },
232 GrantConflict {
234 cog_id: String,
236 version: String,
238 seq: u64,
240 },
241 FloorReset(u64),
243 SyncBadSignature {
245 peer: String,
247 },
248}
249
250impl LicenceEvent {
251 pub fn name(&self) -> &'static str {
253 match self {
254 Self::BindingRefused(_) => "binding_refused",
255 Self::BindingConflict(_) => "binding_conflict",
256 Self::BindingOrphaned { .. } => "binding_orphaned",
257 Self::GrantConflict { .. } => "grant_conflict",
258 Self::FloorReset(_) => "floor_reset",
259 Self::SyncBadSignature { .. } => "sync_bad_signature",
260 }
261 }
262}
263
264pub trait LicenceEventSink: Send + Sync {
267 fn emit(&self, event: LicenceEvent);
269}
270
271#[derive(Debug, Default)]
273pub struct NoopSink;
274
275impl LicenceEventSink for NoopSink {
276 fn emit(&self, _: LicenceEvent) {}
277}
278
279#[derive(Debug, Default)]
281pub struct RecordingSink(Mutex<Vec<LicenceEvent>>);
282
283impl RecordingSink {
284 pub fn events(&self) -> Vec<LicenceEvent> {
286 self.0.lock().unwrap_or_else(|p| p.into_inner()).clone()
287 }
288}
289
290impl LicenceEventSink for RecordingSink {
291 fn emit(&self, event: LicenceEvent) {
292 self.0.lock().unwrap_or_else(|p| p.into_inner()).push(event);
293 }
294}
295