Skip to main content

Kernel

Struct Kernel 

Source
pub struct Kernel {
Show 18 fields pub session_id: SessionId, pub event_bus: Arc<EventBus>, pub capsules: Arc<RwLock<CapsuleRegistry>>, pub mcp: SecureMcpClient, pub capabilities: Arc<CapabilityStore>, pub vfs: Arc<dyn Vfs>, pub overlay_registry: Arc<OverlayVfsRegistry>, pub vfs_root_handle: DirHandle, pub workspace_root: PathBuf, pub home_root: Option<PathBuf>, pub cli_socket_listener: Option<Arc<Mutex<UnixListener>>>, pub kv: Arc<SurrealKvStore>, pub audit_log: Arc<AuditLog>, pub ephemeral: AtomicBool, pub boot_time: Instant, pub shutdown_tx: Sender<bool>, pub session_token: Arc<SessionToken>, pub allowance_store: Arc<AllowanceStore>, /* private fields */
}
Expand description

The core Operating System Kernel.

Fields§

§session_id: SessionId

The unique identifier for this kernel session.

§event_bus: Arc<EventBus>

The global IPC message bus.

§capsules: Arc<RwLock<CapsuleRegistry>>

The process manager (loaded WASM capsules).

§mcp: SecureMcpClient

The secure MCP client with capability-based authorization and audit logging.

§capabilities: Arc<CapabilityStore>

The capability store for this session.

§vfs: Arc<dyn Vfs>

The global Virtual File System mount.

Points at the unmodified workspace (no overlay). Principal-scoped overlays live in overlay_registry — this field is kept for kernel-internal paths that do not know a principal (discovery, capsule load scan).

§overlay_registry: Arc<OverlayVfsRegistry>

Per-principal overlay registry (Layer 4, issue #668).

Each invoking principal resolves their own OverlayVfs from this registry on first use — lower layer is the shared workspace, upper layer is a principal-private tempdir. Agent A’s uncommitted writes are never visible to Agent B.

§vfs_root_handle: DirHandle

The global physical root handle (cap-std) for the VFS.

§workspace_root: PathBuf

The physical path the VFS is mounted to.

§home_root: Option<PathBuf>

The principal home resources directory (~/.astrid/home/{principal}/). Capsules declaring fs_read = ["home://"] can read files under this root. Scoped to the principal’s home so that keys, databases, and system config in ~/.astrid/ are NOT accessible.

Always Some in production (boot requires AstridHome). Remains Option for compatibility with CapsuleContext and test fixtures.

§cli_socket_listener: Option<Arc<Mutex<UnixListener>>>

The natively bound Unix Socket for the CLI proxy.

§kv: Arc<SurrealKvStore>

Shared KV store backing all capsule-scoped stores and kernel state.

§audit_log: Arc<AuditLog>

Chain-linked cryptographic audit log with persistent storage.

§ephemeral: AtomicBool

Ephemeral mode: shut down immediately when the last client disconnects.

§boot_time: Instant

Instant when the kernel was booted (for uptime calculation).

§shutdown_tx: Sender<bool>

Sender for the API-initiated shutdown signal. The daemon’s main loop selects on the receiver to exit gracefully without process::exit.

§session_token: Arc<SessionToken>

Session token for socket authentication. Generated at boot, written to ~/.astrid/run/system.token. CLI sends this as its first message.

§allowance_store: Arc<AllowanceStore>

Shared allowance store for capsule-level approval decisions.

Capsules can check existing allowances and create new ones when users approve actions with session/always scope.

Implementations§

Source§

impl Kernel

Source

pub async fn new( session_id: SessionId, workspace_root: PathBuf, ) -> Result<Arc<Self>, Error>

Boot a new Kernel instance mounted at the specified directory.

§Panics

Panics if called on a single-threaded tokio runtime. The capsule system uses block_in_place which requires a multi-threaded runtime.

§Errors

Returns an error if the VFS mount paths cannot be registered.

Source

pub async fn load_all_capsules(&self)

Auto-discover and load all capsules from the standard directories (~/.astrid/capsules and .astrid/capsules).

Capsules are loaded in dependency order (topological sort) with uplink/daemon capsules loaded first. Each uplink must signal readiness before non-uplink capsules are loaded.

After all capsules are loaded, tool schemas are injected into every capsule’s KV namespace and the astrid.v1.capsules_loaded event is published.

Source

pub fn connection_opened(&self, principal: &PrincipalId)

Record that a new client connection for principal has been established.

Source

pub fn connection_closed(&self, principal: &PrincipalId)

Record that a client connection for principal has been closed.

Uses fetch_update for atomic saturating decrement - avoids the TOCTOU window where fetch_sub wraps to usize::MAX before a corrective store.

When this principal’s counter reaches zero, clears only that principal’s session-scoped allowances — other principals’ state is untouched. The global ephemeral-shutdown path remains gated on the sum across every principal (see total_connection_count).

Source

pub fn set_ephemeral(&self, val: bool)

Enable or disable ephemeral mode (immediate shutdown on last disconnect).

Source

pub fn total_connection_count(&self) -> usize

Total number of active client connections across all principals.

Used by the ephemeral-shutdown gate: the kernel shuts down only when every principal’s counter has reached zero.

Source

pub fn connections_by_principal(&self) -> Vec<(PrincipalId, usize)>

Snapshot of (principal, count) for every principal with a non-zero active connection. The astrid who admin surface reads this to attribute connections to specific agents instead of fabricating a default-only row from the bare total.

Not a hot-path call site — taken at status-RPC time. Iterating the DashMap snapshots the shard guards individually, so the total may not be perfectly consistent with a concurrent connect/disconnect, but each entry is internally consistent and the operator-facing accuracy bound (a flickering one-off count) is acceptable.

Source

pub async fn shutdown(&self, reason: Option<String>)

Gracefully shut down the kernel.

  1. Publish KernelShutdown event on the bus.
  2. Drain and unload all capsules (stops MCP child processes, WASM engines).
  3. Flush and close the persistent KV store.
  4. Remove the Unix socket file.

Auto Trait Implementations§

§

impl !Freeze for Kernel

§

impl !RefUnwindSafe for Kernel

§

impl Send for Kernel

§

impl Sync for Kernel

§

impl Unpin for Kernel

§

impl UnsafeUnpin for Kernel

§

impl !UnwindSafe for Kernel

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Pointee for T

Source§

type Pointer = u32

Source§

fn debug( pointer: <T as Pointee>::Pointer, f: &mut Formatter<'_>, ) -> Result<(), Error>

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more