Breaking
- Per-domain WIT host ABI. The single
astrid:capsule@0.1.0world has been split into per-domain frozen packages at@1.0.0(astrid:fs,astrid:ipc,astrid:kv,astrid:net,astrid:http,astrid:sys,astrid:process,astrid:uplink,astrid:elicit,astrid:approval,astrid:identity) plus Astrid-owned foundation I/O (astrid:io/{error, poll, streams}). Capsule authors must recompile against this SDK; the contract surface is wire-level incompatible with pre-0.7 capsules. Guest exports moved to per-export worlds inastrid:guest@1.0.0(interceptor,background,installable,upgradable). - Resource-backed handles.
ipc::Subscription,fs::File,process::Process,net::TcpStream,net::TcpListener,net::UnixListener,net::UdpSocket, andhttp::HttpStreamare now component-model resources with RAIIDropthat release the underlying kernel handle. Pre-migration code that carried opaqueu64handles (SubscriptionHandle,StreamHandle,ListenerHandle,BackgroundProcessHandle,HttpStreamHandle) and called free fns likeipc::unsubscribe,net::close,http::stream_close,process::kill(id)is gone. The new pattern: hold the typed handle in scope, call methods on it, let scope-end clean up. Explicitclosemethods remain where the spec defines them (e.g.HttpStream::close). - Typed
ErrorCodeenums per domain. Every host fn previously returningResult<T, String>now returns a domain-specific typedErrorCode(astrid:fs/host.error-code,astrid:net/host.error-code, …). The SDK preservesSysError::HostError(String)as the unified public error type — typed kernel errors are converted viaDebugformatting at the boundary (see the newhost_errhelper) so capsule code that branches onSysError::HostError(msg).contains("Timeout")continues to work without change. Pattern-matching on a typed variant requires calling the host fn directly throughastrid_sys::astrid::<domain>::host::*. identity::resolvereturnsOk(None)for unlinked. The new contract surfaces "no link" as a typedErrorCode::LinkNotFoundrather than the pre-migrationfound: boolflag. The SDK wrapper translates this toOk(None)so callers use idiomaticOptionsemantics.identity::unlinksimilarly returnsOk(false)when no link existed.fs::Metadatareshaped.Metadata.mtime(raw u64 seconds) is replaced by typedmodified() -> Result<SystemTime>/created()/accessed()reading optionalDatetimerecords.is_diris replaced by aFileTypeenum withRegular,Directory,Symlink,Othervariants. New:symlink_metadata,Metadata::mode.fs::FileHandle(nowfs::File). Returned byfs::File::open/fs::File::create/fs::File::open_mode. Wraps the resource; providesread_at/write_at/sync_data/sync_all/set_len/metadatamethods. Replaces ad-hocu64file handles.process::ProcessResultrenamed toprocess::Output;process::ExitInfoadded. The new contract carries structured(exit_code, signal)so capsules can distinguish SIGTERM-shutdown from SIGKILL-oom from normal-exit.Output::exit_code() -> i32is kept as a backward-compat accessor (returns-1for signal-killed).BackgroundProcessHandleis replaced byProcess(Drop-reaped) with methodsread_logs,write_stdin,close_stdin,signal,kill,wait,wait_with_output,os_pid. Newprocess::Commandbuilder surfaces thecwd,env, andstdinfields the new ABI adds.approval::request_decisionreturns typedDecision.approval::requeststill returnsbool(any approval variant =true). The newrequest_decisionexposes the fullDenied / Approved / ApprovedSession / ApprovedAlways / Allowanceladder.uplink::registertakes a string profile oruplink::Profile. NewProfileenum mirrors the WIT enum;registervalidates the string against canonical names (chat/interactive/notify/bridge) andregister_profiletakes the typed enum directly.net::TcpStream::connectaccepts both Unix-domain accepted streams and outbound TCP. The pre-migration distinction betweenStreamHandle(accepted) andTcpStream(outbound) collapses — the new contract uses a singleastrid:net.tcp-streamresource for both, and TCP-only options return aNotTcphost error when called on a Unix-domain stream.net::recv/net::send/net::try_recv/net::accept/net::close/net::bind_unix(free fns) are now methods onTcpStream/UnixListener. Newnet::bind_tcpexposes inbound-TCP listeners; newnet::udp_bindexposesUdpSocket.http::HttpStreamreshaped.stream_startreturns a singleHttpStream(resource-backed) carrying status, headers, andread_chunk/closemethods. The pre-migration(handle, status, headers)triple is gone.HttpStream::read_chunk()returnsOk(None)at EOF.ipc::Messagecarries typedPrincipalAttribution. Subscribers see the principal asVerified(...),Claimed(...), orSystemso cross-uplink trust decisions branch on the variant rather than parsing a string.Subscription::poll/Subscription::recvare methods; the free-fnipc::poll/ipc::recvare gone.hooks::triggerremoved. The pre-migrationwit_sys::trigger_hookhost fn is no longer part of the host ABI surface. User-middleware triggering is now an internal capsule-to-capsule concern.interceptors::pollremoved. Interceptor events are delivered throughastrid-hook-trigger(the existing guest export), not run-loop subscriptions.interceptors::bindings()remains for enumeration / debugging.env::varreturnsOk("")for missing keys;env::var_optis the new disambiguator. The host fn now returnsResult<Option<String>>; the SDK keepsvarreturningStringfor source compatibility (empty for missing) and addsvar_optfor the option semantics.
Added
host_errhelper. Single point of conversion from any per-domainErrorCode(or otherDebughost failure) intoSysError::HostError(String).kv::list_keys_page+kv::cas. Wrappers for the new paginated key listing and atomic compare-and-swap host fns.kv::get_bytes_opt/kv::get_json_opt. Disambiguate "missing key" from "empty value"; the existingget_bytes/get_jsoncontinue to collapse both into empty.time::sleep/time::monotonic/runtime::random_bytes. Wrap the newastrid:sysprimitives (sleep-ns, clock-monotonic-ns, random-bytes).process::Commandbuilder. Mirrorsstd::process::Commandfor the newenv/cwd/stdinfields onspawn-request.net::lookup_host. Wraps the new DNS-with-airlock host fn.net::TcpListener+net::bind_tcp. Inbound TCP server posture for self-hosted webhook receivers, gRPC endpoints, etc.net::UdpSocket+net::udp_bind. Unconnected and connected-mode UDP.net::TcpStream::peek/set_keepalive/set_linger/set_reuseaddr/set_hop_limit. Full surface of the newtcp-streamresource.net::TcpStream::shutdown(Shutdown::Read | Write | Both). Mirrorsstd::net::Shutdown.fs::append/fs::create_dir_all/fs::copy/fs::rename/fs::canonicalize/fs::read_link/fs::hard_link/fs::symlink_metadata/fs::remove_dir_all. Bring the SDK to feature parity withstd::fsfor the operations the new VFS surfaces.
Notes
- The
request_responsehelper is unchanged in semantics; the parallel TS SDK is migrating to match.
With many thanks from the following Astrinauts 🚀
- Joshua J. Bouw