Skip to content
Fuse
Esc
↑↓navigate↵open⌘Jpreview

List hitl audit log

Reads the append-only hitl audit log, oldest first: one row per event (see AuditEntry for the list), with the actor, its source, the key id, the remote address and the time. Rows point at an intervention by id and never hold its content; the question, answer and reason stay on the encrypted intervention row.

Each row carries prev_hash, the hash of the row before it (32 zero bytes for the first row), so editing, removing or reordering a row breaks the chain from that point. hash is SHA-256 over the row’s length-prefixed fields and prev_hash. fuse hitl audit --verify reads every row and recomputes the chain client-side.

Requires hitl:read. A key scoped to an environment sees only that environment’s rows and its forks’; naming any other env is 404.

GET/v1/hitl/audit
Authorization
AuthorizationBearer token · headerrequired
`Authorization: Bearer <token>` — either the static master token (`ORCH_AUTH_TOKEN`) or a revocable API key issued via /v1/api-keys (API keys require Postgres; without a database only the master token is accepted). Master-only surfaces (exec, attach, API key management) refuse API keys with 403. An expired key is refused with 401 like an unknown one. A key minted with `scopes` reaches only the hitl routes (`/v1/interventions`, `/v1/hitl/*`, and POST /v1/api-keys to mint a narrower key). Any other route is 403 code `forbidden`, reason `env_scope`, except an `/v1/environments/{vmId}` route for an environment the key does not cover, which is 404 so the key cannot probe which environments exist. **Authentication can be disabled entirely.** When neither `ORCH_AUTH_TOKEN` nor an API key store (`DATABASE_URL`) is configured — the default local-development posture — the bearer middleware becomes a pass-through: every operation this document marks as secured is reachable with no credentials, requests carry no principal, and master-only surfaces therefore admit everyone. Never run that configuration on a reachable network; set `ORCH_REQUIRE_AUTH=true` to make the orchestrator refuse to start without a master token.
or
fuse_sessionAPI key · cookierequired
HttpOnly session cookie set by POST /login for browser callers. Consulted only when no Authorization header is present.
Query parameters
envstring
Filter by environment id.
actorstring
Filter by actor id.
sincestring
Only rows at or after this time (RFC 3339), or this long ago (a duration like `24h`).
limitinteger
Max results per page (default 50, max 200).
cursorstring
Opaque cursor from a previous response's next_cursor.
Header parameters
Fuse-Actorstring
The person behind this request, as an opaque id (`user_42`, `alice@corp.com`, `slack:U0123`). Fuse records it on hitl interventions and the audit log and never checks it. Accepted on every authenticated route; it matters wherever an actor is recorded (raising, deciding, minting). At most 128 bytes, no control characters; a malformed value is 400. How the recorded actor is resolved: - key pinned to an actor: that actor (`source: pinned`). A different `Fuse-Actor` is 403 `forbidden`, reason `actor_mismatch`. - key with `hitl:act-as`: the header value (`source: asserted`, with the asserting key's id), else `key:<key_id>`. - any other key: `key:<key_id>` named after the key's label (`source: key`). Sending the header is 403 `forbidden`, reason `actor_not_allowed`, rather than silently dropped. - master token: the header value (`source: asserted`), else `master` (`source: key`). An asserted actor is only as true as the key holder's own auth.
max length 128
Fuse-Actor-Namestring
Optional display name for `Fuse-Actor`, at most 256 bytes. Sending it without `Fuse-Actor` is 400.
max length 256
Responses
200One page of audit rows.
entriesAuditEntry[]required
Show properties
Array of AuditEntry
seqinteger<int64>required
Position in the chain, strictly increasing.
eventstringrequired
`secret_answered` is a secret request answered (it records who and when, never the value). `takeover_started` and `takeover_ended` bracket a takeover; `takeover_ended` is its release. `takeover_session` closes one recorded shell or desktop session and carries `recording_id`.
Allowed:raiseddecidedexpiredcancelledinvite_mintedinvite_usedgrant_createdgrant_usedsecret_answeredtakeover_startedtakeover_endedtakeover_session
intervention_idstring
Omitted for invite events.
env_idstring
actorActorrequired
Show properties
idstringrequired
A pinned or asserted actor id, `key:<key_id>`, `master`, `system` for fuse itself, or `decider:<gate>`.
namestring
sourcestringrequired
`pinned`: fixed on the key at mint time. `asserted`: named in `Fuse-Actor` by a `hitl:act-as` key or the master token, and only as true as that caller's own auth. `key`: derived from the credential. `system`: expiry and cancellation. `decider`: a gate's decider allowed or denied the action; the id is `decider:<gate>`.
Allowed:pinnedassertedkeysystemdecider
key_idstring
The key that authenticated the request, including the key that asserted an actor. Omitted for the master token.
remote_addrstring
The caller's address as the orchestrator saw it.
recording_idstring
Set on `takeover_session` rows: the recording at GET /v1/hitl/recordings/{recordingId}. Included in `hash` only when set, so older rows hash as before.
atstring<date-time>required
prev_hashstringrequired
Hex SHA-256 `hash` of the previous row; 64 zeros for the first row.
hashstringrequired
Hex SHA-256 over this row's fields and `prev_hash`.
next_cursorstring
400Malformed request.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted by CIDR-allowlist rejections and by hitl access checks, which set `details.reason` (see the Forbidden response); master-only refusals (exec, attach, listing and revoking API keys) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlocked
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty. A 403 `forbidden` from a hitl access check carries `reason` (`missing_scope`, `env_scope`, `self_approval`, `actor_required`, `actor_mismatch`, `actor_not_allowed`, `mint_escalation`, `hitl_denied`), plus `scope` for `missing_scope`, and `gate` and `intervention_id` for `hitl_denied`. A 423 `locked` carries `intervention_id` and `kind` (`takeover` or `stall`).
403The caller authenticated, but may not make this request. Master-only surfaces (exec, attach, listing and revoking API keys) refuse API keys; those 403 bodies carry code `unauthorized`. CIDR allowlist rejections return 403 with code `forbidden` and no reason. Access checks on the hitl routes and scoped keys return 403 with code `forbidden` and `details.reason` set to one of: - `missing_scope`: the key lacks the scope the route needs (`details.scope` names it). Full-access keys never hold `hitl:decide`, `hitl:secret`, `hitl:takeover` or `hitl:act-as`. - `env_scope`: a scoped key called a route outside the hitl routes. - `self_approval`: the key or actor that raised an intervention tried to decide it. - `actor_required`: the environment sets `require_actor` and the decision names no pinned or asserted actor. - `actor_mismatch`: `Fuse-Actor` differs from the key's pinned actor. - `actor_not_allowed`: `Fuse-Actor` sent by a key without `hitl:act-as`. - `hitl_denied`: a hitl gate in `deny` mode, or a gate's decider, refused an exec, lifecycle or computer action, or an edit matched a `deny` gate. `details.gate` names the gate and `details.intervention_id` the terminal record; the message is the gate's `reason`. - `mint_escalation`: a scoped key tried to mint a key wider than itself.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted by CIDR-allowlist rejections and by hitl access checks, which set `details.reason` (see the Forbidden response); master-only refusals (exec, attach, listing and revoking API keys) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlocked
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty. A 403 `forbidden` from a hitl access check carries `reason` (`missing_scope`, `env_scope`, `self_approval`, `actor_required`, `actor_mismatch`, `actor_not_allowed`, `mint_escalation`, `hitl_denied`), plus `scope` for `missing_scope`, and `gate` and `intervention_id` for `hitl_denied`. A 423 `locked` carries `intervention_id` and `kind` (`takeover` or `stall`).
404Resource does not exist. Note the distinct code `route_not_found`, returned when the URL matches no registered route at all (wrong host, port, or path prefix) rather than a known route with a missing resource.
errorobjectrequired
Show properties
codestringrequired
Stable machine-readable code. `route_not_found` (404) means the URL matches no route this server exposes — usually a wrong host, port, or path prefix — as opposed to `not_found`, where the route exists but the resource does not. `forbidden` is emitted by CIDR-allowlist rejections and by hitl access checks, which set `details.reason` (see the Forbidden response); master-only refusals (exec, attach, listing and revoking API keys) return 403 with code `unauthorized`.
Allowed:not_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedlocked
messagestringrequired
Human-readable description.
detailsobject
Optional stable, non-sensitive metadata (e.g. ids, counts). Omitted when empty. A 403 `forbidden` from a hitl access check carries `reason` (`missing_scope`, `env_scope`, `self_approval`, `actor_required`, `actor_mismatch`, `actor_not_allowed`, `mint_escalation`, `hitl_denied`), plus `scope` for `missing_scope`, and `gate` and `intervention_id` for `hitl_denied`. A 423 `locked` carries `intervention_id` and `kind` (`takeover` or `stall`).
Request
curl -X GET "http://localhost:8080/v1/hitl/audit" \
  -H "Authorization: Bearer YOUR_TOKEN"
Response
{
  "entries": [
    {
      "seq": 0,
      "event": "raised",
      "intervention_id": "string",
      "env_id": "string",
      "actor": {
        "id": "string",
        "name": "string",
        "source": "pinned",
        "key_id": "string"
      },
      "remote_addr": "string",
      "recording_id": "string",
      "at": "2024-01-01T00:00:00Z",
      "prev_hash": "string",
      "hash": "string"
    }
  ],
  "next_cursor": "string"
}