Audit Log
All sandbox activity is observable through the events stream — sandbox.getEventsStream(). This is the audit log: a chronological stream of everything the sandbox does, delivered in real time.
Streaming events
index.ts
import { getOrCreateSandbox } from "hive";
const sandbox = await getOrCreateSandbox("my-sandbox", { fs: [...] });
const ac = new AbortController();
for await (const event of sandbox.getEventsStream({ signal: ac.signal })) {
console.log(event.id, event.timestamp, event.type);
}
// Stop the stream
ac.abort();The stream auto-reconnects on network drops (exponential backoff). Pass a signal to stop it cleanly.
Event types
| Event | Fields | Description |
|---|---|---|
config.apply | success, changes, errorMessage? | Sandbox config changed |
egress.request | access, host, method, path, query?, headers?, body? | Outbound HTTP request |
egress.response | request_id, status, duration_ms | Response to an egress request |
egress.chunk | request_id, body | WebSocket frame |
fs.request | access, mount, path, operation | File access attempt (read or write) |
fs.response | backend, request_id, duration_ms, error? | File operation result |
stdio | stdout?, stderr? | Process output |
resource.usage | cpu_percent, memory_bytes | Periodic resource sample |
exec.request | cwd, command | Exec call started |
exec.response | request_id | Exec call completed |
access on egress.request and fs.request is "allowed" or "denied".
Resuming from a cursor
Each event has a numeric id. Pass lastEventId to resume from where you left off — for example after a reconnect or process restart:
index.ts
// First run — save the last event id seen
let cursor: number | undefined;
for await (const event of sandbox.getEventsStream({ signal: ac.signal })) {
cursor = event.id;
// ... process event
}
// Later run — replay only events after the saved cursor
for await (const event of sandbox.getEventsStream({ lastEventId: cursor })) {
// only events after id `cursor`
}Filtering
Filter events by checking event.type in the loop:
index.ts
for await (const event of sandbox.getEventsStream()) {
if (event.type === "egress.request" && event.access === "denied") {
console.log("blocked:", event.host, event.method, event.path);
}
if (event.type === "fs.request" && event.access === "denied") {
console.log("file denied:", event.path, event.operation);
}
}Back to Snapshots