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
78pub type KernelBuilder<P> = LoongKernel<P>;
84
85pub struct Kernel<P: PolicyEngine> {
86 inner: LoongKernel<P>,
87}
88
89impl<P: PolicyEngine> LoongKernel<P> {
90 #[must_use]
94 pub fn new(policy: P) -> Self {
95 Self::new_with_in_memory_audit(policy).0
96 }
97
98 #[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 #[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}