::docs :: concepts

the trust stack

The egress ledger and air gap, prompt-injection quarantine, the per-answer trust receipt, secret handling, and why every loosened posture is session-only unless saved.

The privacy claim is not a policy promise — it is inspectable in the code and observable on the network. With http_request removed, the only ways anything leaves your machine are a web search query, a page fetch, and the MCP servers you configured. Each of those exits is recorded.

::egress ledger and air gap

Every network exit — host, bytes, channel — is recorded and renders live in the rail (⇅ sent → host · bytes · channel). /privacy shows what can leave, /privacy egress what did, and /privacy airgap on seals the boundary: web tools refuse, remote MCP calls refuse, and every blocked attempt shows in the ledger as ⛔ air-gap blocked. A fully local turn's receipt reads local-only; silence means nothing left.

commands
/privacy                    what CAN leave this machine
/privacy egress [clear|n]   the per-event ledger of what DID
/privacy airgap [on|off] [--save]

The test suite carries a no-new-egress grep guard over the source tree, so a new network path cannot land unnoticed.

::prompt-injection quarantine

Web pages, remote MCP results, and the ingested corpus are untrusted input. Content that tries to steer the agent ("ignore your previous instructions", tool coercion, role overrides) is detected, visibly flagged in the trace, and fenced between data-not-instructions markers before the model sees it. In the default gate mode, the first tool batch after a flagged observation faces the approval gate regardless of risk tier — one fresh human look at calls whose arguments may derive from injected content. Tool classifications come from the live registry (tools declare untrusted=True), so the coercion scan covers every gated tool, MCP tools included. @file attachments and piped stdin warn when instruction-shaped, but never block.

runtime.quarantine: off

no scanning

warn

scan, fence, and show flags — never change gating

gate (default)

warn, plus the first tool batch after a hit faces the gate

::the trust receipt

The one-line stats receipt under each answer carries a trust segment: local-only, or the turn's egress summary (⇅ N sends · bytes → host) in yellow, blocked attempts, and how many calls faced the approval gate. /trace answer expands it into full answer provenance — each cited source's origin and trust flags, what left the machine, and the human gate decisions.

::secrets

  • At the gate — each gated call's arguments are scanned for keys, tokens, and private-key blocks; a hit warns inline.
  • In shell childrenrun_shell children do not inherit secret-shaped environment variables (*API_KEY*, *SECRET*, *TOKEN*, *PASSWORD*, *CREDENTIAL*, ANTHROPIC*, OPENAI*, AWS_*, GITHUB_* by default). The fragment list is shell.env_scrub.
  • At the network boundary — outgoing MCP arguments and any remote-Ollama send are subject to runtime.redaction (off / warn / redact); local Ollama calls are never scanned because there is no boundary.
  • Nowhere else — no Saturn feature takes an API key. MCP secrets are plain env vars expanded from .env.

::trust settings are session-only unless saved

runtime.auto_approve, runtime.airgap, runtime.quarantine, runtime.redaction, runtime.grant_scope, and shell.env_scrub set through /config, /policy, or /privacy apply for the session only unless you pass an explicit --save. A loosened security posture is never written to disk silently.

::what the benchmark measures

python benchmark.py runs the graded trust benchmark — the numbers the product's claims rest on: the grounding judge's catch rate, approval-gate coverage (every non-read-only call must have faced the gate), the injection flag rate (a planted corpus document carrying instruction-shaped content, retrieved through the live knowledge-base path), and the semantic write gate's fabrication catch rate. --strict exits 1 on any graded FAIL. Reports land in logging/benchmarks/.