---
title: attest
description: Sign attestation artifacts -- actions, decisions, approvals, handoffs, endorsements, receipts.
---

import { Callout } from 'fumadocs-ui/components/callout';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

<Tabs items={['action', 'decision', 'approval', 'handoff', 'endorsement', 'receipt']}>
<Tab value="action">
## treeship attest action

Record that an actor performed an action.

```bash
treeship attest action \
  --actor agent://researcher \
  --action openai.chat.completion \
  --meta '{"model":"gpt-4o","tokens":1247,"prompt_hash":"sha256:abc..."}'
```

### Options

| Option | Description |
|--------|-------------|
| `--actor <uri>` | Who performed the action (required) |
| `--action <label>` | What action occurred (required) |
| `--parent <id>` | Parent artifact ID for chain linking |
| `--approval-nonce <nonce>` | Nonce from an existing approval |
| `--input-digest <sha256:hex>` | SHA-256 digest of the input consumed |
| `--output-digest <sha256:hex>` | SHA-256 digest of the output produced |
| `--content-uri <uri>` | URI to referenced content |
| `--meta <json>` | Arbitrary JSON metadata |
| `--out <path>` | Write raw DSSE envelope to file (use `-` for stdout) |

<Callout type="info">
Use `--input-digest` to attest that an action occurred on specific content without revealing the content itself. The digest proves which data was processed. The content never enters the artifact.
</Callout>

### Privacy-preserving attestation

```bash
treeship attest action \
  --actor agent://clinical-ai \
  --action clinical.note.summarize \
  --input-digest sha256:e3b0c44298fc1c149afb4c8996fb924 \
  --content-uri ehr://patient/94821/note/2026-03-26
```
</Tab>
<Tab value="decision">
## treeship attest decision

Record an LLM inference decision with model, token usage, and confidence metadata.

```bash
treeship attest decision \
  --actor agent://analyst \
  --model claude-opus-4 \
  --tokens-in 8432 \
  --tokens-out 1247 \
  --summary "Contract analysis complete." \
  --confidence 0.91
```

### Options

| Option | Description |
|--------|-------------|
| `--actor <uri>` | Who made the decision (required) |
| `--model <name>` | Model identifier, e.g. `claude-opus-4`, `gpt-4o` |
| `--tokens-in <n>` | Input token count |
| `--tokens-out <n>` | Output token count |
| `--prompt-digest <sha256:hex>` | SHA-256 digest of the prompt |
| `--summary <text>` | Plain-text summary of the decision |
| `--confidence <0-1>` | Confidence score between 0 and 1 |
| `--parent <id>` | Parent artifact ID for chain linking |

<Callout type="info">
Decision attestations are designed for LLM audit trails. They record which model was used, how many tokens were consumed, and what the model concluded, without storing the prompt or response content.
</Callout>
</Tab>
<Tab value="approval">
## treeship attest approval

Record that an approver authorized an intent. A random nonce is generated automatically.

```bash
treeship attest approval \
  --approver human://alice \
  --description "approve stripe charge max $500 to acme" \
  --expires 2026-03-26T18:00:00Z
```

Returns the approval artifact ID and the nonce. Pass the nonce to the agent so it can echo it in `--approval-nonce` when attesting the action.

### Options

| Option | Description |
|--------|-------------|
| `--approver <uri>` | Approver identity URI (required) |
| `--subject <id>` | Artifact ID being approved (the subject of the approval itself) |
| `--description <text>` | Plain text scope of what is authorized |
| `--allowed-actor <uri>` | Scope: actor URIs permitted to consume this approval (repeatable) |
| `--allowed-action <label>` | Scope: action labels permitted under this approval (repeatable) |
| `--allowed-subject <uri>` | Scope: subject URIs permitted as the action's target (repeatable) |
| `--max-uses <n>` | Signed into the grant for future ledger enforcement |
| `--unscoped` | Required to mint a bearer approval (no scope axes set); without it the CLI refuses |
| `--expires <timestamp>` | RFC 3339 expiry time |

<Callout type="warn" title="Scope is the new default">
As of v0.9.6, `treeship attest approval` refuses to mint an approval that has no scope axis (no `--allowed-*` and no `--max-uses`). Pass `--unscoped` to opt in to a bearer approval explicitly. Verify will warn that an unscoped approval proves binding only -- not actor/action/subject authorization.
</Callout>

<Callout type="info" title="Replay posture (v0.9.10)">
v0.9.9 shipped the **local Approval Use Journal** and the **consumer-side Hub checkpoint verifier**. v0.9.10 closed four trust-bypass paths in those checks. Each replay level surfaces as its own verify row:

- **`replay-package-local`** — duplicate uses inside this package. Always available.
- **`replay-local-journal`** — the workspace's `<config>/journals/approval-use/` enforces single-use for `(grant_id, nonce_digest)`. Available when verifying inside the workspace that produced the package.
- **`replay-included-checkpoint`** — embedded `JournalCheckpoint` records verify offline (each `record_digest` recomputes).
- **`replay-hub-org`** — a Hub-signed checkpoint covers every embedded use_id. Available when present; the Hub server itself is out of scope for v0.9.9-v0.9.10.

Plus four bundle-level binding rows (added in v0.9.10):
`approval-use-record-digest`, `approval-use-nonce-binding`, `approval-use-action-binding`, `approval-use-chain-continuity`. Each pins a specific invariant; the panel renders one ✓ or ✗ per row, never silent pass.

The honesty rule: a row reports `✓` only when the matching evidence is present and verified, `✗` only when present and failed, `-` when the evidence isn't in the package. See [Replay levels](/guides/replay-levels) for the full ladder.
</Callout>
</Tab>
<Tab value="handoff">
## treeship attest handoff

Record a transfer of work between actors.

```bash
treeship attest handoff \
  --from agent://researcher \
  --to agent://executor \
  --artifacts art_a1b2,art_c3d4
```

### Options

| Option | Description |
|--------|-------------|
| `--from <uri>` | Source actor URI (required) |
| `--to <uri>` | Destination actor URI (required) |
| `--artifacts <ids>` | Comma-separated artifact IDs being transferred (required) |
| `--approvals <ids>` | Comma-separated approval IDs the receiver inherits |
| `--obligations <text>` | Comma-separated obligations the receiver must satisfy |
</Tab>
<Tab value="endorsement">
## treeship attest endorsement

Record an endorsement of an existing artifact. Used for post-hoc validation, compliance sign-off, and countersignatures.

```bash
treeship attest endorsement \
  --endorser human://auditor \
  --subject art_a1b2 \
  --kind validation
```

```bash
treeship attest endorsement \
  --endorser human://compliance \
  --subject art_c3d4 \
  --kind compliance \
  --rationale "Meets SOC-2 requirements" \
  --expires 2026-12-31T00:00:00Z \
  --policy-ref https://example.com/policy
```

### Options

| Option | Description |
|--------|-------------|
| `--endorser <uri>` | Endorser identity URI (required) |
| `--subject <id>` | Artifact ID being endorsed (required) |
| `--kind <type>` | Endorsement kind: validation, compliance, countersignature, review (required) |
| `--rationale <text>` | Human-readable rationale for the endorsement |
| `--expires <timestamp>` | Expiration timestamp (RFC 3339) |
| `--policy-ref <uri>` | URI to the governing policy document |
| `--meta <json>` | Extra metadata as a JSON object |
| `--parent <id>` | Parent artifact ID for chain linking |
| `--out <path>` | Write raw DSSE envelope to file (use `-` for stdout) |

<Callout type="info">
Endorsements are separate artifacts that reference the subject via `--subject`. They form their own chain and can be verified independently. Use `--policy-ref` to link to the policy or checklist that was followed during review.
</Callout>
</Tab>
<Tab value="receipt">
## treeship attest receipt

Record an external system confirmation (webhook, timestamp, inclusion proof).

```bash
treeship attest receipt \
  --system system://stripe-webhook \
  --kind confirmation \
  --subject art_a1b2 \
  --payload '{"eventId":"evt_abc","status":"succeeded"}'
```

For larger structured receipts, read the payload from a file:

```bash
treeship attest receipt \
  --system system://acme-memory \
  --kind memory.proof \
  --payload-file memory-proof.json \
  --payload-digest sha256:...
```

### Options

| Option | Description |
|--------|-------------|
| `--system <uri>` | System that produced the receipt (required) |
| `--kind <type>` | Receipt kind: confirmation, timestamp, inclusion, webhook (required) |
| `--subject <id>` | Subject artifact ID |
| `--payload <json>` | Receipt payload as a JSON object |
| `--payload-file <path>` | Read receipt payload JSON from a file |
| `--payload-digest <digest>` | Digest of the external payload, for example `sha256:<hex>` |
</Tab>
</Tabs>
