# Telemetry

Every seal, session and request leaves a signed record your browser checks. Seal can't edit it, and can't drop it without leaving a gap.

Source: https://seal.zone/docs/telemetry

The enclave writes this record itself, signs it and ships it every few seconds. Seal stores it but can't change it.

## What the enclave records

Each entry has the enclave's time, your tenant and the identity that acted.

| Entry | Written when |
|---|---|
| Seal | A blob was sealed, with its id, destination and apps |
| Session | An app started a session, with its address |
| Extend | The SDK renewed a session (every 5 minutes) |
| End | A session ended early |
| Refused | The enclave turned something down, with the full reason |
| Request | A request finished: HTTP method, path and status, or Postgres command kind and SQLSTATE |
| Integrity | An integrity signal arrived, and what your policy did |
| Dropped | An overloaded replica discarded entries, with counts |

It never records your key, bodies, query strings or upstream error text. Only the enclave writes entries, so an attacker on your server can't add, change or erase one.

Callers get a short code like `NotAllowed`, and the full reason goes here. Common reasons are no grant, outside networks, an expired blob and stale state. The console shows each in plain words.

## Signed batches and streams

A replica signs a batch at least every 5 seconds, with a key the key guardian certified. Each start begins a new stream numbered 1, 2, 3, and a clean shutdown marks the last batch. Seal can't edit a batch without breaking its signature, or drop one without leaving a gap.

## Checking it

The console's Telemetry page checks every signature in your browser and shows invalid batches and gaps. A stream that ends without a last batch when a replica restarted is normal. A gap mid-stream isn't.

Summary charts and the Usage page are counted by Seal's servers and marked unverified. Press **Verify** to recount from checked batches.

For a check that doesn't rely on Seal's page, use the CLI:

```shell
seal telemetry --since 24h --receipts receipts.jsonl --reader-key reader.key
```

## Receipts

A receipt proves the enclave recorded a seal or session. Keep them, and you can later prove Seal held back an entry or a whole stream.

```shell
seal secret --to https://api.openai.com/v1 --app checkout --receipt-file receipts.jsonl
```

```python
import os, seal

with seal.session(os.environ["OPENAI_API_BLOB"]) as s:
    ...
    seal.receipts.append("receipts.jsonl", s.receipts())
```

In Node, seal with `withReceipt: true` and use `receipts.append`.

## Encrypting to your own keys

By default Seal's servers can read your telemetry. Add a telemetry reader to encrypt entries to your own key:

```shell
seal settings telemetry-readers add --generate reader.key
```

Seal then sees only the stream, batch number, entry count and time range. Load the key in the console, or pass `--reader-key` to the CLI. Adding a reader is widening, so it waits out your [pending window](https://seal.zone/docs/changes#the-pending-window). Server-side charts can't count encrypted entries, so use Verify.

## Overload

A replica never blocks requests to write telemetry. It holds up to 10,000 unsent entries. Past that, it drops the oldest Request entries first and records the count in a Dropped entry.
