pub struct Kernel {Show 19 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<UplinkListener>,
pub kv: Arc<dyn KvStore>,
pub audit_log: Arc<AuditLog>,
pub audit_sink: Arc<KernelAuditSink>,
pub runtime_key: Arc<KeyPair>,
pub ephemeral: AtomicBool,
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: SessionIdThe 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: SecureMcpClientThe secure MCP client with capability-based authorization and audit logging. Native-only: the MCP host surface belongs to the Wasmtime engine, absent on the browser profile.
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). Native-only: astrid-vfs is built on
cap-std, which does not compile for the browser profile (that host
resolves paths by other means).
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. Native-only (astrid-vfs / cap-std).
vfs_root_handle: DirHandleThe global physical root handle for the VFS. On native hosts the
composition root registers it as the cap-std workspace root; the
browser profile keeps the handle (it is engine-agnostic) but gates
out the cap-std-backed astrid-vfs machinery behind it.
workspace_root: PathBufThe physical path the VFS is mounted to.
home_root: Option<PathBuf>Legacy native home root retained for lifecycle/compatibility contexts.
Steady-state capsule home:// authority is the UID-bound
principal_store projection, never this host path.
Always Some in production (boot requires AstridHome). Remains
Option for compatibility with CapsuleContext and test fixtures.
cli_socket_listener: Option<UplinkListener>The natively bound Unix Socket for the CLI proxy.
kv: Arc<dyn KvStore>Shared KV store backing all capsule-scoped stores and kernel state.
A trait object (Arc<dyn KvStore>) so a portable host can inject its
own backend; the shutdown flush goes through the trait’s
close.
audit_log: Arc<AuditLog>Chain-linked cryptographic audit log with persistent storage.
audit_sink: Arc<KernelAuditSink>Shared bounded host-audit writer and operator health surface.
runtime_key: Arc<KeyPair>The runtime ed25519 signing key (issue #929).
Loaded once at boot from ~/.astrid/keys/runtime.key and shared
(Arc) with AuditLog — both sign with the exact same key bytes,
never loaded twice. Reachable from the admin token-mint handlers so an
operator can pre-grant mcp:// tool access by minting a capability
token signed by this key (the same key the approval interceptor’s
validator trusts as issuer).
ephemeral: AtomicBoolEphemeral mode: shut down immediately when the last client disconnects.
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
impl Kernel
Sourcepub fn bind_native_secret_inputs(
&self,
registry: Arc<PendingSecretElicits>,
) -> Result<(), Error>
pub fn bind_native_secret_inputs( &self, registry: Arc<PendingSecretElicits>, ) -> Result<(), Error>
Bind private secret routing before loading boot capsules. This shares waiter ownership with the native responder; it does not register keys.
§Errors
A second binding is refused. Changing routing requires a daemon restart.
Sourcepub fn native_input_device_is_live(
&self,
principal: &PrincipalId,
device_key_id: &str,
) -> bool
pub fn native_input_device_is_live( &self, principal: &PrincipalId, device_key_id: &str, ) -> bool
Live profile revalidation for private secret replies.
This uses the same profile cache that pair_device_revoke invalidates.
Cached native handshake identity is not sufficient after revoke or
disable.
Source§impl Kernel
impl Kernel
Sourcepub async fn set_system_capsules(
&self,
capsules: impl IntoIterator<Item = String>,
)
pub async fn set_system_capsules( &self, capsules: impl IntoIterator<Item = String>, )
Install the operator-owned allowlist for explicit system-resident capsules. Capsule manifests cannot mutate or widen this policy.
Sourcepub fn claim_native_uplink_listener(&self) -> Option<UplinkListener>
pub fn claim_native_uplink_listener(&self) -> Option<UplinkListener>
Claim the canonical local listener for Astrid’s built-in uplink.
The first caller receives the shared listener. Once claimed, capsule contexts no longer receive it; optional distribution frontends may expose other transports but cannot replace or race the base control plane.
Sourcepub fn ownership_store(&self) -> &Arc<OwnershipStore> ⓘ
pub fn ownership_store(&self) -> &Arc<OwnershipStore> ⓘ
Astrid’s authoritative human-to-fleet ownership store.
Sourcepub fn principal_store(&self) -> Option<&RuntimePrincipalStore>
pub fn principal_store(&self) -> Option<&RuntimePrincipalStore>
Return the durable UID-scoped principal store used by trusted daemon composition paths. Capsule and gateway callers must use authenticated admin requests instead of receiving this storage handle.
Sourcepub fn principal_directory(&self) -> &PrincipalDirectory
pub fn principal_directory(&self) -> &PrincipalDirectory
Return the live alias-to-immutable-UID directory for trusted daemon composition paths. The directory is never a storage authority; it only resolves a principal alias before selecting its UID-owned store view.
Sourcepub fn workspace_layout(&self) -> &WorkspaceLayout
pub fn workspace_layout(&self) -> &WorkspaceLayout
Per-project runtime layout selected at boot.
Sourcepub fn workspace_selection(&self) -> &WorkspaceSelection
pub fn workspace_selection(&self) -> &WorkspaceSelection
Checked project state selection captured at boot.
Sourcepub async fn new(
session_id: SessionId,
workspace_root: PathBuf,
runtime_limits: CapsuleRuntimeLimits,
local_egress: HashMap<String, Vec<String>>,
http_limits: HttpLimits,
) -> Result<Arc<Self>, Error>
pub async fn new( session_id: SessionId, workspace_root: PathBuf, runtime_limits: CapsuleRuntimeLimits, local_egress: HashMap<String, Vec<String>>, http_limits: HttpLimits, ) -> Result<Arc<Self>, Error>
Boot a new Kernel instance mounted at the specified directory.
The native composition root: resolves the Astrid home, opens the durable
principal store and audit log, loads the runtime key, binds the singleton
Unix socket, generates the session token, then delegates to the portable
Kernel::with_resources. Unix-only — the socket bind and singleton
flock have no browser-profile analogue; that host builds its own
KernelResources and calls with_resources directly.
runtime_limits is the resolved per-host capsule concurrency ceiling
pair (blocking vs async-I/O host calls); the daemon resolves it from
config + CLI + host defaults and the kernel forwards it, unmodified, to
every capsule’s WasmEngine. In tests, pass
CapsuleRuntimeLimits::default().
http_limits is the resolved astrid:http host ceilings (a global
value, the same for every capsule), likewise resolved by the daemon from
the [http] config section and forwarded unmodified. In tests, pass
HttpLimits::default().
§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 any native resource cannot be acquired — the Astrid
home cannot be resolved, the KV store, runtime key, or audit log cannot
be opened, the Unix socket cannot be bound (or the singleton lock is
already held), or the session token cannot be generated — or if the
portable wiring in Kernel::with_resources fails.
Sourcepub async fn new_with_workspace_layout(
session_id: SessionId,
workspace_root: PathBuf,
runtime_limits: CapsuleRuntimeLimits,
local_egress: HashMap<String, Vec<String>>,
http_limits: HttpLimits,
workspace_layout: WorkspaceLayout,
) -> Result<Arc<Self>, Error>
pub async fn new_with_workspace_layout( session_id: SessionId, workspace_root: PathBuf, runtime_limits: CapsuleRuntimeLimits, local_egress: HashMap<String, Vec<String>>, http_limits: HttpLimits, workspace_layout: WorkspaceLayout, ) -> Result<Arc<Self>, Error>
Boot a kernel with an explicit per-project runtime layout.
§Errors
Returns an error if the Astrid home or native resources cannot be acquired, or if portable kernel wiring fails.
Sourcepub async fn with_resources(
session_id: SessionId,
workspace_root: PathBuf,
runtime_limits: CapsuleRuntimeLimits,
local_egress: HashMap<String, Vec<String>>,
http_limits: HttpLimits,
resources: KernelResources,
) -> Result<Arc<Self>, Error>
pub async fn with_resources( session_id: SessionId, workspace_root: PathBuf, runtime_limits: CapsuleRuntimeLimits, local_egress: HashMap<String, Vec<String>>, http_limits: HttpLimits, resources: KernelResources, ) -> Result<Arc<Self>, Error>
Construct a Kernel from already-acquired host resources.
This is the portable composition root: it performs the entire
kernel wiring (event bus, registries, capability store, VFS/overlay,
identity/group config, monitors, dispatcher) but performs no native
side-effects — every platform-specific facility is injected via
KernelResources. Kernel::new is the native composition root that
acquires those resources (resolving the home, opening the KV/audit
stores, loading the runtime key, binding the socket, generating the
token) and delegates here. An alternate host can build its own
KernelResources and call this directly.
runtime_limits is the resolved per-host capsule concurrency ceiling
pair (blocking vs async-I/O host calls); the daemon resolves it from
config + CLI + host defaults and the kernel forwards it, unmodified, to
every capsule’s WasmEngine. In tests, pass
CapsuleRuntimeLimits::default().
http_limits is the resolved astrid:http host ceilings (a global
value, the same for every capsule), likewise resolved by the daemon from
the [http] config section and forwarded unmodified. In tests, pass
HttpLimits::default().
§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 any portable wiring step fails: the VFS mount paths cannot be registered, the capability store cannot be initialized over the injected KV, the group configuration cannot be loaded, or the CLI root identity cannot be bootstrapped.
Sourcepub fn bind_boot_local_egress(
&self,
local_egress: HashMap<String, Vec<String>>,
) -> Result<(), Error>
pub fn bind_boot_local_egress( &self, local_egress: HashMap<String, Vec<String>>, ) -> Result<(), Error>
Bind the process-lifetime local-egress boot snapshot before the first capsule load.
This is a boot-only seam: reloads reuse the bound snapshot and a second bind fails, so operator revocation remains daemon-restart-bound.
§Errors
Returns an error if a boot snapshot was already bound.
Sourcepub async fn with_resources_and_workspace_layout(
session_id: SessionId,
workspace_root: PathBuf,
runtime_limits: CapsuleRuntimeLimits,
local_egress: HashMap<String, Vec<String>>,
http_limits: HttpLimits,
resources: KernelResources,
workspace_layout: WorkspaceLayout,
) -> Result<Arc<Self>, Error>
pub async fn with_resources_and_workspace_layout( session_id: SessionId, workspace_root: PathBuf, runtime_limits: CapsuleRuntimeLimits, local_egress: HashMap<String, Vec<String>>, http_limits: HttpLimits, resources: KernelResources, workspace_layout: WorkspaceLayout, ) -> Result<Arc<Self>, Error>
Construct a kernel from injected resources and workspace layout.
§Panics
Panics on native targets when called from a single-threaded tokio
runtime because the capsule engine requires block_in_place.
§Errors
Returns an error if VFS mounts, the capability store, group configuration, or CLI root bootstrap cannot be initialized.
Sourcepub async fn load_boot_capsules(&self)
pub async fn load_boot_capsules(&self)
Auto-discover and load the default principal’s boot-critical view.
Daemon readiness depends on the default view because it owns system service capsules such as the CLI proxy. Other profile principals are warmed after boot so persisted tenant state cannot make restart health depend on loading every agent’s tool set.
Sourcepub fn schedule_profile_principal_warm(self: &Arc<Self>)
pub fn schedule_profile_principal_warm(self: &Arc<Self>)
Schedule background warm-up for known non-default profile principals.
The actual load work is serialized by
Kernel::capsule_load_lock, so this can run behind a ready daemon
without racing other admin-driven warm/reload paths.
Sourcepub async fn load_all_capsules(&self)
pub async fn load_all_capsules(&self)
Auto-discover and load capsule views for known principals.
The default principal is loaded eagerly, then every principal with a profile on disk gets its own view. Content-identical capsules reuse the same installed artifact on disk, but loaded runtime instances remain principal-scoped; default’s capsule set is never copied into another principal’s view.
Sourcepub async fn ensure_principal_loaded(&self, principal: &PrincipalId)
pub async fn ensure_principal_loaded(&self, principal: &PrincipalId)
Build or refresh one principal’s capsule view from its own install set.
Sourcepub fn agent_readiness_probe(&self) -> AgentReadinessProbe
pub fn agent_readiness_probe(&self) -> AgentReadinessProbe
Build an in-process agent-loop readiness probe over the live registry.
Handed to the co-located gateway so its prompt fail-fast can ask whether
the loaded set can serve a chat turn directly — agent-loop serviceability
is global daemon health, not per-principal authorization, so it needs no
capability check and no socket round-trip (unlike the capability-gated
GetAgentReadiness request, which exists for the detailed, ops-facing
/api/sys/readiness view and astrid doctor). The closure clones the
registry Arc, so each call reflects the current loaded set.
Sourcepub fn capsule_topic_probe(&self) -> CapsuleTopicProbe
pub fn capsule_topic_probe(&self) -> CapsuleTopicProbe
In-process probe for “does a loaded capsule subscribe to this topic”,
computed from the live registry without a capability check. Mirrors
Self::agent_readiness_probe; the co-located gateway uses it to
gracefully degrade a route whose backing verb a pre-upgrade capsule
may not handle (e.g. answer 501 instead of waiting out a bus timeout),
and lets routes wait for a caller’s async-warmed capsule view without
going through capability-gated inventory APIs.
Sourcepub fn capsule_topic_probe_with_warm(self: &Arc<Self>) -> CapsuleTopicProbe
pub fn capsule_topic_probe_with_warm(self: &Arc<Self>) -> CapsuleTopicProbe
Build a topic probe that can actively warm the caller’s uplink capsules before answering a scoped readiness read.
The daemon-spawned gateway uses this for registry-backed model routes:
after restart, the route must not publish request IPC until the caller’s
registry subscription exists. The plain Self::capsule_topic_probe
remains passive for compatibility with existing callers.
Sourcepub fn connection_opened(&self, principal: &PrincipalId)
pub fn connection_opened(&self, principal: &PrincipalId)
Record that a new client connection for principal has been established.
Sourcepub fn connection_closed(&self, principal: &PrincipalId)
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).
Sourcepub fn set_ephemeral(&self, val: bool)
pub fn set_ephemeral(&self, val: bool)
Enable or disable ephemeral mode (immediate shutdown on last disconnect).
Sourcepub fn arm_ephemeral_startup_fallback(self: &Arc<Self>)
pub fn arm_ephemeral_startup_fallback(self: &Arc<Self>)
Arm startup handoff grace after readiness, allowing brief preflight connections before the host establishes its lasting lifecycle lease.
Sourcepub fn total_connection_count(&self) -> usize
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.
Sourcepub fn connections_by_principal(&self) -> Vec<(PrincipalId, usize)>
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.
Auto Trait Implementations§
impl !Freeze for Kernel
impl !RefUnwindSafe for Kernel
impl !UnwindSafe for Kernel
impl Send for Kernel
impl Sync for Kernel
impl Unpin for Kernel
impl UnsafeUnpin for Kernel
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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