Skip to content

Data handling ​

This page is the data inventory your security, compliance, and data-protection teams need before deploying Opsta AI Gateway. It answers: what is stored, where, at what classification, for how long, and what controls exist. It also states the product's current gaps honestly — see the Shared responsibility matrix for the maturity column.

Who this is for

Data protection officers, security architects, and compliance teams. Read alongside Data sovereignty (residency + air-gap) and Audit & compliance (audit log detail).


Data inventory ​

PostgreSQL — source of truth ​

Managed by CloudNativePG. Contains everything the control plane owns.

Table / dataClassificationWhat's thereRetention
orgs, projects, membersConfidentialOrganisation names, project names, member email addressesUntil deleted
providersConfidentialProvider name, endpoint, model list (no key material — keys are in Kubernetes Secrets)Until deleted
api_keysConfidentialHMAC hash of key + metadata (project, user, label, budget); raw key material is never storedUntil revoked
budgets, usage_ledgerInternalUSD budgets, per-key token counters, billing ledgerUntil deleted / reset
audit_logConfidentialAdmin action log — who changed what and when (org/project/provider/key mutations)Configurable (audit.retentionDays, default 365 days); pruned daily
guardrail_blocksSensitivePer-block record: consumer identity, org/project, timestamp, which gate denied, matched rule, and a ≤280-character excerpt of the offending request contentConfigurable (audit.retentionDays, same setting, default 365 days); pruned daily
guardrail_rulesConfidentialGuardrail patterns configured by org adminsUntil deleted
routing_rules, provider_keys, canary_rules, mcp_servers, prompt_templatesConfidentialConfiguration objectsUntil deleted

Guardrail-block snippets (G4)

The guardrail_blocks.snippet column stores up to 280 characters of the request content that triggered a guardrail block. This excerpt may contain the sensitive text the guardrail was meant to catch (PII, a prompt-injection attempt, confidential content). Treat guardrail_blocks as a sensitive table and apply appropriate access controls, backup encryption, and retention discipline.

What to do:

  • Reduce retention — set audit.retentionDays to a shorter window (e.g. 90 days) if you do not need long-term forensics on blocked content.
  • Restrict access — the table is in the same database as the rest of the control-plane schema; it is not exposed externally, but database-level access (e.g. psql as the opsta role) can read it. Scope database access accordingly.
  • Disable the snippet — this is not yet a first-class config knob; it is a planned roadmap item. In the interim, a post-migration SQL trigger or a custom CNPG hook can zero out the column on insert if your policy requires it. Contact Opsta support for guidance.

Kubernetes Secrets ​

Created by the chart and operators. Standard Kubernetes Secrets (base64-encoded, not encrypted at rest unless you add etcd encryption or an external-secrets/KMS integration).

SecretWhat's in itMounted by
provider-keys-<org>LLM provider API keys for each orgHigress gateway (Wasm plugin)
idp-secrets-<org>OIDC/SAML client secrets for per-org IdP brokeringKeycloak via control plane
mcp-*MCP server credentialsHigress gateway
opsta-pg-appPostgreSQL connection string (host, user, password, db)Control plane
keycloak-pg-appKeycloak's PostgreSQL connection stringKeycloak
Session / CSRF secretsWeb console session signing keyConsole
TLS cert + keyWildcard TLS certificate (*.<baseDomain>)cert-manager / Higress

Secret encryption at rest (G3)

Kubernetes Secrets are base64-encoded, not encrypted unless your cluster has etcd encryption enabled or you use sealed-secrets / external-secrets. Anyone with cluster-admin access — or raw etcd access — can decode and read the plaintext API keys and IdP credentials.

Customer action required for production:

Native ESO/Vault integration is on the product roadmap. In the interim, any of the above customer-applied controls is sufficient.

Redis — ephemeral quota and cache state ​

Managed by the Opstree Redis operator. Contains transient state only — nothing in Redis is the system of record. All counters are derived from usage events and can be reconstructed on loss.

Key spaceWhat's thereDurability
Quota / rate-limit countersPer-key token-per-minute and USD-balance countersEphemeral — counters reset to the authoritative value from PostgreSQL on the next reconcile
Semantic-cache entriesRequest embedding + response pairs (opt-in)TTL-bounded; cache misses degrade to upstream, not errors

RPO for Redis is effectively N/A — a Redis loss causes a brief enforcement gap (see the FMEA section in Reference architecture), not data loss.

Object store (HA topology only) ​

Used by the LGTM observability stack and (when enabled) Postgres WAL archiving. S3-compatible; you supply and own the bucket.

DataStoreRetention control
Mimir metrics blocksYour S3 bucketmimir.storage.retention (default: configurable)
Loki log chunksYour S3 bucketloki.storage.retention (default: configurable)
Tempo trace blocksYour S3 buckettempo.storage.retention (default: configurable)
PostgreSQL base backups (when enabled)Your S3 bucketCNPG backup schedule + retention policy

The object store is operated by you. Opsta has no access to its contents.


Data classification summary ​

ClassificationDataRequired controls
CriticalProvider API keys, IdP client secrets, TLS private keysetcd encryption or sealed/external secrets; strict RBAC; rotation schedule
SensitiveGuardrail-block snippets (≤280 chars of offending content)Short retention window; database-level access control; encryption at rest
ConfidentialMember emails, org/project names, audit log, usage ledgerBackup encryption; TLS in-transit; access restricted to admin roles
InternalBudget config, routing rules, guardrail patternsStandard access controls
EphemeralRedis counters, semantic cacheNo backup required; loss is a service degradation, not a data loss

Retention controls ​

Audit log and guardrail blocks ​

Both the audit_log and guardrail_blocks tables use the same retention setting, pruned daily:

yaml
# charts/opsta-ai-gateway/values.yaml
audit:
  retentionDays: 365    # default — reduce for guardrail-block privacy

Set audit.retentionDays to your policy requirement (e.g. 90 days for GDPR minimisation, or 730 days if you have a long-term audit obligation).

Observability retention ​

Configure per-signal in the LGTM chart values:

yaml
loki:
  storage:
    retention: 90d      # log chunk retention

mimir:
  # see mimir configuration for compactor retention

tempo:
  storage:
    trace:
      backend: s3
      block_retention: 720h   # 30 days in hours (Go duration)

See Platform observability for full detail.


PII masking (G5 — opt-in) ​

The ai-data-masking Higress plugin can mask PII patterns in request prompts and completion responses before they reach or leave the gateway.

Opt-in — OFF by default

PII masking (guardrails.masking.enabled) is off by default since v1.8.1. The upstream plugin truncates streaming responses that include tool-calls (a known upstream bug in the Wasm plugin's buffering of streaming tool-call frames). Enabling it when your workload uses streaming tool-call responses may drop the tool_calls field.

When to enable: enable masking if your workload does not use streaming tool-calls, or if you need a PII floor and can accept the streaming trade-off.

When not to enable: if your workload uses agentic/tool-use patterns with streaming responses, leave masking off until the upstream bug is fixed (tracked in the Opsta roadmap).

To enable:

yaml
# charts/opsta-ai-gateway/values.yaml (or your values overlay)
guardrails:
  masking:
    enabled: true
    rules:
      - type: replace
        regex: "\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b"
        placeholder: "[EMAIL]"
        restore: false
      # Add more rules as needed

Provider data-in-flight ​

Prompts and completion responses leave your cluster and travel to your configured LLM provider over HTTPS. The gateway is a transparent proxy for the content — it does not store prompt or response bodies (only the guardrail-block snippet, described above).

No-train and zero-data-retention

Whether your provider uses prompt content for model training, or offers a zero-data-retention (ZDR) contract, is governed entirely by your agreement with that provider. Opsta cannot enforce or audit provider-side data handling — you must select providers whose data-handling terms satisfy your policy.

For workloads that must not send data off-premises, configure an on-premises model via Ollama and route to it exclusively. See Supported providers.

Egress endpoints ​

At runtime the gateway makes outbound HTTPS connections to:

  1. Configured LLM providers — endpoints you set per-provider (e.g. api.openai.com, api.anthropic.com). You control the list.
  2. Configured MCP servers — endpoints you set per-MCP-server. You control the list.
  3. Let's Encrypt ACME API — acme-v02.api.letsencrypt.org (only if tls.mode: letsencrypt).
  4. Nothing else. No telemetry to Opsta. No product analytics. No call-home.

In an air-gapped cluster, configure a local CA (tls.mode: provided or selfsigned) and mirror all images — then zero outbound connections are required after installation. See Air-gapped install.


Cross-border and residency ​

Because all stores run in your cluster, data residency follows your cluster. Deploy in the region or data center your legal and compliance requirements specify.

The only cross-border data movement is the request content forwarded to your LLM providers — and that is entirely under your control (choose provider endpoints in the required geography, or use on-premises models).


No external telemetry ​

The platform does not send any of the following to Opsta or any third party:

  • Usage metrics (token counts, request rates)
  • Prompt or response content
  • User or organisation identity
  • Configuration or policy
  • Error logs

All observability data remains in your self-hosted LGTM stack.


Enterprise AI governance, on infrastructure you own.