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

# Evidence Families: Six Independent Measurement Domains

> Heretic runs six independent evidence families per session. Learn what each family measures, which signals it emits, and how families combine.

Heretic measures every session across six independent evidence families, each targeting a different layer of the browser-to-server stack. Independence is the key design property: a verdict requires corroboration across families for composite signals, so a single exploit or misconfiguration can only produce signals within one family — not enough to reach a conclusive ruling on its own. The more families that corroborate, the stronger the verdict.

## network-geometry

**Family ID:** `network-geometry`

Network geometry measures whether the physics of the connection are consistent with the client's declared location. It compares the measured round-trip time against the **speed-of-light floor** — the minimum time a photon could travel between the claimed endpoint and the server, given the geodesic distance and fiber refraction index.

No amount of software tuning can make a packet travel faster than light. A measured RTT below the theoretical minimum is a physical impossibility, and therefore a conclusive indicator that the declared location is false.

<AccordionGroup>
  <Accordion title="Key signals">
    | Signal ID              | Tier        | Description                                                                                                          |
    | ---------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------- |
    | `geo.rtt-below-vacuum` | composite   | Measured RTT is below the speed-of-light floor for the claimed location. Example: *RTT 2.1 ms; light needs 27.4 ms.* |
    | `geo.rtt-implausible`  | conditional | RTT is physically possible but statistically inconsistent with the declared city or region.                          |
  </Accordion>
</AccordionGroup>

***

## transport-stack

**Family ID:** `transport-stack`

Transport stack fingerprints the TCP options, SYN flags, window sizes, and QUIC reachability of the incoming connection. Every operating system kernel has a characteristic TCP/TLS handshake structure that is difficult to spoof from userland. If the kernel's SYN packet identifies a Linux 5.x network stack but the client declares macOS 15, something is misrepresenting itself.

<AccordionGroup>
  <Accordion title="Key signals">
    | Signal ID                     | Tier      | Description                                                                                         |
    | ----------------------------- | --------- | --------------------------------------------------------------------------------------------------- |
    | `stack.os-contradiction`      | composite | Kernel TCP fingerprint contradicts the claimed OS. Example: *SYN by Linux 5.x; UA claims macOS 15.* |
    | `reach.no-quic-attempt`       | composite | No QUIC connection attempt observed despite a browser that claims full QUIC support.                |
    | `stack.window-scale-mismatch` | weak      | TCP window scaling value inconsistent with claimed OS defaults.                                     |
  </Accordion>
</AccordionGroup>

***

## tls-construction

**Family ID:** `tls-construction`

TLS construction inspects the structure of the TLS `ClientHello`: the cipher suite ordering, supported groups (elliptic curves), signature algorithm list, and extension layout. Each TLS library — BoringSSL, NSS, OpenSSL, the Windows SChannel — produces a characteristic fingerprint. A `ClientHello` assembled by a headless automation library looks different from one produced by a genuine Chrome browser, even if the User-Agent string matches.

<AccordionGroup>
  <Accordion title="Key signals">
    | Signal ID                   | Tier        | Description                                                                                         |
    | --------------------------- | ----------- | --------------------------------------------------------------------------------------------------- |
    | `tls.group-disagreement`    | composite   | Supported group list is inconsistent with the TLS library implied by the declared browser version.  |
    | `tls.cipher-order-mismatch` | composite   | Cipher suite ordering matches a known automation framework rather than the declared browser.        |
    | `tls.extension-absent`      | conditional | A TLS extension universally present in the claimed browser version is missing from the ClientHello. |
  </Accordion>
</AccordionGroup>

***

## compute

**Family ID:** `compute`

Compute probes CPU characteristics: model corpus matching, core count claims versus measured parallelism throughput, and timing resolution. A client that declares an 8-core desktop CPU but can only execute tasks at 2-thread throughput is either running in a constrained VM or misrepresenting its hardware.

<AccordionGroup>
  <Accordion title="Key signals">
    | Signal ID                           | Tier        | Description                                                                                         |
    | ----------------------------------- | ----------- | --------------------------------------------------------------------------------------------------- |
    | `compute.cores-exceed-claim`        | composite   | Measured parallel throughput exceeds what the declared core count could produce.                    |
    | `compute.cores-below-claim`         | conditional | Measured throughput is significantly lower than the declared core count implies.                    |
    | `compute.timing-resolution-clamped` | weak        | `performance.now()` resolution is clamped beyond spec, consistent with automation sandbox settings. |
  </Accordion>
</AccordionGroup>

***

## render

**Family ID:** `render`

Render probes the GPU, canvas rasterization, WebGL renderer string, audio processing pipeline, parallel execution timing, and frame delivery cadence. Real GPUs produce characteristic rendering outputs — software rasterizers (SwiftShader, llvmpipe) produce different pixel hashes and timing profiles. Frame timing irregularities reveal headless environments that lack a real display compositor.

<AccordionGroup>
  <Accordion title="Key signals">
    | Signal ID                         | Tier        | Description                                                                                                                |
    | --------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- |
    | `render.software-rasterizer`      | composite   | Canvas or WebGL output matches a known software renderer rather than the declared GPU.                                     |
    | `identity.same-origin-cluster`    | conditional | Session fingerprint clusters with other sessions sharing the same apparent origin, consistent with coordinated automation. |
    | `render.frame-timing-irregular`   | conditional | Frame delivery cadence inconsistent with a real display compositor.                                                        |
    | `render.audio-fingerprint-absent` | weak        | Audio context produces no meaningful fingerprint, consistent with a muted headless environment.                            |
  </Accordion>
</AccordionGroup>

<Note>
  You can disable device fingerprinting by passing `render: false` to the collector options. This removes the render family from the session entirely, which eliminates canvas and audio probes. You lose the `render` clustering signal and any composite corroboration it would have contributed. Use this option only when your privacy requirements explicitly prohibit device fingerprinting.
</Note>

***

## declared

**Family ID:** `declared`

The declared family reads the values the browser exposes directly: `navigator`, `screen`, `Intl`, `userAgentData`, and WebGL renderer strings. These values are **never treated as ground truth**. Heretic reads them only as claims — inputs against which the other five families test for contradiction.

<AccordionGroup>
  <Accordion title="What is read">
    | Source          | Values captured                                                                         |
    | --------------- | --------------------------------------------------------------------------------------- |
    | `navigator`     | `userAgent`, `platform`, `hardwareConcurrency`, `deviceMemory`, `language`, `languages` |
    | `screen`        | `width`, `height`, `colorDepth`, `pixelDepth`                                           |
    | `Intl`          | `timeZone`, locale preference list                                                      |
    | `userAgentData` | `platform`, `brands`, `mobile`, `architecture`                                          |
    | WebGL           | `RENDERER`, `VENDOR`, `VERSION` strings                                                 |
  </Accordion>
</AccordionGroup>

<Warning>
  The declared family never produces signals on its own. A suspicious `navigator.platform` value is only meaningful when it contradicts a transport-stack or compute signal. If Heretic only has declared data — because the collector was blocked from running its probes — the verdict will be `insufficient`.
</Warning>

<Tip>
  Read [Evidence Families in verdicts](/concepts/verdicts#the-contradicting_families-field) to see how `contradicting_families` tells you exactly which families produced the contradicting signals in a given session.
</Tip>


## Related topics

- [Heretic: Physics-Based Browser Intelligence Platform](/introduction.md)
- [Signal Tiers, Ruling Algebra, and Enforcement Policy](/concepts/signal-tiers.md)
- [How Heretic Measures Browser Integrity with Physics](/how-it-works.md)
- [Heretic FAQ: Integration, Verdicts, Privacy, and Access](/reference/faq.md)
- [Heretic Signal Reference: IDs, Evidence Families, and Tiers](/reference/signals.md)
