Skip to main content
← Tessera
Trust · Security posture

Security posture

Updated 26 May 2026

Tessera operates a substrate proxy that sits in the LLM request path for AI-native businesses. Every request we proxy carries an Authorization header that gates the customer's upstream provider account; every measurement we ship is the audit-grade record of what the proxy saved. So data minimisation, encryption, and audit immutability are not optional — they are structural properties of the engagement. This page documents what we hold, where, for how long, and the controls protecting it. We do not pretend to compliance certifications we have not yet achieved.

What we proxy (and what we never store)

The proxy path: your application calls api.tesseraai.io/v1/<provider> with two headers — your Tessera key (X-Tessera-Key: tk_…) and your upstream provider Authorization (Authorization: Bearer sk-…). Tessera forwards the request body untouched to the upstream provider (OpenAI, Anthropic, Google, etc.), receives the response, and returns it to you. Seven optimization mechanics may mutate the outgoing request body — auto-route to a cheaper model, inject a provider prompt-cache header, prune long conversation history, enforce a JSON schema, batch-route async-tolerant calls — but only when you have opted that mechanic in per workload.

What we never store at rest: prompt content; response content; end-user personal data; source code; production credentials beyond the bounded settlement-token use described below; any cross-site tracking identifiers.

What we do store at rest: per-request token counts (prompt + completion); per-request cost figures (original_cost_usd at the requested model rate, actual_cost_usd at the routed model rate); the model identifiers; the mechanics stack that fired; provider stop signals (finish_reason); the immutable pricing_snapshot_id active at request time; and any feature_tag / customer_tag string the caller chose to set. Cache mechanics additionally store a sha256 hash of the normalised request body (exact cache) or a 1536-dim embedding of the prompt (semantic cache) — neither shape recovers the original prompt. Cache keys are scoped by {client_id}/{workload_id}/{entry_id} in the worker KV namespace — cache lookup walks only the calling workload's own partition, so cross-tenant cache hit is structurally impossible by namespace design. Cached response bodies live with a default 7-day TTL and are purged automatically.

For async batch arbitrage (M10), the customer's upstream Authorization header is encrypted at rest in vault.secrets via Supabase Vault (XChaCha20-Poly1305 AEAD under the hood) and destroyed on terminal settlement of the batch — typically within 24 hours of dispatch, always within 48.

Where data lives

Operator + sponsor data lives in a single Supabase Postgres project (region us-east-1, project id tyqjsegyhwyrdbfcojaa). The Cloudflare Worker proxy serves api.tesseraai.iofrom Cloudflare's global edge with KV namespaces for cache + API key lookup. Dashboard + ledger.tesseraai.io hosts on Vercel; public landing at tesseraai.iouses no client data. Sentry telemetry routes to the EU region. PostHog product analytics, when a visitor has granted explicit consent, routes to PostHog's regional infrastructure with PII-shaped fields disabled.

The full subprocessor inventory with regions is in the Data Processing Agreement and the Privacy Policy.

Encryption

TLS 1.2+ in transit for every connection — public landing, dashboard, API routes, Supabase, Sentry, Cloudflare edge. AES-256 at rest via Supabase managed encryption for the Postgres database and storage buckets. Authentication tokens (Supabase Auth) are short-lived JWTs with refresh rotation; no plaintext passwords are stored.

Settlement-token encryption(M10 batch arbitrage, migration 0079): the customer's upstream Authorization header is stored as a Supabase Vault secret, encrypted at rest via pgsodium IETF XChaCha20-Poly1305 AEAD with a per-installation key. The key is managed by Supabase Vault under supabase_admin; our application code holds only the UUID reference and reads the decrypted value via SECURITY DEFINER RPC at settlement time. The secret is destroyed on terminal batch transition (completed / failed / expired).

Access control

Row-Level Security is enabled on every Tessera application table. Three policy classes apply:

  • · Operator (Tessera staff with a JWT email present in the operators table) — full read/write across every client, scoped by the application middleware.
  • · Sponsor (client-side authorised contacts in client_users) — SELECT only on their own client's rows, plus permission to toggle their own workload mechanic flags and read their audit ledger. No cross-client visibility, ever.
  • · Anonymous — only public surfaces: /signup-dev form INSERT, Monthly Reading retrieval by share_token, status page. No other table is reachable.

Helper functions is_operator() and sponsor_client_ids() are SECURITY DEFINER with a locked search_path, to prevent RLS recursion from operator policies that themselves read the operators table.

Service-role keys are stored in Vercel encrypted env vars (never committed to git) and are scoped to server-side API routes only — the publishable anon key in the client bundle has no privileged access because RLS treats it as anonymous.

Proxy API key authentication: each customer key (tk_…) is SHA-256 hashed at creation and only the hash is stored. The raw key is shown once at creation in the dashboard; we cannot recover it after that. Customer compromises rotate via key revocation + reissue from the portal.

Audit immutability + provenance

Every per-request measurement row in optimize_savings carries the pricing_snapshot_id that was active at request time. Vendor pricing changes mid-contract do not retroactively alter past savings calculations — historical rows stay locked to their snapshot.

pricing_catalogrows themselves are append-only: a price update closes the prior row's effective_to and inserts a new row with a new pricing_snapshot_id, preserving the full historical chain. Each row carries a confidence score derived from multi-source agreement (LiteLLM model_prices.json, the tokencost library, the OpenRouter API) with 0.99/day recency decay.

audit_events records every state transition on every entity — workload mechanic toggles, balance transactions, anomaly responses, quality-SLA disables and reactivations, settlement transitions. Rows are append-only with an actor identity and a timestamp. The sponsor sees the relevant subset in /portal/audit; the operator sees the full cross-customer view.

A sponsor can export their full audit ledger as CSV any time from /portal/audit. Two engineers, three hours, can re-derive any month's savings figure from the raw inputs.

Prompt fingerprint v1 (anonymized)

Every audit-event row carries a prompt_fingerprint_v1 JSONB column populated by the worker. The fingerprint is anonymized and content-free by construction. It captures the shape of the request, not the request itself.

What it contains:

  • structural_signature — a compressed role-sequence string (e.g. s.u.a/c=1/j=0/t=0/b=2): which roles spoke in what order, whether the prompt contains code fences, whether it contains JSON blocks, whether it carries tool-use, and a coarse turn-count band. Consecutive same-role turns collapse to a single letter so long agent loops bucket uniformly.
  • token_count_band — an integer 1..6 coarsening total token count (≤512, 513-2k, 2k-8k, 8k-32k, 32k-128k, 128k+). A band, not the exact count.
  • embedding_cluster_id— a stable integer 1..N referring to a centroid of historical anonymized prompts. NULL when no cluster has been assigned yet (cluster IDs do not encode any specific customer's data; they encode the shape of the cluster across all opted-in customers).

What it does NOT contain:prompt content; user identifiers; the upstream model's response; any substring of the original request body. The embedding used to derive embedding_cluster_id is computed on the request body in worker memory and discarded after the cluster lookup completes (≤100 ms in-memory residence; never persisted).

What it enables: per-customer prompt-pattern dashboards (you see your own top clusters and their cost / quality profile) and cross-customer aggregation gated by the contributes_to_cross_customer_intelligence opt-in flag. The cross-customer aggregation rules are documented in the Terms of Service §15 (Cross-customer learning) and you can opt out at any time from /portal/settings/privacy.

Versioning: the fingerprint schema is locked at v1. Schema changes that add fields land as additive JSONB keys (safe under the JSONB column shape). Breaking changes require a v2 column on audit_events. Existing rows are never mutated.

Quality SLA — auto-rollback + 10% credit

Every workload runs a daily canary cron at 10% sample rate against the customer's promptfoo eval set. Each sampled request is double-fired (once on the routed model, once on the baseline); both are scored. The aggregate mean-score per mechanics stack must hold ≥ 0.95.

If a stack's mean-score drops below 0.95 for 3 consecutive days with at least 30 samples per stack, that specific stack auto-disables — surgical rollback, not nuclear. E.g. m1+m7 together breaches? m1 alone and m7alone stay live. A service credit on the customer's next monthly bill is applied automatically, with an audit_events row recording the breach + credit + the reactivation path. The customer can re-enable the stack from /portal/anomalies once they believe their eval set or prompt template has been fixed.

A global kill-switch in /portal/settings pauses optimization for an entire client at any time — traffic continues flowing as passthrough, just with no mutation. The kill-switch is contract-codified: we never block its use, never gate it on balance or seat status, never delay its effect beyond next KV refresh (≤ 60s).

Application-error monitoring

Sentry SDK is wired into both the public landing and the dashboard. Before any event leaves the browser or server, a beforeSend hook strips the Authorization and Cookie headers from breadcrumbs. Replays on the dashboard are maskAllText: true and blockAllMedia: true by default, so screenshots captured during error replays cannot leak dashboard contents. Sentry events tunnel through /monitoring(a same-origin proxy) so that browser ad-blockers and corporate firewalls don't drop them.

The Cloudflare Worker proxy reports operational errors to Sentry with explicit field redaction — request and response bodies are never attached to error events; only request_id, provider, model, timing, and the error class.

Product analytics

PostHog product analytics load only after a visitor grants explicit consent through the cookie banner. Until consent is given, no PostHog script is requested and no analytics events fire. The consent decision is stored in localStorage (tessera_analytics_consent) and can be revoked at any time by clearing site data.

We do not use Google Analytics, Facebook Pixel, advertising identifiers, or any cross-site tracking technology.

Personnel

Tessera is a small practice. Access to Controller data is on a need-to-know basis under written confidentiality obligations, with two-factor authentication enforced on every administrative surface (Supabase admin, Vercel, Sentry, Cloudflare). We do not share credentials between team members. Departures trigger immediate revocation of all access on the same business day.

Backups and recovery

Supabase managed automated daily backups with seven-day point-in-time recovery. Retention by class:

  • · optimize_savings, balance_transactions, audit_events, monthly_readings: 7 years per Estonian accounting law (Raamatupidamise seadus § 12) for invoiced engagements; deletable on demand for hobby / free-tier accounts.
  • · cache.RESPONSE_CACHE KV (cached response bodies): default 7-day TTL, auto-purged. Sponsor can flush on demand via portal.
  • · vault.secrets(settlement tokens for M10 batch): destroyed on terminal batch transition, typically < 48h from dispatch.
  • · Sentry breadcrumbs: 90-day rolling retention.
  • · Operator session logs (Supabase Auth): 30-day rolling retention.

Hard-delete on account closure (GDPR right-to-be-forgotten): the operator /clients/[id]/hard-delete surface erases all sponsor data including audit_events, optimize_savings rows, balance_transactions, anonymized hashes, and any vault secrets — completes within one business day. A terminal entry in the operator-side delete log records the deletion timestamp + initiator for our own records.

SOC 2 status and commitment

Honest framing: we are not yet SOC 2 certified. Tessera is an early-stage practice with first paying customers landing in mid-2026. We do not pretend to controls we cannot continuously demonstrate.

Targeted timeline: SOC 2 Type 1 attestation target Q3 2026 (after the first paid-tier billing cycle completes). SOC 2 Type 2 attestation target Q1 2027. Auditor selection will be announced in the Changelog rather than as marketing copy.

What we already operate under as SOC 2 preparation controls:

  • · Bounded attack surface — one Postgres project, two Next.js apps, one Cloudflare Worker, documented subprocessors.
  • · Row-Level Security on every application table.
  • · Encryption at rest (Supabase AES-256 + pgsodium Vault for settlement tokens) and in transit (TLS 1.2+).
  • · Written DPA incorporating SCCs for non-EEA transfers.
  • · 72-hour breach-notification commitment in Section 10 of the DPA.
  • · Append-only audit log on every $ figure.
  • · Client-controlled kill-switch on the request path.
  • · Access review and credential rotation on personnel departure.
  • · The full technical controls listed in the sections above.

For procurement teams requiring attestation evidence ahead of our Type 1 audit, write to contact@tesseraai.io — we share interim controls evidence (architecture diagram, RLS policy matrix, subprocessor inventory, breach-response runbook) under NDA and walk through our posture in a structured vendor- security review.

Reporting a vulnerability

Responsible disclosure policy: /security/disclosure. For active incidents involving client data, write directly to privacy@tesseraai.io — we respond within twenty-four hours.

Vendor-security review

If your procurement process requires a structured security questionnaire, write to contact@tesseraai.io with the questionnaire attached. We complete CAIQ and SIG-Lite forms directly rather than running you through a third-party trust portal we have not built. For short-form vendor security reviews, this page plus the DPA usually answers the standard B2B SaaS questions.