Compliance
You are the data controller. Most processing runs in your environment, end-point evidence included.
This page covers the GDPR / SOC 2 controls the system ships: the data it stores, the data-subject-request endpoints, retention, and audit trails. It pairs with Security and Data boundary, which own the access and privacy mechanics.
The controller/processor model, the shared-responsibility split, and Anyray's regulatory standing are on the Anyray compliance page. This page documents the shipped controls.
Anyray holds an independent SOC 2 Type I attestation of its own program (as of 6 July 2026), examined by Securance Pro Assurance PLLC against the Security, Availability, and Confidentiality Trust Services Criteria. A SOC 2 Type II examination is in progress. The report is available under NDA; contact security@anyray.ai. The attestation program for your deployment stays yours. Anyray supplies the control inventory and audit evidence to support it.
What data is stored
Most stores below live on your volumes. The Anyray Billing app plane and support bundles you explicitly send live in vendor systems. These vendor-side paths never carry prompt or response content.
| Store | Data | Where |
|---|---|---|
| Spend store | Per-request metadata: user/team, model, provider, tokens, cost, latency. Never content. | Your Postgres (anyray_spend) |
| Connector observations (when configured) | Official vendor usage metadata: timestamps, user/model identifiers, vendor-native quantities, and reported cost. Never prompts, responses, source code, or attachments. Kept separate from request spend. | Your Postgres (anyray_spend_connector_events) |
| Observability traces | Attribution + token/cost/latency metadata; content only per the content mode (ciphertext in encrypted, none in off, raw only in deploy-gated plaintext). | Your Postgres (anyray_traces / anyray_observations) |
| Client keys & enrollment links | Usernames bound to records, with token hashes only (SHA-256) and never raw values. | Gateway data volume |
| Optimizer ephemeral stores | Semantic-cache responses and stashed originals, in memory, TTL-bounded, keyed by content-free hashes. | Optimizer memory |
| Audit logs | Admin/GDPR actions and optimizer settings changes: actor + action + timestamp. Metadata only; the actor is bounded to an identity-shaped value. | Your Postgres (anyray_audit_log); per-pod files as fallback |
| End-point evidence | Internal host and organization IDs, hashed device identifiers, hostname, platform, evidence source, receipt time, policy pass/fail metadata, and bounded remediation audit metadata. Well-formed hostnames are retained verbatim. No users, inventory, arbitrary evidence text, or script output. | Your Postgres, in the endpoint-control service beside the gateway (Anyray sees a content-free rollup only) |
| Anyray Billing app plane | Operator emails/names (Google sign-in), tenant memberships, content-free usage rollups, seat hashes, and the deployment heartbeat (health, counts, database size, error class names, env-var names, never values, content, or user identities). | Vendor Billing backend |
| Support bundles (explicitly pushed) | Only when an admin clicks Send: the redacted, content-free diagnostic bundle plus its analysis. Never automatic, never pullable by Anyray. | Vendor Billing backend (newest 20, 90-day retention) |
Data subject requests
The gateway exposes admin-gated endpoints for erasure and export. All are capability-gated under RBAC (security_admin or owner; the break-glass ANYRAY_ADMIN_TOKEN always works), and each call is itself audit-logged.
Erasure (GDPR Art. 17)
| Store | Endpoint | Removes |
|---|---|---|
| Gateway | delete /admin/gdpr/users/:user | Every spend row, cap counter, client key, and enrollment link for the user (which also cuts their access), plus their trace rows and their rows in the optimizer's context stash (the reversible-trim originals, keyed by the same user attribution). An owner-level request also removes connector observations whose exact attribution.user or userId matches. Returns per-store counts; erasedContextStash is null rather than 0 when that store could not be reached, so a skipped store never reads as an empty one. |
| End-point evidence | Host or organization deletion | Device evidence has no user identity mapping by design, so it is outside a user-scoped erasure. Delete hosts through the gateway's admin API (delete /admin/endpoint/hosts/:id, provisioning:manage); deleting the whole organization cascades to every host and evidence row, through the endpoint-control service's own admin API. The gateway response declares this exclusion. |
| Optimizer | post /admin/optimizer/purge | Drops the whole semantic cache and stash, for every user at once. Per-user stash erasure goes through the gateway endpoint above. |
| Anyray Billing app | delete /portal/me | A portal operator self-erases their account, memberships, and sessions. Refuses (409) if they're a tenant's sole owner. |
Access & portability (GDPR Art. 20)
| Scope | Endpoint | Returns |
|---|---|---|
| Gateway | get /admin/gdpr/users/:user/export | Everything the gateway holds for the user as JSON: spend rows and, for an owner-level request, matching connector observations (all metadata only; content stripped defensively even in plaintext) plus key/link metadata (hashes stripped). The response identifies end-point evidence as excluded because it is not user-attributed. |
| Anyray Billing app | get /portal/me/export | A portal operator's own account data: profile, memberships, and audit-log entries. |
Retention (GDPR Art. 5(1)(e))
Storage limitation is per-store. Only the spend/trace window is a knob you set directly.
| Store | Default | Configurable? |
|---|---|---|
| Spend store | Unset = kept indefinitely (ANYRAY_SPEND_RETENTION_DAYS prunes at boot and daily) | Yes |
| Connector observations | 90 days maximum; a shorter positive ANYRAY_SPEND_RETENTION_DAYS applies. Cleanup continues without active connectors. | No |
| Observability traces | Trace window from the console Privacy page (1–3650 days); unset falls back to ANYRAY_SPEND_RETENTION_DAYS, else 90 days. Never kept indefinitely. | Yes |
| Optimizer cache / stash | In-memory, lost on restart (cache 3600s, stash 4h from each store, extended 30m per retrieval up to a 48h read ceiling; re-storing the same content starts a fresh window); durable stash rows swept hourly | No |
| Optimizer decision pins | Pruned after 30d idle | No |
| Audit logs | Kept indefinitely in Postgres (unpruned by spend retention); fallback files until rotated | Via your Postgres retention |
| End-point evidence | Until explicit host or organization deletion. No automatic age-based purge. | Deletion only: hosts from your own console, the whole organization through the endpoint-control service's admin API |
| Billing app plane | Sessions expire; invites pruned after 90d; usage rollups tiered (30d / 90d / 365d) | ANYRAY_CP_RETENTION_TIERS |
| Support bundles (vendor side) | Newest 20 per deployment, 90d | No |
Audit trails (SOC 2 CC6/CC7)
Every admin mutation is recorded as an append-only, metadata-only event ({ ts, actor, action } plus its category, never content). The actor is the SSO operator's IdP email, or break-glass for anything done with the shared admin key; a value that does not look like an operator identity is stored as unknown rather than verbatim, so an identity field cannot carry free text into the trail. Both the gateway's trails and the optimizer's settings trail are written to the shared spend Postgres (anyray_audit_log), so they're durable across restarts and centralized across replicas; per-pod files under ANYRAY_DATA_DIR are the fallback off Postgres or on a failed append, and they outlive spend rows (compliance evidence).
Covered domains include GDPR/DSAR operations, content-mode changes, client- and provider-key and enrollment-link changes, user caps, routing and model aliases, optimizer config and purges, admin sessions, and the Billing app lifecycle. The access controls behind these trails (admin-token auth, console SSO with RBAC, the auth-failure throttle, and signed sessions) live in Security.