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}