> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heretic.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Privacy and retention

> Review what Heretic observes, receives, derives, stores, returns, and deletes on normal and zero-data-retention paths.

Heretic observes a connection, receives a browser payload, derives an assessment, and stores different data in separate layers. A deletion or retention bound in one layer does not apply to every other layer.

## Data observed at the edge

Depending on protocol and available evidence, a full session can contain:

* the connecting IP and port
* TCP and IP handshake fields
* TLS ClientHello fields and parsed fingerprints
* HTTP/2 settings, frame order, and window information
* UDP, QUIC Initial, and HTTP/3 observations
* HTTP request metadata and selected headers
* round-trip timing

The edge can derive ASN, country, network description, and network classification from the connecting IP. Network classification remains separate from the verdict.

## Data submitted by the collector

`GET /n` can carry an optional free-text tag in its query string. The final POST is a flat object containing the public site key and collected fields. The edge presents selected work-output keys as `measured` and the remaining fields as `declared` in the full session API; NDJSON retains the original payload.

Measured sections can include:

* compute timing and cache probes
* GPU work and graphics observations
* worker parallelism
* frame cadence
* microarchitecture-related checks
* canvas and audio measurements

Declared sections can include:

* user agent, platform, languages, logical cores, memory claim, touch points, and webdriver state
* user-agent client hints
* display dimensions and pixel ratio
* timezone, UTC offset, and locale
* WebGL values
* the broader optional surface, including WebGPU, fonts, WebRTC metadata, media-device counts and hashed IDs, permission states, storage capabilities, battery state, codecs, runtime, and cross-realm observations

The browser sends this data to the edge. It can be modified before arrival. The rules treat declarations as claims.

## Browser-local behavior

Collector requests use `credentials: 'omit'` and do not send ambient cookies or browser credentials.

Endpoint resolution can cache a selected edge in `sessionStorage`. The default discovery cache lifetime is 15 minutes. Storage availability tests briefly write and remove probe values.

`rawSurface` defaults to `false`. It changes only:

* exact WebRTC host candidate addresses
* exact battery level and finite charge or discharge times
* exact storage quota and usage

Counts, address families, coarse battery values, and storage buckets can remain. Other surface fields are not removed by this option.

## Identity

Identity version `2` can derive `machine` and `instance` IDs from normalized components. When the edge accepts a nonempty posted public site key of at most 128 bytes, its trimmed value participates in the ID scope. Sessions without an accepted key use the unscoped fallback.

The identity object can also expose normalized component material. These IDs describe matching component sets within one identity version and key scope. They do not identify a person or guarantee global uniqueness, anonymity, irreversibility, collision freedom, or continuity through every software and hardware change.

Identity does not change the verdict.

## Storage layers

| Layer                    | Contents                                                           | Current bound                                                                                                                                                      | Tenant access                                           |
| ------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- |
| Edge flow state          | Packet and connection observations used to join a flow             | Idle TTL of 180 seconds                                                                                                                                            | None                                                    |
| Live edge session        | Submitted payload, raw IP, request metadata, and assessment inputs | Normal expiry threshold of 900 seconds from creation; memory pressure can remove it sooner, while failed persistence can extend residency through the retry window | Dashboard detail after projection ownership is verified |
| Edge NDJSON              | Record schema `4` with the full session and full assessment        | Defaults to 180 days and 64 GiB per records directory                                                                                                              | None                                                    |
| Control-plane projection | Tenant-attributed subset of a settled assessment                   | Eligible for pruning after seven days                                                                                                                              | Dashboard and tenant API                                |
| Erasure ledger           | Workspace, site, deleted row count, requester, and timestamp       | No deletion schedule in the current implementation                                                                                                                 | Not exposed as verdict data                             |

## Normal settlement

A normal session's evidence freezes at the first valid `/c`. The tenant projection commits before the collector receives its request ID. Local NDJSON becomes eligible after the separate 60-second settlement threshold, and a sweep runs every 30 seconds.

A session normally expires from memory 900 seconds after creation. If its local record has not persisted, the edge retains it while retrying for up to 40 sweeps, about 20 minutes of retries at the current interval. Successful persistence permits removal after the normal expiry threshold. Memory pressure can remove a session sooner.

At settlement, the edge attempts two independent writes:

1. Append the full record to local NDJSON.
2. Persist the same frozen session and assessment to local NDJSON.

The edge sends the projection directly during ordinary completion. It permits 64 in-flight projections, fails immediately when saturated, applies a six-second whole-request deadline and two-second connect timeout, rejects redirects and non-200 responses, caps the acknowledgement body at 4 KiB, and parses the acknowledgement strictly. It has no internal retry queue.

One store can contain a session when the other does not.

## Edge NDJSON retention

The edge writes one NDJSON file per UTC day. Default bounds are:

* 180 days through the age setting
* 64 GiB through the byte setting

Operators can override or disable either bound.

Cleanup runs after persistence activity and removes whole daily files. It can delete older files before the age cutoff to satisfy the byte cap. It always keeps the newest daily file.

These are configured bounds, not exact deletion times.

## Control-plane projection retention

A projection stores assessment fields, projected findings and family reports, provenance, projected network metadata, identity, edge, and timestamps. It has no raw-IP column.

Rows become eligible for pruning when `created_at` is more than seven days old. Seven days is not a deletion deadline.

The Worker has no scheduled pruning job. It samples a retention sweep after roughly one in every 200 successful ingest writes. Sparse traffic, interruption, or sweep failure can leave rows beyond seven days.

## Tenant deletion

The dashboard can delete a site's attributed projection rows. It does not rewrite edge files, remove live state, revoke keys, archive the site, or delete unattributed rows.

The operation records erasure metadata after deleting the verdict rows.

## Zero data retention

With `zdr: true`, the collector posts to `/z` instead of `/c`.

Parsed claims remain request-local. A valid ZDR request creates no assessment, identity, projection, NDJSON record, request ID, or retrievable session. It removes the owned per-nonce session and linked state. The edge returns exactly `{ "ok": true }`, and the collector returns `{ ok: true }`.

Malformed or incomplete ZDR submissions retain only a hidden, nonpersistable baseline marker. They retain none of the submitted request data.


## Related topics

- [Dashboard and keys](/dashboard/dashboard-and-keys.md)
- [Heretic documentation](/index.md)
- [Troubleshooting](/troubleshooting.md)
- [Signal reference](/reference/signals.md)
