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

EventFieldsDescription
config.applysuccess, changes, errorMessage?Sandbox config changed
egress.requestaccess, host, method, path, query?, headers?, body?Outbound HTTP request
egress.responserequest_id, status, duration_msResponse to an egress request
egress.chunkrequest_id, bodyWebSocket frame
fs.requestaccess, mount, path, operationFile access attempt (read or write)
fs.responsebackend, request_id, duration_ms, error?File operation result
stdiostdout?, stderr?Process output
resource.usagecpu_percent, memory_bytesPeriodic resource sample
exec.requestcwd, commandExec call started
exec.responserequest_idExec 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