Skip to content

Security architecture

Venturi’s security architecture is designed around one principle: a tool that sees your AI traffic must be incapable of harming you with that visibility. This page describes the trust boundary, the read-only integration model, encryption, secrets management, the fail-open guarantee, and the threat model: the controls a security reviewer evaluates before deployment.

The trust boundary

Venturi’s data plane (the decision-time interceptor, attribution processor, attribution store, and serving APIs) is dedicated to one tenant. In self-hosted mode it deploys in your cloud account; in SaaS mode Venturi operates it in the residency lane contracted during onboarding. Operational data stays inside that dedicated tenant boundary and is never pooled with another tenant.

The interceptor, processor, attribution store, and serving API all sit inside the dedicated tenant boundary. The shared SaaS routing tier sits outside it. The data plane initiates the outbound control-plane fetch; the control plane opens no inbound connection.

From To Traffic or data
Shared SaaS routing tier, in SaaS mode only Tenant decision-time interceptor Proxied calls, bound to the tenant from the request credential.
Shared SaaS routing tier, in SaaS mode only Tenant serving and query API API requests, bound to the tenant from the request credential.
Decision-time interceptor Attribution processor Invocation events for asynchronous attribution.
Attribution processor Per-tenant attribution store Attribution records, encrypted with your KMS key.
Per-tenant attribution store Serving and query API Reads for dashboards and exports.
Dedicated tenant data plane Venturi control plane Outbound-only signed fetches over mTLS. No inbound control-plane connection or raw tenant-data transfer.

SaaS routing tier

In SaaS mode, every request to https://api.venturi.systems (the tenant API, the token endpoint, and the drop-in proxy) first reaches a shared, multi-tenant routing tier in front of each tenant’s dedicated data plane. The tier terminates client TLS behind the tenant-plane edge protection (WAF) and per-tenant rate limits, which are configured separately from the control plane’s. It resolves each request’s tenant from the credential the request carries, never from a tenant identifier in the URL, the request body, or a header: a signed JWT by its tenant_id claim, an API key by a lookup against its stored salted hash, a token request by its registered client_id, and a proxied call by the one-way fingerprint of its provider API key. It then forwards the request to that tenant’s dedicated data plane; a tenant identifier that disagrees with the credential returns 403 TENANT_MISMATCH.

To route, the tier holds salted API-key hashes, client_id registrations, and provider-key fingerprints, never an API key or a provider key itself. Request and response content on a proxied call passes through it in memory only while the call is forwarded and is never written to access logs, error logs, traces, queues, or exception payloads. In self-hosted mode there is no shared routing tier: requests go to your own instance host. See Tenant routing on the SaaS host.

Control-plane connection

The control-plane connection is data-plane initiated. The control plane initiates nothing inbound to your environment and observes none of your transactional data. It exists for three narrow, signed, opt-in functions only:

  • a daily pricing-catalog sync (signed JSON, Ed25519, with a vendored local fallback);
  • a daily software-release check (your own CI/CD pulls the images; there is no auto-update); and
  • opt-in anonymized telemetry (off by default; contains no PII).

Full offline mode is available

Venturi can run with the control plane disconnected entirely. In offline mode you pull signed image and pricing-catalog updates on your own cadence, and Venturi publishes a security-advisory feed so you can prioritize patches. The vendored pricing fallback is bounded and surfaced when it diverges from the live catalog.

This is a hard invariant: per-tenant operational data lives inside the dedicated tenant data plane. The separate control plane receives only signed control traffic and explicitly opted-in de-identified telemetry, never provider credentials or prompt/completion content in plaintext.

Read-only integrations, enforced at three layers

Venturi reads from your systems; it never writes to them. This is not a setting. Provider permissions, connector endpoint restrictions, and CI certification work together. Cloud IAM enforcement applies to cloud-authorized operations; it cannot restrict an external provider bearer key.

Every source-system connector requests read-only scopes or permissions wherever the provider offers them. For example, the GitHub App uses the read-only Metadata, Contents, and organization Members permissions for code-ownership data; the Okta connector uses the okta.users.read, okta.groups.read, and okta.logs.read scopes for identity; and cloud billing uses Cost Explorer and CUR read access. The HRIS poller asserts read-only credentials at construction and refuses to start with write-capable credentials. Where a vendor scope is broader than read-only, such as Salesforce api, the integration user’s permissions enforce the read-only boundary. Where a credential also permits management operations, the connector guide names that wider capability and the independent read-endpoint allowlist. Anthropic reporting can require such an Admin API credential. OpenAI API Platform organization Admin keys support permission selection: enable only the required read permissions, including Usage: Read for usage and cost reporting and Audit Logs Scope: Read when audit logs are selected. Venturi is not authorized to invoke source-system writes, including where a reporting credential has broader native capability (see Provider connectors). See each connector guide for the exact vendor permissions.

The IAM roles attached to Venturi’s workloads contain an explicit Deny on write actions against your source systems and cloud resources. The decision-time interceptor’s service account, for example, denies s3:PutObject, s3:DeleteObject, ec2:*, and iam:*. The Deny does not cover the stores Venturi’s own workloads write: the attribution store inside the dedicated tenant boundary, and the audit bucket in customer object storage, to which Venturi’s writer can only append (see Who holds the audit bucket). The customer cross-account role grants no write permission and is read-only by construction: Cost Explorer, the pricing catalog, the named CUR bucket and prefix, Bedrock model and invocation metadata when enabled, scoped CloudWatch and CloudTrail inventory, and IAM and Organizations inventory (see AWS onboarding). Your own security team reviews the IaC before deployment. Log read access can reach content-bearing records, so scope it to the named log group and review the content-bearing log boundary.

A binding permissions check runs in the platform’s CI gate stack. It rejects source-system write operations, unnecessary native management grants, and a broader reporting credential without independently certified read-only egress. Cloud IAM grants remain read-only. Read-only integration is a frozen system invariant: Venturi cannot invoke source-system writes.

This is a frozen decision

Read-only integration is not a configurable behavior. No flag grants source-system write access. Connector certification checks native permissions against the provider’s supported credential model and rejects unnecessary management grants. If the reporting credential necessarily carries broader capability, certification verifies the dedicated credential boundary and independently restricts egress to GET requests on the documented endpoint allowlist. Missing enforcement evidence fails certification. See Residency & subprocessors for the provider-key model.

Encryption

At rest

  • AES-256 at rest across every resource, using customer-managed KMS keys, one key per tenant (see Tenant isolation). Venturi workloads hold only Decrypt and GenerateDataKey on your key, never ScheduleKeyDeletion.
  • All object storage is encrypted, versioned, and denies non-TLS access. The audit bucket additionally carries S3 Object Lock with a 5-year retention period, in Governance mode by default or Compliance mode where root-resistant retention is required (see Data privacy & retention).
  • Instance and database storage are encrypted: EBS for instance storage, native encryption for Postgres, and at-rest encryption for the event stream.

In transit

  • TLS 1.3 on every service-to-service connection. Internal gRPC traffic uses mutual TLS (mTLS), with each side verifying the other’s SPIFFE identity (X.509-SVID) through a service mesh. Customer-facing REST uses one-way TLS.
  • The data-plane-initiated control-plane path uses mTLS with certificate pinning. A man-in-the-middle attempt fails certificate verification and the data plane refuses the response.
  • Trained attribution-model artifacts are staged by an init container from object storage in your own account before the attribution processor starts, mounted read-only, and hash-verified before they are bound. In SaaS mode, that object storage sits inside your dedicated tenant environment. Artifacts are never fetched over the control-plane connection or on the request path. Verification failure refuses the artifact, falls back to the deterministic baseline, and pages on-call rather than loading an unverified model.

Standards basis: TLS 1.3 (RFC 8446), NIST SP 800-52r2, SPIFFE X.509-SVID, and Ed25519 signatures (RFC 8032) for the signed pricing catalog.

Secrets management & rotation

All secrets (source-system API keys, database credentials, JWT signing keys, and provider admin keys) are stored in a managed secrets store (AWS Secrets Manager, or GCP Secret Manager in GCP-native deployments).

  • Pods retrieve secrets at startup via their workload identity role. Secrets are never written to disk and never appear in pod environment manifests.
  • Database credentials rotate every 90 days via automated rotation. Manually rotated secrets are tracked in an inventory and reviewed quarterly.
  • JWT signing keys are externally managed and rotated, carry a key identifier (kid) to support overlapping-window rotation, and are never generated per-process. Access tokens expire within 60 minutes.
  • Provider admin keys are stored per-tenant, KMS-encrypted, inside your trust boundary. The Venturi control plane never observes a provider admin key in plaintext, and a log-guard rejects any line that would emit one. When you rotate a provider key mid-month, attribution and budget accumulation continue across the rotation boundary with no billing gap.

Cloud onboarding uses no long-lived cloud credentials by default: AWS uses cross-account role assumption with 15-minute sessions, GCP uses Workload Identity Federation with no service-account keys, and Azure uses a federated credential. Three exceptions are explicit:

  • Azure client-secret fallback. If you choose it, the secret has a 90-day TTL and its value is stored in Terraform state even though it is never exposed as an output. Protect that state and hand the secret to Venturi only through the encrypted handoff path.
  • Venturi API keys remain valid until their optional expiry or until you rotate or revoke them. Grant each key only the scopes it needs, set an expiry within your tenant’s maximum, and rotate it on your own schedule; see API keys.
  • SaaS connector credentials are stored as encrypted credential references. Rotate them according to each vendor’s policy.

See No long-lived cloud credentials by default and Rotate & offboard.

The fail-open guarantee

The single most important availability control: a slow, degraded, or unavailable Venturi dependency behind the decision-time interceptor never blocks or degrades your AI traffic.

  • The synchronous decision-time interceptor performs a fast index lookup, not inline model inference, and no graph-database call enters the hot path. It works to a 50 ms P99 end-to-end budget, with 15 ms for its internal calls, bounded by a cooperative timeout against a cumulative deadline. On any exception or timeout, the request is forwarded unmodified and the event is logged with null attribution.
  • Stage B (trained edge-existence inference) runs in-process inside the asynchronous attribution processor, with no separate inference service and no additional process boundary. Each Stage B call has a hard 20 ms wall-clock timeout inside the asynchronous processor’s 100 ms P99 Stage B budget; Stage B never runs on the synchronous interceptor path. A timeout, a missing or invalid model artifact, an invalid output, or a disabled flag sends that call to the deterministic heuristic baseline. Under load, a per-instance cap of 8 in-flight calls and a circuit breaker that opens when the timeout rate exceeds its configured threshold (default: 5% over a 100-call rolling window) do the same. A fail-closed per-edge veto withholds an inferred edge, and calibration drift beyond its bound triggers a non-waivable automatic rollback to the baseline.
  • The heuristic fallback keeps attribution processing flowing. It has no role in forwarding your traffic; the interceptor’s fail-open behavior does that. See System architecture.

Fail-open is not configurable

Fail-open has no feature flag and cannot be disabled. It is a frozen decision, exercised by an invariant test and by a 72-hour sustained-load acceptance run. The decision-time interceptor’s only runtime dependencies are the cache and the event stream; it never reads the attribution graph directly and never depends on the control plane to let your traffic through.

Because of fail-open, the unavailability of a Venturi dependency behind the interceptor never blocks your AI traffic. Venturi’s serving-plane SLO (99.9% over a rolling 28-day window) bounds attribution availability (your dashboards and queries), not the forwarding of your AI traffic. Fail-open cannot cover the endpoint your application sends requests to: with the drop-in proxy, the proxy endpoint’s own reachability is on your request path, and a provider key not registered to your tenant is rejected by tenant admission. See Proxy endpoint reachability for client-side failover. See the fail-open boundary and the engine’s invariants.

Index integrity & freshness

The decision-time interceptor reads only a precomputed attribution index that the processor writes and the interceptor reads (never the other way around). The index carries a freshness timestamp and a maximum-staleness bound; beyond that bound the interceptor emits a null attribution rather than a stale guess. The index freshness objective is P99 ≤ 90 seconds.

Confidence-bounded outputs

Venturi’s outputs are deliberately bounded so financial and governance decisions never rest on false precision:

  • Operational confidence (coper) is policy-capped at 0.95 at materialization. The cap can be lowered by configuration but a value above 0.95 is rejected at startup, and the attribution data structures raise on any value above the cap.
  • Chargeback eligibility includes the 0.80 confidence floor. Chargeback-ready (coper >= 0.80) is a score band, not financial approval. Eligible output state, current evidence, no open dispute or degraded result, reconciliation and finance acceptance also govern publication. Provisional (0.50 <= coper < 0.80) and Estimated (coper < 0.50) attributions remain excluded from chargeback.
  • Unknown is reported as unknown: unknown cost is None, never zero; unknown energy is null, never a fabricated number.

For the full confidence model and how to act on each band, see Confidence and evidence.

Threat model

Venturi maintains a STRIDE-based threat model that maps each principal threat to its control and residual risk. A red-team exercise tests it at least annually and on any change to the attribution or confidence-scoring logic.

Threat Control Residual risk
Compromised control plane reaches inbound Outbound-only architecture; no inbound listener; NAT-only egress; full offline mode Low: no inbound path exists by construction
Model-artifact substitution (MITM / poisoned registry) Artifacts staged from your own object storage by an init container, never over the control-plane connection; artifact hash + signature verified at load; data-plane-initiated control-plane connection over mTLS with certificate pinning; signed-build provenance and SBOM Low
Cross-tenant exfiltration via the query API Per-tenant stores and keys; TENANT_MISMATCH rejection (property-tested); signature-then-tenant-binding on tokens Low
Support-staff access to tenant data Break-glass only: customer-Admin-approved, time-boxed, MFA-gated, audit-logged, customer-notified Low to Medium (human-mediated, audited)
Supply-chain compromise of the pricing catalog Ed25519-signed catalog + vendored local fallback; signature verified before use Low
Credential theft of provider admin keys Keys KMS-encrypted in your boundary; control plane never sees plaintext; log-guard; egress network policy Low
Evidence / feedback poisoning of the learner Feedback authentication; per-update drift bound; calibration re-check with automatic rollback; heuristic-baseline fallback Medium: monitored, auto-fallback
Disputed attribution / override repudiation Append-only audit trail; append-only policy-event writer; pseudonymized actor identifiers Low
Query / ingest API abuse (DoS) Per-tenant quotas and rate limits; processor backpressure; fail-open preserves customer traffic Low
Confidence inflation / ownership spoofing 0.95 cap (rejects higher); 0.80 chargeback floor; per-edge false-high-confidence gate under 1% (non-waivable) Low

The customer-facing API additionally sits behind edge protection (WAF) and per-tenant rate limits, with a documented DDoS posture and an explicit responsibility split between your cloud’s edge and Venturi-configured limits. Malformed events are rejected at the edge of ingest and never partially materialized into the graph.

Supply chain

Every released image carries a signature and a software bill of materials (SBOM); the build verifies provenance (SLSA / NIST SSDF). Dependency and image scanning runs continuously with severity-based remediation SLAs: critical findings remediated within 7 days, high within 30 days. An OSS license inventory with a compatibility allowlist is maintained. Venturi operates a coordinated Vulnerability Disclosure Program. Report privately to security@venturi.systems or through the RFC 9116 security.txt intake; every report becomes a tracked case, and good-faith research is covered by the disclosure and safe-harbor terms. Venturi does not run a paid bug bounty.

Give feedback on this page

Sign in to send feedback. Opens in a new tab.

Copy page details
Docs feedback: Security architecture
Page: https://docs.venturi.systems/security/architecture/