Security model

The operator's laptop is the trust anchor. The relay is dumb pipe. Tenant data is isolated at the database level. Every action that touches a managed system is recorded in a hash-chained audit log.

Trust boundaries

  1. Desktop install — generates an Ed25519 + X25519 identity at first launch. Private keys live in the OS keychain (Windows Credential Manager / macOS Keychain / libsecret). Never on disk in plaintext.
  2. Tenant DB — one SQLite file per tenant, in the OS app-data dir. v1 ships unencrypted (OS disk encryption is the at-rest defense); v2 reintroduces SQLCipher per-tenant.
  3. Agent — Go binary on each managed Linux box. Holds its own Ed25519 + X25519 identity. Sealed with the desktop's pubkey via X25519 ECDH + ChaCha20-Poly1305 AEAD.
  4. Relay (command.orchhq.com) — routes opaque ciphertext between desktop and agent. Sees envelope metadata (from/to/timestamp). Cannot decrypt body.

What we do NOT trust

Audit log

Every state-changing action (create tenant, run workflow, approve gate, set secret) inserts a row with a SHA-256 hash chained to the previous row. Any tamper attempt produces a chain break detectable by validate_audit_chain. Logs export as JSONL for SIEM ingestion (Splunk HEC, Datadog Logs, Sumo).

Destructive commands

The DAG schema marks commands as destructive. The runner refuses to execute a destructive node unless one of its parents is an approval_gate node — the runner parks waiting for a human click, with a 24-hour default timeout. The default chat-to-DAG planner is instructed to insert these gates automatically.

Cost caps

Every workflow has a cost_cap_usd. Before invoking any Claude node, the runner projects the worst-case cost. If projected exceeds the cap, the run fails with cost_cap_exceeded — no surprise bills.

Reporting issues

Security issues — please email security@orchhq.com. We aim for first-response within 24 hours.