# Security
Source: https://docs.treeship.dev/concepts/security

> Treeship's security properties and threat model.

## Cryptographic primitives

| Primitive       | Usage                                                 |
| --------------- | ----------------------------------------------------- |
| Ed25519         | All artifact signatures                               |
| SHA-256         | Content-addressed artifact IDs, subject digests       |
| DSSE            | Envelope format for all signed statements             |
| PAE             | Pre-Authentication Encoding for deterministic signing |
| DPoP (RFC 9449) | Proof-of-possession for Hub authentication            |

## Key management

* One Ed25519 keypair per Treeship
* Private key encrypted at rest
* Key never leaves the local machine unless explicitly exported
* No key escrow, no key recovery service

<Callout type="warn">
  Root access to the machine breaks all guarantees. The trust boundary is the machine itself. If someone has your private key and passphrase, they can forge artifacts.
</Callout>

## Hub connection model: enrollment and operation

**Two phases, two different security questions:**

| Phase                                                    | Question                                                                                         | Mechanism                                                                                                                                                                                                                                                                            |
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Enrollment** (`treeship hub attach`)                   | Should this machine be allowed to register a new **hub connection** (dock) with the Hub?         | Human-in-the-loop **device authorization** (browser at `treeship.dev/hub/activate`, single-use challenge, atomic consumption, mandatory nonce on finalize). The CLI generates a fresh Ed25519 keypair for Hub / DPoP use and registers **ship** + **dock** public keys with the Hub. |
| **Operation** (every `hub push`, `session report`, etc.) | Does this request come from someone who **right now** holds the private key for this connection? | **DPoP (RFC 9449)** -- a short-lived proof JWT bound to HTTP method and URL, signed with the connection private key. **No** long-lived bearer token for writes.                                                                                                                      |

Good user experience (**no device code on every push**) is compatible with this model: the code is **only** for **bootstrapping trust** (enrollment). Ongoing auth is **cryptographic proof-of-possession**, not repeated human proof.

### What counts as a "device"?

The Hub identifies a **hub connection** by a **`dock_id`** (returned as `hub_id` in the CLI) and registered **public keys**. That is **cryptographic device identity**, **not** hardware attestation (no TPM / Secure Enclave binding in the default path). Copying `~/.treeship` with valid hub connection material to another host is, from the Hub's perspective, the **same** connection -- the same as copying an SSH private key.

### Standards alignment

* **RFC 8628** (OAuth 2.0 Device Authorization Grant) -- same *class* of flow as "CLI / constrained client can't do a browser redirect."
* **RFC 9449** (DPoP) -- proof-of-possession for API requests, aligned with modern **sender-constrained** access patterns (contrast with replayable bearer secrets for every call).
* **Ed25519** -- widely deployed signature scheme for new systems.

### Threats and mitigations (Hub path)

| Threat                                               | Mitigation                                                                                                                                                 | Residual risk                                                                                                                   |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Stolen **DPoP proof** from a log                     | Proofs are bound to **method + URL** and use **jti** / time window; replay should fail                                                                     | Misconfiguration or bugs could weaken binding -- treat as **implementation** risk                                               |
| Stolen **connection private key** (filesystem exfil) | Same class as **stolen SSH key**; use **OS protections**, FDE, least privilege, **`treeship hub kill`** to revoke the connection on the Hub                | Until revoked, attacker can act as that connection **without** a new device code                                                |
| Rogue **enrollment**                                 | Device flow requires **human approval**; challenge is **single-use** and consumed **atomically** (see `PLATFORM.md` / Hub changelog for hardening history) | Phishing a user into approving a rogue attach -- partial mitigation is **user education** and **clear UI** on the activate page |
| **Hub** compromise                                   | Does not rewrite **past** offline-verifiable receipts; may affect **availability** and **published** URLs                                                  | Out of scope for client-only verification; run verifiers **offline** for evidence                                               |

### Operational best practices

* **Revoke** lost or decommissioned machines: `treeship hub kill` (or equivalent) so the Hub stops accepting that dock's DPoP.
* **Named connections** (`treeship hub attach --name ...`) for multiple tenants or lifecycles.
* **CI and automation:** prefer **short-lived** or **federated** provisioning when you add it; avoid long-lived **shared** secrets in plain environment variables where OIDC or a vault is available.
* **Be explicit** if you add a separate **bearer** or API-key path: document it as a **different** trust tier, not a silent substitute for DPoP.

## What Treeship does not protect against

* A compromised signing key (if someone steals your private key and passphrase, they can forge artifacts)
* Actions taken outside of Treeship (unwrapped commands leave no trace)
* Content confidentiality (Treeship signs metadata and digests, not content, but metadata can still be sensitive)

## What Treeship does protect against

<Callout type="success">
  Treeship provides strong guarantees against retroactive tampering, unauthorized agent actions, broken chains of custody, and replay attacks.
</Callout>

* Retroactive tampering of action records
* Unauthorized agent actions (missing or expired approval)
* Broken chain of custody (missing parent links)
* Replay attacks (nonce binding, content-addressed IDs)
* Forged verification results (client-side WASM verifier runs independently of the Hub)

## Revocation

The Hub publishes a signed revocation list at:

```
GET /.well-known/treeship/revoked.json
```

This list contains revoked artifact IDs and key fingerprints. Verifiers that have network access check this list. Offline verifiers skip it and rely solely on cryptographic validity.

## Privacy

Treeship never stores the content of actions. It stores:

* Actor URIs
* Action names
* Timestamps
* Subject digests (SHA-256 hashes of content)
* Metadata you explicitly provide

To attest an action on sensitive data without revealing the data:

```bash
treeship attest action \
  --actor agent://clinical-ai \
  --action clinical.note.summarize \
  --input-digest sha256:e3b0c44298fc1c149afb4c8996fb924
```

The digest proves which document was processed. The content never enters the artifact.