Privacy contract
This is the non-negotiable part. If it's violated, Saxeo's whole reason to exist evaporates.
What we do
- Seal prompts on ingress. AES-256-GCM with a master key the moment the request hits the gateway. For inference calls, the plaintext window lives only between the egress shim and the upstream call: never on disk, never in logs. (The keyless assistant on the portal home is the one other surface that handles plaintext: it proxies your question to our upstream under the same never-logged, never-persisted rule, but it is a convenience surface, not the sealed inference path.)
- Log metadata only. Inference logs hold model id, node id, token counts, latency, and status. Nothing else.
- Hash API keys. Argon2id, with only a 20-char prefix kept in the clear for UI labeling.
- Authenticate dashboard sessions via SIWE. No email + password store to breach.
What we will never do
- Store, log, or echo prompt content.
- Store, log, or echo completion content.
- Inspect inflight requests for "policy" reasons.
- Sell or share usage metadata to anyone, ever.
The disclosed exceptions
A few features cannot work if nothing is kept, and pretending otherwise would be the dishonest option. Each is listed here, each is AES-GCM-sealed with the master key (ciphertext at rest), each is opened in-frame only to do the job you asked for, none is ever logged, and each is destroyed on a schedule you can predict:
- Hosted agents — agent code and env, because a scheduler cannot re-run what it does not hold. Destroyed when you delete the agent.
- Relay — the note and files you chose to share, because you cannot share what was not kept. Destroyed on revoke or expiry.
- Memory and agent state — the content an agent explicitly asked to remember. Yours to delete. One carve-out from the rule above: a memory chunk's embedding vector is stored unsealed so search can score it. The text is sealed; the vector it was turned into is not, and a vector leaks more about its text than nothing. See Memory → Privacy and limits.
- Batch files — the input JSONL and the output/error files,
because a batch worker cannot run a file it does not hold and you cannot
collect results tomorrow that were not kept. A batch's input has its
ciphertext destroyed the moment the batch reaches a terminal state; every
file expires on a hard TTL (7 days by default) and
DELETEdestroys it immediately. Download your results before the TTL: afterwards the metadata remains and the content is gone, including to us.
The rule these share: content persists only where you asked for a feature that requires it, sealed, bounded in time, and never in a log line. Everything outside this list follows the ordinary contract above.
What's confidential today, and what isn't yet
Better you read this here than find out later, because it depends on the tier.
On standard tier (and any model that isn't confidential-capable), we
decrypt the prompt at the egress frame and hand it to a third-party host to run
it (OpenRouter, or the vendor for the closed models). That host sees the
prompt. Standard tier protects you from someone watching the network, and from
anyone who gets into Saxeo's own logs or database. But it does not hide the
prompt from the company running the model.
What standard tier does hide from that company is you: every request leaves
on Saxeo's own upstream account, so the vendor never learns the caller's
identity, key, or payment details. That's anonymized access (who, not
what), and it is not confidentiality; only the saxeo-confidential-* models
hide the content from the host itself. The
privacy ladder walks through the distinction.
On confidential tier (live today for the saxeo-confidential-*
models) that
no longer holds: the model runs inside an attested Intel TDX enclave the host
can't see into. The gateway verifies the enclave's hardware quote before routing
and verifies a per-response signature from the key bound into that quote
afterward, both stamped into your receipt. This is the thing we
used to say "Phase 2 fixes". It's real now, for that model. What's still ahead:
extending it to more models, and moving the enclave from an attested third-party
backend to hardware Saxeo measures itself (so the trust root is our binary,
not the backend's attestation report).
How to verify
The privacy-critical code lives in two short files, sable-api/src/routes/chat.rs
and sable-api/src/crypto/mod.rs. We kept them small enough to read in one
sitting. We're getting the gateway source ready to publish so you can check it
yourself instead of taking our word for it. Two things you can already verify
today: the signed receipt on every call, and, for the
confidential tier, the TEE attestation carried in that receipt's
attestation block (the SDK's verifyAttestation() checks it before you send),
so you can confirm the enclave that ran your request, not just trust us.