astrid-kernel
The microkernel.
In the OS model, this is init. It boots every subsystem, binds the Unix socket, mounts the VFS overlay, opens the audit log, and starts the IPC bus. No business logic lives here. No cognitive loops, no LLM calls, no tool implementations. The kernel routes bytes between capsules and enforces system-wide invariants. Frontends (CLI, Discord, web) connect over the Unix socket and drive the same Kernel instance.
What it owns
The Kernel struct holds every system-wide resource: EventBus, CapsuleRegistry, SecureMcpClient, CapabilityStore, OverlayVfs, SurrealKvStore, AuditLog, AllowanceStore, SessionToken, and an IdentityStore. All fields are pub. One struct, one owner, no ambient state.
Boot sequence
Kernel::new(session_id, workspace_root) runs the full boot:
- Resolve
~/.astrid/(or$ASTRID_HOME). Open persistent KV store. - Initialize the MCP process manager with workspace-scoped sandboxing.
- Bootstrap the capability store (ed25519 key pair) and chain-linked audit log.
- Mount the copy-on-write VFS overlay. Writes land in a session-scoped
TempDir. The real workspace is read-only until explicit commit. - Bind
~/.astrid/sessions/system.sock(parent directory 0o700). Generate a 256-bit CSPRNG session token, write it to a 0o600 file. - Create the identity store. Bootstrap the CLI root user idempotently.
- Spawn four background tasks: kernel management router, connection tracker, idle monitor, capsule health monitor.
- Spawn the
EventDispatcherto route IPC events to capsule interceptors.
Requires a multi-threaded tokio runtime. The constructor asserts this at the top and panics on single-threaded runtimes because block_in_place would deadlock.
Management API
The kernel router listens on astrid.v1.request.* and handles ListCapsules, GetCommands, GetCapsuleMetadata, and ReloadCapsules. Mutating operations are rate-limited with a sliding-window limiter (e.g. ReloadCapsules capped at 5/min). Read-only operations are unlimited.
InstallCapsule and ApproveCapability are defined in the protocol but not yet implemented. They return errors.
Idle auto-shutdown
Tracks active connections via AtomicUsize plus EventBus::subscriber_count() as a secondary signal. Shuts down after ASTRID_IDLE_TIMEOUT_SECS (default 300) of zero effective connections and no daemon/cron capsules running.
Socket security
- Stale sockets are detected via
connect()probe. Connection refused = stale, safe to remove. Successful connect = live kernel, boot aborted. - Symlinks at the socket path are unconditionally removed before bind.
- Socket path length is validated against the platform
sun_pathlimit (104 bytes macOS, 108 bytes Linux). - The session token has no
/tmpfallback. Writing a secret under a world-listable directory would undermine the authentication it provides.
Development
License
Dual MIT/Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.