Skip to main content

clawft_kernel/
mesh_delivery.rs

1//! How the mesh hands inbound messages to the local side (P3-K0, K1).
2//!
3//! The in-kernel mesh delivers into the [`A2ARouter`]. A machine mesh
4//! service has no kernel router; it implements [`LocalDelivery`] to route
5//! to tenant registrations instead. [`MeshRuntime`](crate::mesh_runtime::MeshRuntime)
6//! only sees this trait.
7//!
8//! # Trust
9//!
10//! Everything a peer puts in an envelope is untrusted input. In
11//! particular `dest_scope` is only a *request* for an address and
12//! `src_scope` only a claim; neither is evidence of tenancy. What the
13//! implementor may rely on is [`PeerCtx`]: it is built by the kernel from
14//! the connection (admission result, Noise static key), never from
15//! envelope fields.
16
17use async_trait::async_trait;
18
19use crate::a2a::A2ARouter;
20use crate::error::KernelResult;
21use crate::ipc::KernelMessage;
22use crate::mesh_admit::PeerClass;
23use crate::mesh_ipc::Scope;
24
25/// Who delivered a message, as established by the connection.
26#[derive(Debug, Clone)]
27pub struct PeerCtx {
28    /// The peer's node id. When [`node_verified`](Self::node_verified)
29    /// this is the id admission verified; otherwise it is merely what the
30    /// peer claimed in `source_node`.
31    pub peer_id: String,
32    /// True when admission verified `peer_id` (signed hello bound to the
33    /// Noise session). False for legacy/plaintext peers and in `off` mode.
34    pub node_verified: bool,
35    /// Class admission assigned.
36    pub class: PeerClass,
37    /// The peer's Noise static public key, when the channel had one.
38    pub remote_static: Option<Vec<u8>>,
39    /// The envelope's `src_scope` claim. Already stripped by the listener
40    /// unless the peer is verified; still unproven until the receiver
41    /// checks a certificate chain.
42    pub src_scope: Option<Scope>,
43}
44
45impl PeerCtx {
46    /// The admission grant this connection holds, rebuilt from what the
47    /// connection recorded (`node_verified` is `Grant::admitted`: the hello
48    /// verified, the gate enforced and admitted; `class` is the class
49    /// admission assigned). `trust_scope` follows the rule every gate applies,
50    /// admitted `Node` peers only. A connection that is not admitted holds
51    /// no grant.
52    pub fn grant(&self) -> Option<crate::mesh_admit::Grant> {
53        self.node_verified.then(|| crate::mesh_admit::Grant {
54            limits: if self.class == PeerClass::Leaf {
55                crate::mesh_admit::PeerLimits::Leaf
56            } else {
57                crate::mesh_admit::PeerLimits::None
58            },
59            class: self.class,
60            admitted: true,
61            trust_scope: self.class == PeerClass::Node,
62            observed: None,
63        })
64    }
65
66    /// A peer with no authenticated identity (embedded use, tests, `off`
67    /// mode): `peer_id` is only the claimed source node.
68    pub fn unauthenticated(peer_id: impl Into<String>) -> Self {
69        Self {
70            peer_id: peer_id.into(),
71            node_verified: false,
72            class: PeerClass::Legacy,
73            remote_static: None,
74            src_scope: None,
75        }
76    }
77}
78
79/// Sink for messages that arrived from a mesh peer and are bound for a
80/// local recipient.
81#[async_trait]
82pub trait LocalDelivery: Send + Sync + 'static {
83    /// Deliver `msg` from `from`. `dest_scope` is the envelope's
84    /// `dest_scope` as supplied by the peer: **untrusted**. Implementations
85    /// that have no tenants ignore it.
86    async fn deliver(
87        &self,
88        from: &PeerCtx,
89        dest_scope: Option<&Scope>,
90        msg: KernelMessage,
91    ) -> KernelResult<()>;
92
93    /// May `from` subscribe to `topic` (a `mesh.subscribe` control
94    /// message, which is consumed before delivery)? Default: yes.
95    async fn authorize_subscribe(
96        &self,
97        _from: &PeerCtx,
98        _topic: &str,
99        _dest_scope: Option<&Scope>,
100    ) -> bool {
101        true
102    }
103}
104
105/// The collapsed (in-kernel) mode: scopes do not exist, the router decides.
106#[async_trait]
107impl LocalDelivery for A2ARouter {
108    async fn deliver(
109        &self,
110        _from: &PeerCtx,
111        _scope: Option<&Scope>,
112        msg: KernelMessage,
113    ) -> KernelResult<()> {
114        self.send(msg).await
115    }
116}