Skip to main content

loong_kernel/
kernel.rs

1use std::{
2    collections::{BTreeMap, BTreeSet},
3    ops::Deref,
4    sync::{
5        Arc,
6        atomic::{AtomicU64, Ordering},
7    },
8};
9
10use crate::{
11    audit::{
12        AuditEvent, AuditEventKind, AuditSink, ExecutionPlane, InMemoryAuditSink, NoopAuditSink,
13        PlaneTier,
14    },
15    clock::{Clock, SystemClock},
16    connector::{ConnectorExtensionAdapter, ConnectorPlane, CoreConnectorAdapter},
17    contracts::{
18        Capability, CapabilityToken, ConnectorCommand, ConnectorOutcome, HarnessRequest, TaskIntent,
19    },
20    errors::KernelError,
21    harness::{HarnessAdapter, HarnessBroker},
22    memory::{
23        CoreMemoryAdapter, MemoryCoreOutcome, MemoryCoreRequest, MemoryExtensionAdapter,
24        MemoryExtensionOutcome, MemoryExtensionRequest, MemoryPlane,
25    },
26    pack::VerticalPackManifest,
27    policy::PolicyEngine,
28    policy_ext::{PolicyExtension, PolicyExtensionChain, PolicyExtensionContext},
29    runtime::{
30        CoreRuntimeAdapter, RuntimeCoreOutcome, RuntimeCoreRequest, RuntimeExtensionAdapter,
31        RuntimeExtensionOutcome, RuntimeExtensionRequest, RuntimePlane,
32    },
33    tool::{
34        CoreToolAdapter, ToolCoreOutcome, ToolCoreRequest, ToolExtensionAdapter,
35        ToolExtensionOutcome, ToolExtensionRequest, ToolPlane,
36    },
37};
38
39#[derive(Debug, Clone, PartialEq)]
40pub struct KernelDispatch {
41    pub adapter_route: crate::contracts::ExecutionRoute,
42    pub outcome: crate::contracts::HarnessOutcome,
43}
44
45#[derive(Debug, Clone, PartialEq)]
46pub struct ConnectorDispatch {
47    pub connector_name: String,
48    pub outcome: ConnectorOutcome,
49}
50
51struct PlaneInvocationRecord<'a> {
52    timestamp_epoch_s: u64,
53    agent_id: &'a str,
54    pack_id: &'a str,
55    plane: ExecutionPlane,
56    tier: PlaneTier,
57    primary_adapter: String,
58    delegated_core_adapter: Option<String>,
59    operation: String,
60    required_capabilities: &'a BTreeSet<Capability>,
61}
62
63pub struct LoongKernel<P: PolicyEngine> {
64    policy: P,
65    packs: BTreeMap<String, VerticalPackManifest>,
66    namespaces: BTreeMap<String, loong_contracts::Namespace>,
67    harness: HarnessBroker,
68    connector_plane: ConnectorPlane,
69    runtime_plane: RuntimePlane,
70    tool_plane: ToolPlane,
71    memory_plane: MemoryPlane,
72    policy_extensions: PolicyExtensionChain,
73    clock: Arc<dyn Clock>,
74    audit: Arc<dyn AuditSink>,
75    event_seq: AtomicU64,
76}
77
78/// Additive migration alias for the legacy kernel surface.
79///
80/// During the compatibility window this still exposes the executable
81/// `LoongKernel` API, while also supporting `.build()` into the new
82/// frozen `Kernel<P>` handle.
83pub type KernelBuilder<P> = LoongKernel<P>;
84
85pub struct Kernel<P: PolicyEngine> {
86    inner: LoongKernel<P>,
87}
88
89impl<P: PolicyEngine> LoongKernel<P> {
90    /// Safe convenience constructor for callers that do not need to customize
91    /// runtime components. This defaults to in-memory audit rather than silent
92    /// audit dropping.
93    #[must_use]
94    pub fn new(policy: P) -> Self {
95        Self::new_with_in_memory_audit(policy).0
96    }
97
98    /// Construct a kernel with the default system clock and an inspectable
99    /// in-memory audit sink.
100    #[must_use]
101    pub fn new_with_in_memory_audit(policy: P) -> (Self, Arc<InMemoryAuditSink>) {
102        let audit = Arc::new(InMemoryAuditSink::default());
103        let kernel = Self::with_runtime(policy, Arc::new(SystemClock), audit.clone());
104        (kernel, audit)
105    }
106
107    /// Construct a kernel that intentionally discards audit events.
108    ///
109    /// This is reserved for narrow fixture paths where callers explicitly do
110    /// not need audit assertions or evidence retention.
111    #[must_use]
112    pub fn new_without_audit(policy: P) -> Self {
113        Self::with_runtime(policy, Arc::new(SystemClock), Arc::new(NoopAuditSink))
114    }
115
116    #[must_use]
117    pub fn with_runtime(policy: P, clock: Arc<dyn Clock>, audit: Arc<dyn AuditSink>) -> Self {
118        Self {
119            policy,
120            packs: BTreeMap::new(),
121            namespaces: BTreeMap::new(),
122            harness: HarnessBroker::new(),
123            connector_plane: ConnectorPlane::new(),
124            runtime_plane: RuntimePlane::new(),
125            tool_plane: ToolPlane::new(),
126            memory_plane: MemoryPlane::new(),
127            policy_extensions: PolicyExtensionChain::new(),
128            clock,
129            audit,
130            event_seq: AtomicU64::new(0),
131        }
132    }
133
134    pub fn register_pack(&mut self, pack: VerticalPackManifest) -> Result<(), KernelError> {
135        pack.validate()?;
136        if self.packs.contains_key(&pack.pack_id) {
137            return Err(KernelError::DuplicatePack(pack.pack_id));
138        }
139        let namespace = loong_contracts::Namespace {
140            pack_id: pack.pack_id.clone(),
141            domain: pack.domain.clone(),
142            membrane: pack.pack_id.clone(),
143            default_route: pack.default_route.clone(),
144            granted_capabilities: pack.granted_capabilities.clone(),
145        };
146        self.namespaces.insert(pack.pack_id.clone(), namespace);
147        self.packs.insert(pack.pack_id.clone(), pack);
148        Ok(())
149    }
150
151    pub fn get_namespace(&self, pack_id: &str) -> Option<&loong_contracts::Namespace> {
152        self.namespaces.get(pack_id)
153    }
154
155    pub fn register_policy_extension<E: PolicyExtension + 'static>(&mut self, extension: E) {
156        self.policy_extensions.register(extension);
157    }
158
159    pub fn register_harness_adapter<A: HarnessAdapter + 'static>(&mut self, adapter: A) {
160        self.harness.register(adapter);
161    }
162
163    pub fn register_core_connector_adapter<A: CoreConnectorAdapter + 'static>(
164        &mut self,
165        adapter: A,
166    ) {
167        self.connector_plane.register_core_adapter(adapter);
168    }
169
170    pub fn register_connector_extension_adapter<A: ConnectorExtensionAdapter + 'static>(
171        &mut self,
172        adapter: A,
173    ) {
174        self.connector_plane.register_extension_adapter(adapter);
175    }
176
177    pub fn set_default_core_connector_adapter(&mut self, name: &str) -> Result<(), KernelError> {
178        self.connector_plane
179            .set_default_core_adapter(name)
180            .map_err(KernelError::from)
181    }
182
183    pub fn register_core_runtime_adapter<A: CoreRuntimeAdapter + 'static>(&mut self, adapter: A) {
184        self.runtime_plane.register_core_adapter(adapter);
185    }
186
187    pub fn register_runtime_extension_adapter<A: RuntimeExtensionAdapter + 'static>(
188        &mut self,
189        adapter: A,
190    ) {
191        self.runtime_plane.register_extension_adapter(adapter);
192    }
193
194    pub fn set_default_core_runtime_adapter(&mut self, name: &str) -> Result<(), KernelError> {
195        self.runtime_plane
196            .set_default_core_adapter(name)
197            .map_err(KernelError::from)
198    }
199
200    pub fn register_core_tool_adapter<A: CoreToolAdapter + 'static>(&mut self, adapter: A) {
201        self.tool_plane.register_core_adapter(adapter);
202    }
203
204    pub fn register_tool_extension_adapter<A: ToolExtensionAdapter + 'static>(
205        &mut self,
206        adapter: A,
207    ) {
208        self.tool_plane.register_extension_adapter(adapter);
209    }
210
211    pub fn set_default_core_tool_adapter(&mut self, name: &str) -> Result<(), KernelError> {
212        self.tool_plane
213            .set_default_core_adapter(name)
214            .map_err(KernelError::from)
215    }
216
217    pub fn register_core_memory_adapter<A: CoreMemoryAdapter + 'static>(&mut self, adapter: A) {
218        self.memory_plane.register_core_adapter(adapter);
219    }
220
221    pub fn register_memory_extension_adapter<A: MemoryExtensionAdapter + 'static>(
222        &mut self,
223        adapter: A,
224    ) {
225        self.memory_plane.register_extension_adapter(adapter);
226    }
227
228    pub fn set_default_core_memory_adapter(&mut self, name: &str) -> Result<(), KernelError> {
229        self.memory_plane
230            .set_default_core_adapter(name)
231            .map_err(KernelError::from)
232    }
233
234    #[must_use]
235    pub fn build(self) -> Kernel<P> {
236        Kernel { inner: self }
237    }
238
239    pub fn issue_token(
240        &self,
241        pack_id: &str,
242        agent_id: &str,
243        ttl_s: u64,
244    ) -> Result<CapabilityToken, KernelError> {
245        let pack = self
246            .packs
247            .get(pack_id)
248            .ok_or_else(|| KernelError::PackNotFound(pack_id.to_owned()))?;
249
250        let now = self.clock.now_epoch_s();
251        let token = self.policy.issue_token(pack, agent_id, now, ttl_s)?;
252
253        self.audit.record(self.new_event(
254            now,
255            Some(agent_id.to_owned()),
256            AuditEventKind::TokenIssued {
257                token: token.clone(),
258            },
259        ))?;
260
261        Ok(token)
262    }
263
264    pub fn issue_scoped_token(
265        &self,
266        pack_id: &str,
267        agent_id: &str,
268        allowed_capabilities: &BTreeSet<Capability>,
269        ttl_s: u64,
270    ) -> Result<CapabilityToken, KernelError> {
271        let pack = self
272            .packs
273            .get(pack_id)
274            .ok_or_else(|| KernelError::PackNotFound(pack_id.to_owned()))?;
275        self.assert_pack_grants(pack, allowed_capabilities)?;
276
277        let now = self.clock.now_epoch_s();
278        let mut scoped_pack = pack.clone();
279        scoped_pack.granted_capabilities = allowed_capabilities.clone();
280        let token = self
281            .policy
282            .issue_token(&scoped_pack, agent_id, now, ttl_s)?;
283
284        self.audit.record(self.new_event(
285            now,
286            Some(agent_id.to_owned()),
287            AuditEventKind::TokenIssued {
288                token: token.clone(),
289            },
290        ))?;
291
292        Ok(token)
293    }
294
295    pub fn revoke_token(
296        &self,
297        token_id: &str,
298        actor_agent_id: Option<&str>,
299    ) -> Result<(), KernelError> {
300        self.policy.revoke_token(token_id)?;
301        self.audit.record(self.new_event(
302            self.clock.now_epoch_s(),
303            actor_agent_id.map(std::string::ToString::to_string),
304            AuditEventKind::TokenRevoked {
305                token_id: token_id.to_owned(),
306            },
307        ))?;
308        Ok(())
309    }
310
311    pub fn revoke_generation(&self, below: u64) {
312        self.policy.revoke_generation(below);
313    }
314
315    pub fn record_audit_event(
316        &self,
317        agent_id: Option<&str>,
318        kind: AuditEventKind,
319    ) -> Result<(), KernelError> {
320        let now = self.clock.now_epoch_s();
321        self.audit.record(self.new_event(
322            now,
323            agent_id.map(std::string::ToString::to_string),
324            kind,
325        ))?;
326        Ok(())
327    }
328
329    pub fn authorize_operation(
330        &self,
331        pack_id: &str,
332        token: &CapabilityToken,
333        plane: ExecutionPlane,
334        tier: PlaneTier,
335        primary_adapter: &str,
336        delegated_core_adapter: Option<&str>,
337        operation: &str,
338        required_capabilities: &BTreeSet<Capability>,
339    ) -> Result<(), KernelError> {
340        let pack = self.get_pack(pack_id)?;
341        let now = self.authorize_pack_operation(pack, token, required_capabilities, None)?;
342
343        let primary_adapter = primary_adapter.to_owned();
344        let delegated_core_adapter = delegated_core_adapter.map(std::string::ToString::to_string);
345        let operation = operation.to_owned();
346        let record = PlaneInvocationRecord {
347            timestamp_epoch_s: now,
348            agent_id: token.agent_id.as_str(),
349            pack_id: pack.pack_id.as_str(),
350            plane,
351            tier,
352            primary_adapter,
353            delegated_core_adapter,
354            operation,
355            required_capabilities,
356        };
357        self.record_plane_invocation(record)?;
358        Ok(())
359    }
360
361    pub async fn execute_task(
362        &self,
363        pack_id: &str,
364        token: &CapabilityToken,
365        task: TaskIntent,
366    ) -> Result<KernelDispatch, KernelError> {
367        let pack = self.get_pack(pack_id)?;
368        let now = self.authorize_pack_operation(pack, token, &task.required_capabilities, None)?;
369
370        let request = HarnessRequest {
371            token_id: token.token_id.clone(),
372            pack_id: pack.pack_id.clone(),
373            agent_id: token.agent_id.clone(),
374            task_id: task.task_id.clone(),
375            objective: task.objective,
376            payload: task.payload,
377        };
378
379        let route = pack.default_route.clone();
380        let outcome = self.harness.execute(&route, request).await?;
381
382        self.audit.record(self.new_event(
383            now,
384            Some(token.agent_id.clone()),
385            AuditEventKind::TaskDispatched {
386                pack_id: pack.pack_id.clone(),
387                task_id: task.task_id,
388                route: route.clone(),
389                required_capabilities: task.required_capabilities.iter().copied().collect(),
390            },
391        ))?;
392
393        Ok(KernelDispatch {
394            adapter_route: route,
395            outcome,
396        })
397    }
398
399    pub async fn execute_connector_core(
400        &self,
401        pack_id: &str,
402        token: &CapabilityToken,
403        core_name: Option<&str>,
404        command: ConnectorCommand,
405    ) -> Result<ConnectorDispatch, KernelError> {
406        let pack = self.get_pack(pack_id)?;
407        self.assert_connector_allowed(pack, &command.connector_name)?;
408        let now =
409            self.authorize_pack_operation(pack, token, &command.required_capabilities, None)?;
410        let resolved_core_adapter = core_name
411            .map(std::string::ToString::to_string)
412            .or_else(|| {
413                self.connector_plane
414                    .default_core_adapter_name()
415                    .map(std::string::ToString::to_string)
416            })
417            .unwrap_or_else(|| "default".to_owned());
418
419        let connector_name = command.connector_name.clone();
420        let operation = command.operation.clone();
421        let required_capabilities = command.required_capabilities.clone();
422        let outcome = self.connector_plane.invoke_core(core_name, command).await?;
423
424        self.audit.record(self.new_event(
425            now,
426            Some(token.agent_id.clone()),
427            AuditEventKind::ConnectorInvoked {
428                pack_id: pack.pack_id.clone(),
429                connector_name: connector_name.clone(),
430                operation: operation.clone(),
431                required_capabilities: required_capabilities.iter().copied().collect(),
432            },
433        ))?;
434
435        self.record_plane_invocation(PlaneInvocationRecord {
436            timestamp_epoch_s: now,
437            agent_id: &token.agent_id,
438            pack_id: &pack.pack_id,
439            plane: ExecutionPlane::Connector,
440            tier: PlaneTier::Core,
441            primary_adapter: resolved_core_adapter,
442            delegated_core_adapter: None,
443            operation,
444            required_capabilities: &required_capabilities,
445        })?;
446
447        Ok(ConnectorDispatch {
448            connector_name,
449            outcome,
450        })
451    }
452
453    pub async fn execute_connector_extension(
454        &self,
455        pack_id: &str,
456        token: &CapabilityToken,
457        extension_name: &str,
458        core_name: Option<&str>,
459        command: ConnectorCommand,
460    ) -> Result<ConnectorDispatch, KernelError> {
461        let pack = self.get_pack(pack_id)?;
462        self.assert_connector_allowed(pack, &command.connector_name)?;
463        let now =
464            self.authorize_pack_operation(pack, token, &command.required_capabilities, None)?;
465        let resolved_core_adapter = core_name
466            .map(std::string::ToString::to_string)
467            .or_else(|| {
468                self.connector_plane
469                    .default_core_adapter_name()
470                    .map(std::string::ToString::to_string)
471            })
472            .unwrap_or_else(|| "default".to_owned());
473
474        let connector_name = command.connector_name.clone();
475        let operation = command.operation.clone();
476        let required_capabilities = command.required_capabilities.clone();
477        let outcome = self
478            .connector_plane
479            .invoke_extension(extension_name, core_name, command)
480            .await?;
481
482        self.audit.record(self.new_event(
483            now,
484            Some(token.agent_id.clone()),
485            AuditEventKind::ConnectorInvoked {
486                pack_id: pack.pack_id.clone(),
487                connector_name: connector_name.clone(),
488                operation: operation.clone(),
489                required_capabilities: required_capabilities.iter().copied().collect(),
490            },
491        ))?;
492
493        self.record_plane_invocation(PlaneInvocationRecord {
494            timestamp_epoch_s: now,
495            agent_id: &token.agent_id,
496            pack_id: &pack.pack_id,
497            plane: ExecutionPlane::Connector,
498            tier: PlaneTier::Extension,
499            primary_adapter: extension_name.to_owned(),
500            delegated_core_adapter: Some(resolved_core_adapter),
501            operation,
502            required_capabilities: &required_capabilities,
503        })?;
504
505        Ok(ConnectorDispatch {
506            connector_name,
507            outcome,
508        })
509    }
510
511    pub async fn execute_runtime_core(
512        &self,
513        pack_id: &str,
514        token: &CapabilityToken,
515        required_capabilities: &BTreeSet<Capability>,
516        core_name: Option<&str>,
517        request: RuntimeCoreRequest,
518    ) -> Result<RuntimeCoreOutcome, KernelError> {
519        let pack = self.get_pack(pack_id)?;
520        let now = self.authorize_pack_operation(pack, token, required_capabilities, None)?;
521        let resolved_core_adapter = core_name
522            .map(std::string::ToString::to_string)
523            .or_else(|| {
524                self.runtime_plane
525                    .default_core_adapter_name()
526                    .map(std::string::ToString::to_string)
527            })
528            .unwrap_or_else(|| "default".to_owned());
529        let action = request.action.clone();
530        let outcome = self
531            .runtime_plane
532            .execute_core(core_name, request)
533            .await
534            .map_err(KernelError::from)?;
535
536        self.record_plane_invocation(PlaneInvocationRecord {
537            timestamp_epoch_s: now,
538            agent_id: &token.agent_id,
539            pack_id: &pack.pack_id,
540            plane: ExecutionPlane::Runtime,
541            tier: PlaneTier::Core,
542            primary_adapter: resolved_core_adapter,
543            delegated_core_adapter: None,
544            operation: action,
545            required_capabilities,
546        })?;
547
548        Ok(outcome)
549    }
550
551    pub async fn execute_runtime_extension(
552        &self,
553        pack_id: &str,
554        token: &CapabilityToken,
555        required_capabilities: &BTreeSet<Capability>,
556        extension_name: &str,
557        core_name: Option<&str>,
558        request: RuntimeExtensionRequest,
559    ) -> Result<RuntimeExtensionOutcome, KernelError> {
560        let pack = self.get_pack(pack_id)?;
561        let now = self.authorize_pack_operation(pack, token, required_capabilities, None)?;
562        let resolved_core_adapter = core_name
563            .map(std::string::ToString::to_string)
564            .or_else(|| {
565                self.runtime_plane
566                    .default_core_adapter_name()
567                    .map(std::string::ToString::to_string)
568            })
569            .unwrap_or_else(|| "default".to_owned());
570        let action = request.action.clone();
571        let outcome = self
572            .runtime_plane
573            .execute_extension(extension_name, core_name, request)
574            .await
575            .map_err(KernelError::from)?;
576
577        self.record_plane_invocation(PlaneInvocationRecord {
578            timestamp_epoch_s: now,
579            agent_id: &token.agent_id,
580            pack_id: &pack.pack_id,
581            plane: ExecutionPlane::Runtime,
582            tier: PlaneTier::Extension,
583            primary_adapter: extension_name.to_owned(),
584            delegated_core_adapter: Some(resolved_core_adapter),
585            operation: action,
586            required_capabilities,
587        })?;
588
589        Ok(outcome)
590    }
591
592    pub async fn execute_tool_core(
593        &self,
594        pack_id: &str,
595        token: &CapabilityToken,
596        required_capabilities: &BTreeSet<Capability>,
597        core_name: Option<&str>,
598        request: ToolCoreRequest,
599    ) -> Result<ToolCoreOutcome, KernelError> {
600        let pack = self.get_pack(pack_id)?;
601        let tool_policy_params = serde_json::json!({
602            "tool_name": &request.tool_name,
603            "payload": &request.payload,
604        });
605        let now = self.authorize_pack_operation(
606            pack,
607            token,
608            required_capabilities,
609            Some(&tool_policy_params),
610        )?;
611        let resolved_core_adapter = core_name
612            .map(std::string::ToString::to_string)
613            .or_else(|| {
614                self.tool_plane
615                    .default_core_adapter_name()
616                    .map(std::string::ToString::to_string)
617            })
618            .unwrap_or_else(|| "default".to_owned());
619        let tool_name = request.tool_name.clone();
620        let outcome = self
621            .tool_plane
622            .execute_core(core_name, request)
623            .await
624            .map_err(KernelError::from)?;
625
626        self.record_plane_invocation(PlaneInvocationRecord {
627            timestamp_epoch_s: now,
628            agent_id: &token.agent_id,
629            pack_id: &pack.pack_id,
630            plane: ExecutionPlane::Tool,
631            tier: PlaneTier::Core,
632            primary_adapter: resolved_core_adapter,
633            delegated_core_adapter: None,
634            operation: tool_name,
635            required_capabilities,
636        })?;
637
638        Ok(outcome)
639    }
640
641    pub async fn execute_tool_extension(
642        &self,
643        pack_id: &str,
644        token: &CapabilityToken,
645        required_capabilities: &BTreeSet<Capability>,
646        extension_name: &str,
647        core_name: Option<&str>,
648        request: ToolExtensionRequest,
649    ) -> Result<ToolExtensionOutcome, KernelError> {
650        let pack = self.get_pack(pack_id)?;
651        let tool_policy_params = serde_json::json!({
652            "tool_name": &request.extension_action,
653            "payload": &request.payload,
654        });
655        let now = self.authorize_pack_operation(
656            pack,
657            token,
658            required_capabilities,
659            Some(&tool_policy_params),
660        )?;
661        let resolved_core_adapter = core_name
662            .map(std::string::ToString::to_string)
663            .or_else(|| {
664                self.tool_plane
665                    .default_core_adapter_name()
666                    .map(std::string::ToString::to_string)
667            })
668            .unwrap_or_else(|| "default".to_owned());
669        let action = request.extension_action.clone();
670        let outcome = self
671            .tool_plane
672            .execute_extension(extension_name, core_name, request)
673            .await
674            .map_err(KernelError::from)?;
675
676        self.record_plane_invocation(PlaneInvocationRecord {
677            timestamp_epoch_s: now,
678            agent_id: &token.agent_id,
679            pack_id: &pack.pack_id,
680            plane: ExecutionPlane::Tool,
681            tier: PlaneTier::Extension,
682            primary_adapter: extension_name.to_owned(),
683            delegated_core_adapter: Some(resolved_core_adapter),
684            operation: action,
685            required_capabilities,
686        })?;
687
688        Ok(outcome)
689    }
690
691    pub async fn execute_memory_core(
692        &self,
693        pack_id: &str,
694        token: &CapabilityToken,
695        required_capabilities: &BTreeSet<Capability>,
696        core_name: Option<&str>,
697        request: MemoryCoreRequest,
698    ) -> Result<MemoryCoreOutcome, KernelError> {
699        let pack = self.get_pack(pack_id)?;
700        let now = self.authorize_pack_operation(pack, token, required_capabilities, None)?;
701        let resolved_core_adapter = core_name
702            .map(std::string::ToString::to_string)
703            .or_else(|| {
704                self.memory_plane
705                    .default_core_adapter_name()
706                    .map(std::string::ToString::to_string)
707            })
708            .unwrap_or_else(|| "default".to_owned());
709        let operation = request.operation.clone();
710        let outcome = self
711            .memory_plane
712            .execute_core(core_name, request)
713            .await
714            .map_err(KernelError::from)?;
715
716        self.record_plane_invocation(PlaneInvocationRecord {
717            timestamp_epoch_s: now,
718            agent_id: &token.agent_id,
719            pack_id: &pack.pack_id,
720            plane: ExecutionPlane::Memory,
721            tier: PlaneTier::Core,
722            primary_adapter: resolved_core_adapter,
723            delegated_core_adapter: None,
724            operation,
725            required_capabilities,
726        })?;
727
728        Ok(outcome)
729    }
730
731    pub async fn execute_memory_extension(
732        &self,
733        pack_id: &str,
734        token: &CapabilityToken,
735        required_capabilities: &BTreeSet<Capability>,
736        extension_name: &str,
737        core_name: Option<&str>,
738        request: MemoryExtensionRequest,
739    ) -> Result<MemoryExtensionOutcome, KernelError> {
740        let pack = self.get_pack(pack_id)?;
741        let now = self.authorize_pack_operation(pack, token, required_capabilities, None)?;
742        let resolved_core_adapter = core_name
743            .map(std::string::ToString::to_string)
744            .or_else(|| {
745                self.memory_plane
746                    .default_core_adapter_name()
747                    .map(std::string::ToString::to_string)
748            })
749            .unwrap_or_else(|| "default".to_owned());
750        let operation = request.operation.clone();
751        let outcome = self
752            .memory_plane
753            .execute_extension(extension_name, core_name, request)
754            .await
755            .map_err(KernelError::from)?;
756
757        self.record_plane_invocation(PlaneInvocationRecord {
758            timestamp_epoch_s: now,
759            agent_id: &token.agent_id,
760            pack_id: &pack.pack_id,
761            plane: ExecutionPlane::Memory,
762            tier: PlaneTier::Extension,
763            primary_adapter: extension_name.to_owned(),
764            delegated_core_adapter: Some(resolved_core_adapter),
765            operation,
766            required_capabilities,
767        })?;
768
769        Ok(outcome)
770    }
771
772    fn get_pack(&self, pack_id: &str) -> Result<&VerticalPackManifest, KernelError> {
773        self.packs
774            .get(pack_id)
775            .ok_or_else(|| KernelError::PackNotFound(pack_id.to_owned()))
776    }
777
778    fn authorize_pack_operation(
779        &self,
780        pack: &VerticalPackManifest,
781        token: &CapabilityToken,
782        required_capabilities: &BTreeSet<Capability>,
783        request_parameters: Option<&serde_json::Value>,
784    ) -> Result<u64, KernelError> {
785        self.assert_pack_grants(pack, required_capabilities)?;
786        let now = self.clock.now_epoch_s();
787        self.authorize_or_audit_denial(
788            pack,
789            token,
790            now,
791            required_capabilities,
792            request_parameters,
793        )?;
794        Ok(now)
795    }
796
797    fn assert_connector_allowed(
798        &self,
799        pack: &VerticalPackManifest,
800        connector_name: &str,
801    ) -> Result<(), KernelError> {
802        if !pack.allows_connector(connector_name) {
803            return Err(KernelError::ConnectorNotAllowed {
804                connector: connector_name.to_owned(),
805                pack_id: pack.pack_id.clone(),
806            });
807        }
808        Ok(())
809    }
810
811    fn record_plane_invocation(
812        &self,
813        record: PlaneInvocationRecord<'_>,
814    ) -> Result<(), KernelError> {
815        self.audit.record(self.new_event(
816            record.timestamp_epoch_s,
817            Some(record.agent_id.to_owned()),
818            AuditEventKind::PlaneInvoked {
819                pack_id: record.pack_id.to_owned(),
820                plane: record.plane,
821                tier: record.tier,
822                primary_adapter: record.primary_adapter,
823                delegated_core_adapter: record.delegated_core_adapter,
824                operation: record.operation,
825                required_capabilities: record.required_capabilities.iter().copied().collect(),
826            },
827        ))?;
828        Ok(())
829    }
830
831    fn assert_pack_grants(
832        &self,
833        pack: &VerticalPackManifest,
834        required_capabilities: &BTreeSet<Capability>,
835    ) -> Result<(), KernelError> {
836        for capability in required_capabilities {
837            if !pack.grants(*capability) {
838                return Err(KernelError::PackCapabilityBoundary {
839                    pack_id: pack.pack_id.clone(),
840                    capability: *capability,
841                });
842            }
843        }
844        Ok(())
845    }
846
847    #[cfg(test)]
848    pub(crate) fn record_tool_call_denial(
849        &self,
850        pack: &VerticalPackManifest,
851        token: &CapabilityToken,
852        now_epoch_s: u64,
853        error: &crate::errors::PolicyError,
854    ) -> Result<(), KernelError> {
855        self.audit.record(self.new_event(
856            now_epoch_s,
857            Some(token.agent_id.clone()),
858            AuditEventKind::AuthorizationDenied {
859                pack_id: pack.pack_id.clone(),
860                token_id: token.token_id.clone(),
861                reason: error.to_string(),
862            },
863        ))?;
864        Ok(())
865    }
866
867    fn authorize_or_audit_denial(
868        &self,
869        pack: &VerticalPackManifest,
870        token: &CapabilityToken,
871        now_epoch_s: u64,
872        required_capabilities: &BTreeSet<Capability>,
873        request_parameters: Option<&serde_json::Value>,
874    ) -> Result<(), KernelError> {
875        if let Err(policy_error) =
876            self.policy
877                .authorize(token, &pack.pack_id, now_epoch_s, required_capabilities)
878        {
879            self.audit.record(self.new_event(
880                now_epoch_s,
881                Some(token.agent_id.clone()),
882                AuditEventKind::AuthorizationDenied {
883                    pack_id: pack.pack_id.clone(),
884                    token_id: token.token_id.clone(),
885                    reason: policy_error.to_string(),
886                },
887            ))?;
888            return Err(KernelError::Policy(policy_error));
889        }
890
891        if let Err(policy_error) = self.policy_extensions.authorize(&PolicyExtensionContext {
892            pack,
893            token,
894            now_epoch_s,
895            required_capabilities,
896            request_parameters,
897        }) {
898            self.audit.record(self.new_event(
899                now_epoch_s,
900                Some(token.agent_id.clone()),
901                AuditEventKind::AuthorizationDenied {
902                    pack_id: pack.pack_id.clone(),
903                    token_id: token.token_id.clone(),
904                    reason: policy_error.to_string(),
905                },
906            ))?;
907            return Err(KernelError::Policy(policy_error));
908        }
909
910        Ok(())
911    }
912
913    fn new_event(
914        &self,
915        timestamp_epoch_s: u64,
916        agent_id: Option<String>,
917        kind: AuditEventKind,
918    ) -> AuditEvent {
919        let seq = self.event_seq.fetch_add(1, Ordering::Relaxed) + 1;
920        AuditEvent {
921            event_id: format!("evt-{seq:016x}"),
922            timestamp_epoch_s,
923            agent_id,
924            kind,
925        }
926    }
927}
928
929impl<P: PolicyEngine> Kernel<P> {
930    pub fn get_namespace(&self, pack_id: &str) -> Option<&loong_contracts::Namespace> {
931        self.inner.get_namespace(pack_id)
932    }
933
934    pub fn issue_token(
935        &self,
936        pack_id: &str,
937        agent_id: &str,
938        ttl_s: u64,
939    ) -> Result<CapabilityToken, KernelError> {
940        self.inner.issue_token(pack_id, agent_id, ttl_s)
941    }
942
943    pub fn revoke_token(
944        &self,
945        token_id: &str,
946        actor_agent_id: Option<&str>,
947    ) -> Result<(), KernelError> {
948        self.inner.revoke_token(token_id, actor_agent_id)
949    }
950
951    pub fn revoke_generation(&self, below: u64) {
952        self.inner.revoke_generation(below);
953    }
954
955    pub fn record_audit_event(
956        &self,
957        agent_id: Option<&str>,
958        kind: AuditEventKind,
959    ) -> Result<(), KernelError> {
960        self.inner.record_audit_event(agent_id, kind)
961    }
962
963    pub async fn execute_task(
964        &self,
965        pack_id: &str,
966        token: &CapabilityToken,
967        task: TaskIntent,
968    ) -> Result<KernelDispatch, KernelError> {
969        self.inner.execute_task(pack_id, token, task).await
970    }
971
972    pub async fn execute_connector_core(
973        &self,
974        pack_id: &str,
975        token: &CapabilityToken,
976        core_name: Option<&str>,
977        command: ConnectorCommand,
978    ) -> Result<ConnectorDispatch, KernelError> {
979        self.inner
980            .execute_connector_core(pack_id, token, core_name, command)
981            .await
982    }
983
984    pub async fn execute_connector_extension(
985        &self,
986        pack_id: &str,
987        token: &CapabilityToken,
988        extension_name: &str,
989        core_name: Option<&str>,
990        command: ConnectorCommand,
991    ) -> Result<ConnectorDispatch, KernelError> {
992        self.inner
993            .execute_connector_extension(pack_id, token, extension_name, core_name, command)
994            .await
995    }
996
997    pub async fn execute_runtime_core(
998        &self,
999        pack_id: &str,
1000        token: &CapabilityToken,
1001        required_capabilities: &BTreeSet<Capability>,
1002        core_name: Option<&str>,
1003        request: RuntimeCoreRequest,
1004    ) -> Result<RuntimeCoreOutcome, KernelError> {
1005        self.inner
1006            .execute_runtime_core(pack_id, token, required_capabilities, core_name, request)
1007            .await
1008    }
1009
1010    pub async fn execute_runtime_extension(
1011        &self,
1012        pack_id: &str,
1013        token: &CapabilityToken,
1014        required_capabilities: &BTreeSet<Capability>,
1015        extension_name: &str,
1016        core_name: Option<&str>,
1017        request: RuntimeExtensionRequest,
1018    ) -> Result<RuntimeExtensionOutcome, KernelError> {
1019        self.inner
1020            .execute_runtime_extension(
1021                pack_id,
1022                token,
1023                required_capabilities,
1024                extension_name,
1025                core_name,
1026                request,
1027            )
1028            .await
1029    }
1030
1031    pub async fn execute_tool_core(
1032        &self,
1033        pack_id: &str,
1034        token: &CapabilityToken,
1035        required_capabilities: &BTreeSet<Capability>,
1036        core_name: Option<&str>,
1037        request: ToolCoreRequest,
1038    ) -> Result<ToolCoreOutcome, KernelError> {
1039        self.inner
1040            .execute_tool_core(pack_id, token, required_capabilities, core_name, request)
1041            .await
1042    }
1043
1044    pub async fn execute_tool_extension(
1045        &self,
1046        pack_id: &str,
1047        token: &CapabilityToken,
1048        required_capabilities: &BTreeSet<Capability>,
1049        extension_name: &str,
1050        core_name: Option<&str>,
1051        request: ToolExtensionRequest,
1052    ) -> Result<ToolExtensionOutcome, KernelError> {
1053        self.inner
1054            .execute_tool_extension(
1055                pack_id,
1056                token,
1057                required_capabilities,
1058                extension_name,
1059                core_name,
1060                request,
1061            )
1062            .await
1063    }
1064
1065    pub async fn execute_memory_core(
1066        &self,
1067        pack_id: &str,
1068        token: &CapabilityToken,
1069        required_capabilities: &BTreeSet<Capability>,
1070        core_name: Option<&str>,
1071        request: MemoryCoreRequest,
1072    ) -> Result<MemoryCoreOutcome, KernelError> {
1073        self.inner
1074            .execute_memory_core(pack_id, token, required_capabilities, core_name, request)
1075            .await
1076    }
1077
1078    pub async fn execute_memory_extension(
1079        &self,
1080        pack_id: &str,
1081        token: &CapabilityToken,
1082        required_capabilities: &BTreeSet<Capability>,
1083        extension_name: &str,
1084        core_name: Option<&str>,
1085        request: MemoryExtensionRequest,
1086    ) -> Result<MemoryExtensionOutcome, KernelError> {
1087        self.inner
1088            .execute_memory_extension(
1089                pack_id,
1090                token,
1091                required_capabilities,
1092                extension_name,
1093                core_name,
1094                request,
1095            )
1096            .await
1097    }
1098}
1099
1100impl<P: PolicyEngine> AsRef<LoongKernel<P>> for Kernel<P> {
1101    fn as_ref(&self) -> &LoongKernel<P> {
1102        &self.inner
1103    }
1104}
1105
1106impl<P: PolicyEngine> Deref for Kernel<P> {
1107    type Target = LoongKernel<P>;
1108
1109    fn deref(&self) -> &Self::Target {
1110        &self.inner
1111    }
1112}
1113
1114#[cfg(test)]
1115mod send_sync_tests {
1116    use super::*;
1117    use crate::StaticPolicyEngine;
1118
1119    fn assert_send<T: Send>() {}
1120    fn assert_sync<T: Sync>() {}
1121
1122    #[test]
1123    fn kernel_is_send_and_sync() {
1124        assert_send::<Kernel<StaticPolicyEngine>>();
1125        assert_sync::<Kernel<StaticPolicyEngine>>();
1126    }
1127}