# Session privacy and retention

Gray’s risk API is session defense, not device identification.

## Data minimization

The runtime may reduce a request to these coarse, optional categories:

- IPv4 `/24` or IPv6 `/48` network-prefix change;
- browser-family change such as Chromium to Firefox;
- broad TLS/HTTP/Fetch-Metadata/compression capability change;
- excessive use within one bounded window;
- overlapping use of one session by concurrent request handlers;
- use through a recently replaced identifier; and
- privilege-sensitive activity without sufficiently recent authentication.

Only HMAC-SHA-256 outputs under `GRAY_SESSION_RISK_KEYS` enter encrypted
session state. The HMAC input includes the application context. Raw addresses,
User-Agent strings, header sets, fonts, canvas data, hardware properties, and
cross-site identifiers are not retained.

| Signal | Defensive purpose | Retention | Disable key |
|---|---|---|---|
| Coarse network change | Suggest step-up after a broad network move without treating it as identity. | HMAC baseline deadline | `network` |
| Browser-family change | Surface a large client-family transition. | HMAC baseline deadline | `user_agent` |
| Broad capability change | Surface a material protocol-capability transition. | HMAC baseline deadline | `capability` |
| Activity burst | Bound unusually dense use of one session. | 1–60 second counter window | `activity` |
| Concurrent use | Surface overlapping request handlers sharing one session. | Current request only; no client data stored | `concurrent_use` |
| Rotated identifier reuse | Advise on legitimate use inside the remaining grace window. | Current request only | `rotated_identifier_reuse` |
| Privilege without recent authentication | Request a visible step-up for sensitive work. | Current request plus monotonic authentication age | `privilege_sensitive` |

## Retention

`retention_ms` defaults to 24 hours and is limited to one minute through seven
days. When the deadline passes, the complete baseline resets. Activity windows
are limited to one through 60 seconds and counters are capped.

Applications may independently disable `network`, `user_agent`, `capability`,
`activity`, `rotated_identifier_reuse`, or `privilege_sensitive`. Disabling
activity also clears its retained window and counter. Concurrent-request
advice is independently controlled by `concurrent_use` and stores no client
attribute. Choose the shortest retention that supports a documented
application purpose.

Invalid generation transitions and exhausted retired-token grace are
fail-closed lifecycle violations rather than optional risk scores. They are
rejected before application policy runs and emit only aggregate, redacted
evidence.

## Decisions and fairness

A network-prefix change contributes 15 points and therefore remains `allow`
under the default policy. It never destroys a session by itself. Browser
family and capability changes are advisory. Applications choose whether to
allow, rotate, challenge, reauthenticate, or deny after considering their own
context.

Mobile networks, travel, VPNs, carrier NAT, browser updates, accessibility
tools, and privacy software can change coarse signals. A score is not proof of
abuse or identity. Provide a usable recovery and step-up path, and do not make
high-impact decisions from this signal alone.

## Observability retention

The in-process flight recorder contains at most 512 enum-only events and is
lost at process exit. Prometheus metrics contain aggregate counters and one
gauge without session-, account-, route-, address-, User-Agent-, or
risk-reason labels. If an application exports events elsewhere, it owns the
external retention policy and must preserve the same redaction boundary.
