astrid_sys/lib.rs
1//! Raw FFI bindings for the Astrid OS System API (The Airlocks).
2//!
3//! This crate defines the absolute lowest-level, mathematically pure ABI.
4//! Every single parameter and return type across the WASM boundary is
5//! represented as raw bytes (`Vec<u8>`).
6//!
7//! This provides true OS-level primitiveness: file paths can contain non-UTF-8
8//! sequences, IPC topics can be binary hashes, and the Kernel never wastes CPU
9//! validating string encodings. All ergonomic serialization is handled entirely
10//! by the `astrid-sdk` User-Space layer.
11
12#![allow(unsafe_code)]
13#![allow(missing_docs)]
14#![deny(clippy::all)]
15#![deny(unreachable_pub)]
16#![deny(clippy::unwrap_used)]
17#![cfg_attr(test, allow(clippy::unwrap_used))]
18
19#[allow(clippy::wildcard_imports)]
20use extism_pdk::*;
21
22#[host_fn]
23extern "ExtismHost" {
24 // -----------------------------------------------------------------------
25 // File System (VFS) Operations
26 // -----------------------------------------------------------------------
27 /// Check if a VFS path exists.
28 pub fn astrid_fs_exists(path: Vec<u8>) -> Vec<u8>;
29 /// Create a directory in the VFS.
30 pub fn astrid_fs_mkdir(path: Vec<u8>);
31 /// Read a directory in the VFS.
32 pub fn astrid_fs_readdir(path: Vec<u8>) -> Vec<u8>;
33 /// Get stats for a VFS path.
34 pub fn astrid_fs_stat(path: Vec<u8>) -> Vec<u8>;
35 /// Delete a file or directory in the VFS.
36 pub fn astrid_fs_unlink(path: Vec<u8>);
37
38 /// Read a file's contents from the VFS.
39 pub fn astrid_read_file(path: Vec<u8>) -> Vec<u8>;
40 /// Write contents to a file in the VFS.
41 pub fn astrid_write_file(path: Vec<u8>, content: Vec<u8>);
42
43 // -----------------------------------------------------------------------
44 // Inter-Process Communication (Message Bus & Uplinks)
45 // -----------------------------------------------------------------------
46 /// Publish a message to the OS event bus.
47 pub fn astrid_ipc_publish(topic: Vec<u8>, payload: Vec<u8>);
48 /// Subscribe to a topic on the OS event bus.
49 pub fn astrid_ipc_subscribe(topic: Vec<u8>) -> Vec<u8>;
50 /// Unsubscribe from the OS event bus.
51 pub fn astrid_ipc_unsubscribe(handle: Vec<u8>);
52 /// Poll for the next message on an IPC subscription handle.
53 pub fn astrid_ipc_poll(handle: Vec<u8>) -> Vec<u8>;
54 /// Block until a message arrives on an IPC subscription handle, or timeout.
55 pub fn astrid_ipc_recv(handle: Vec<u8>, timeout_ms: Vec<u8>) -> Vec<u8>;
56
57 /// Register a direct uplink (frontend).
58 pub fn astrid_uplink_register(name: Vec<u8>, platform: Vec<u8>, profile: Vec<u8>) -> Vec<u8>;
59 /// Send a message via a direct uplink.
60 pub fn astrid_uplink_send(
61 uplink_id: Vec<u8>,
62 platform_user_id: Vec<u8>,
63 content: Vec<u8>,
64 ) -> Vec<u8>;
65
66 // -----------------------------------------------------------------------
67 // Storage & Configuration
68 // -----------------------------------------------------------------------
69 /// Get a value from the KV store.
70 pub fn astrid_kv_get(key: Vec<u8>) -> Vec<u8>;
71 /// Set a value in the KV store.
72 pub fn astrid_kv_set(key: Vec<u8>, value: Vec<u8>);
73 /// Delete a value from the KV store.
74 pub fn astrid_kv_delete(key: Vec<u8>);
75 /// List keys matching a prefix in the KV store. Returns JSON array of strings.
76 pub fn astrid_kv_list_keys(prefix: Vec<u8>) -> Vec<u8>;
77 /// Delete all keys matching a prefix. Returns JSON count of deleted keys.
78 pub fn astrid_kv_clear_prefix(prefix: Vec<u8>) -> Vec<u8>;
79
80 /// Get a system configuration string.
81 pub fn astrid_get_config(key: Vec<u8>) -> Vec<u8>;
82 /// Get the user ID and session ID that invoked the current execution context.
83 pub fn astrid_get_caller() -> Vec<u8>;
84
85 // -----------------------------------------------------------------------
86 // Network (Sockets & Streams)
87 // -----------------------------------------------------------------------
88 /// Bind a Unix Domain Socket and return a listener handle.
89 pub fn astrid_net_bind_unix(path: Vec<u8>) -> Vec<u8>;
90 /// Accept an incoming connection on a bound Unix listener handle. Returns a stream handle.
91 pub fn astrid_net_accept(listener_handle: Vec<u8>) -> Vec<u8>;
92 /// Read bytes from a stream handle.
93 pub fn astrid_net_read(stream_handle: Vec<u8>) -> Vec<u8>;
94 /// Write bytes to a stream handle.
95 pub fn astrid_net_write(stream_handle: Vec<u8>, data: Vec<u8>);
96 /// Close a stream handle, releasing its resources on the host.
97 pub fn astrid_net_close_stream(stream_handle: Vec<u8>);
98 /// Non-blocking accept: returns a stream handle if a connection is pending, or empty bytes.
99 pub fn astrid_net_poll_accept(listener_handle: Vec<u8>) -> Vec<u8>;
100
101 // -----------------------------------------------------------------------
102 // General System (Network, Logging, & Scheduling)
103 // -----------------------------------------------------------------------
104 /// Issue an HTTP request.
105 pub fn astrid_http_request(request_bytes: Vec<u8>) -> Vec<u8>;
106 /// Log a message to the OS journal.
107 pub fn astrid_log(level: Vec<u8>, message: Vec<u8>);
108 /// Schedule a dynamic cron job to trigger the capsule later.
109 pub fn astrid_cron_schedule(name: Vec<u8>, schedule: Vec<u8>, payload: Vec<u8>);
110 /// Cancel a dynamic cron job.
111 pub fn astrid_cron_cancel(name: Vec<u8>);
112 /// Trigger a hook event and wait for its synchronous result.
113 pub fn astrid_trigger_hook(event_bytes: Vec<u8>) -> Vec<u8>;
114
115 // -----------------------------------------------------------------------
116 // Clock
117 // -----------------------------------------------------------------------
118 /// Get the current wall-clock time as milliseconds since the UNIX epoch.
119 pub fn astrid_clock_ms() -> Vec<u8>;
120
121 // -----------------------------------------------------------------------
122 // Lifecycle (Install & Upgrade Elicitation)
123 // -----------------------------------------------------------------------
124 /// Elicit user input during install/upgrade. Request is JSON-encoded.
125 /// Returns JSON: `{"ok":true}` for secrets, `{"value":"..."}` for text/select,
126 /// or `{"values":["..."]}` for arrays.
127 /// On user cancellation or host error, returns an Extism error (not JSON),
128 /// which surfaces as `SysError::HostError` in the SDK layer.
129 pub fn astrid_elicit(request: Vec<u8>) -> Vec<u8>;
130 /// Check whether a secret has been configured (without reading it).
131 /// Takes JSON: `{"key":"..."}`, returns JSON: `{"exists":true/false}`.
132 pub fn astrid_has_secret(request: Vec<u8>) -> Vec<u8>;
133
134 // -----------------------------------------------------------------------
135 // Approval (Capsule-Level Approval Requests)
136 // -----------------------------------------------------------------------
137 /// Request human approval for a sensitive action.
138 /// Takes JSON: `{"action":"...","resource":"...","risk_level":"..."}`.
139 /// Returns JSON: `{"approved":true/false,"decision":"..."}`.
140 /// Blocks the WASM guest until the frontend responds or timeout.
141 pub fn astrid_request_approval(request: Vec<u8>) -> Vec<u8>;
142
143 // -----------------------------------------------------------------------
144 // Host Execution (The Escape Hatch)
145 // -----------------------------------------------------------------------
146 /// Spawn a native host process. Requires the `host_process` capability.
147 pub fn astrid_spawn_host(cmd_and_args_json: Vec<u8>) -> Vec<u8>;
148
149 // -----------------------------------------------------------------------
150 // Readiness Signaling
151 // -----------------------------------------------------------------------
152 /// Signal that the capsule's run loop is ready (subscriptions are active).
153 pub fn astrid_signal_ready();
154
155 // -----------------------------------------------------------------------
156 // Interceptor Handles (Run-Loop Auto-Subscribe)
157 // -----------------------------------------------------------------------
158 /// Query auto-subscribed interceptor handle mappings.
159 /// Returns JSON array of `{handle_id, action, topic}` objects.
160 pub fn astrid_get_interceptor_handles() -> Vec<u8>;
161
162 // -----------------------------------------------------------------------
163 // Identity (Platform User Resolution)
164 // -----------------------------------------------------------------------
165 /// Resolve a platform user to an Astrid user.
166 /// Takes JSON: `{"platform":"...","platform_user_id":"..."}`.
167 /// Returns JSON: `{"found":true/false,"user_id":"...","display_name":"..."}`.
168 pub fn astrid_identity_resolve(request: Vec<u8>) -> Vec<u8>;
169 /// Link a platform identity to an Astrid user.
170 /// Takes JSON: `{"platform":"...","platform_user_id":"...","astrid_user_id":"...","method":"..."}`.
171 /// Returns JSON: `{"ok":true/false,...}`.
172 pub fn astrid_identity_link(request: Vec<u8>) -> Vec<u8>;
173 /// Unlink a platform identity from its Astrid user.
174 /// Takes JSON: `{"platform":"...","platform_user_id":"..."}`.
175 /// Returns JSON: `{"ok":true/false,"removed":true/false}`.
176 pub fn astrid_identity_unlink(request: Vec<u8>) -> Vec<u8>;
177 /// Create a new Astrid user.
178 /// Takes JSON: `{"display_name":"..."}` (display_name is optional).
179 /// Returns JSON: `{"ok":true/false,"user_id":"..."}`.
180 pub fn astrid_identity_create_user(request: Vec<u8>) -> Vec<u8>;
181 /// List all platform links for an Astrid user.
182 /// Takes JSON: `{"astrid_user_id":"..."}`.
183 /// Returns JSON: `{"ok":true/false,"links":[...]}`.
184 pub fn astrid_identity_list_links(request: Vec<u8>) -> Vec<u8>;
185
186 // -----------------------------------------------------------------------
187 // Cross-Capsule Capability Checks
188 // -----------------------------------------------------------------------
189 /// Check whether a capsule (identified by session UUID) has a specific
190 /// manifest capability. Takes JSON: `{"source_uuid":"...","capability":"..."}`.
191 /// Returns JSON: `{"allowed":true/false}`.
192 pub fn astrid_check_capsule_capability(request: Vec<u8>) -> Vec<u8>;
193
194 // -----------------------------------------------------------------------
195 // Background Process Management
196 // -----------------------------------------------------------------------
197 /// Spawn a background host process. Returns JSON: `{"id": <handle>}`.
198 /// The process runs in the host sandbox with piped stdout/stderr.
199 pub fn astrid_spawn_background_host(request: Vec<u8>) -> Vec<u8>;
200 /// Read buffered stdout/stderr from a background process.
201 /// Returns JSON: `{"stdout":"...","stderr":"...","running":bool,"exit_code":int|null}`.
202 pub fn astrid_read_process_logs_host(request: Vec<u8>) -> Vec<u8>;
203 /// Terminate a background process and clean up resources.
204 /// Returns JSON: `{"killed":bool,"exit_code":int|null,"stdout":"...","stderr":"..."}`.
205 pub fn astrid_kill_process_host(request: Vec<u8>) -> Vec<u8>;
206}