Standard enterprise hygiene, run carefully.

Most of the security work on a platform of this kind is standard. Encryption at rest. Encryption in transit. Secrets scoped to single workers. Keys isolated per environment. A documented incident response procedure. A responsible disclosure program. None of it is novel. The work is in doing each piece carefully, with fail-closed defaults, and with no development bypasses.

This page describes how each piece is implemented. The full enforcement matrix lives in the engineering security document; this version is what you need to read to brief a security team.

[ 01 ]  ·  NAMED: ENCRYPTION

At rest. In transit. Per-environment keys.

All object storage (Cloudflare R2, AWS S3, on-premise MinIO, and Azure through an S3-compatible endpoint) is encrypted at rest using the platform provider’s default AES-256. All Durable Object and database storage inherits the same default. Inter-worker and worker-to-storage traffic runs over TLS 1.2 or higher, and outbound calls to Anthropic and ElevenLabs negotiate TLS 1.3.

Keys are scoped per environment and per worker. The development environment never shares a key with production, and the data-plane workers never share keys with the operator-plane workers. Each workspace’s credential vault is sealed under a key derived for that workspace alone. For deployments that require customer-managed keys, a KMS integration on the cloud of choice (AWS KMS, Azure Key Vault, or the Cloudflare equivalent) is wired during the engagement.

[ 02 ]  ·  NAMED: TENANT-SCOPED SECRETS

One worker holds one secret.

Every secret lives in exactly one worker. There are no shared HMAC keys, no copied bearer tokens, no cross-environment reuse. The ingestion worker holds the webhook signing secret. The operations worker holds the admin bearer secret. The engine worker holds the LLM API key. The query worker holds the read-side bearer secret. The canvas worker holds the matrix mutation secret.

Workers that need to talk to each other use Cloudflare service bindings (or the equivalent on AWS, Azure, on premise). Service bindings carry the caller’s identity natively. There is no shared signing key copied across workers. Compromising one worker’s secret does not cascade into another worker’s blast radius.

Workers fail closed when a required secret is absent at startup. The worker comes up, refuses to serve, and logs the missing-secret name. There is no fallback path that quietly serves with a default credential.

[ 03 ]  ·  NAMED: FAIL-CLOSED CHECKS

Every boundary denies when uncertain.

The platform locks before it leaks. The fail-closed checklist is enforced on every worker, with no exceptions in development or staging:

  • Webhook HMAC signature on every inbound webhook. Missing or wrong signature returns 401 with no body read and no storage write.
  • Bearer token on every operator API call. Missing, malformed, or revoked token returns 401 with no downstream call issued.
  • Role gate on every authenticated route. Valid token plus wrong role returns 403.
  • Matrix ownership check on every canvas mutation. The caller must be the matrix owner; otherwise 403. The same fail-closed posture covers the canvas surface as it ships.
  • Token budget check before every LLM call. Over budget returns a budget-exceeded lineage row and no call.
  • Prompt hash check before every enrichment call. A prompt-template mismatch fails closed with a prompt_drift lineage row. No silent edits to deployed prompts.
  • Output schema validation on every LLM response. Non-validating output fails closed; the raw response is preserved in the result blob for forensics.

If a developer ever wants a “skip auth for local testing” flag, that is the moment we ship a vulnerability. The dev environment uses a separate secret with the same enforcement.

[ 04 ]  ·  NAMED: TENANCY IN THE TYPE SYSTEM

The scope key is mandatory at the type level.

Every query method on the read API requires its scope key (matrix identifier, organization identifier) as a typed positional argument. Omitting it is a TypeScript compile error. It is checked at build time, before runtime authorization gets a chance.

Every HTTP route carries the scope key in the path itself. The handler signature requires it. There is no “list everything” route where a tenant filter could be silently dropped. When the platform adds a second organization scope (current deployments are single-organization), the compile error catches every place that needs to update.

[ 05 ]  ·  NAMED: AUDIT TRAIL AS DEFAULT STATE

The system is the audit log.

Every state-changing operation already writes to an append-only store. Webhook ingest writes to the datalake index. Canvas edits write a new plan version blob with the prior version retained. Engine envelopes write a lineage row for every LLM call: model identifier, token counts, duration, status, and a pointer to the result blob. Budget spend increments a counter row.

There is no separate “audit log” feature because the entire system is the audit log. An operator investigating an incident queries the existing tables. The answers are already there. There is no row-deletion path in the platform. Consent revocation is handled by a tombstone that blocks access to a conversation rather than erasing history, so the record of what happened stays intact and tamper-evident.

[ 06 ]  ·  NAMED: INCIDENT RESPONSE

A documented procedure with a named on-call.

Incidents are paged to a named on-call. The procedure has five steps: confirm the incident, freeze affected credentials, snapshot the affected state from the append-only stores, identify the blast radius from the lineage rows, and run the remediation. The runbook is published with the engagement.

Customer notification is bound by contract. For a confirmed data incident affecting respondent data, we notify the customer within 24 hours of confirmation. The notification includes the timestamps of compromise, the blast radius, the remediation taken, and the audit trail we used to establish those facts.

A post-incident review is shared in writing within ten business days. The review names the root cause, the architectural change that prevents recurrence, and the verification we ran to confirm the change holds.

[ 07 ]  ·  NAMED: RESPONSIBLE DISCLOSURE

Researchers report; we respond.

Security researchers who find a vulnerability can report it to security@nexaintel.ai. We acknowledge within two business days. We commit to a fix or a documented mitigation timeline within fifteen business days for high-severity issues, thirty business days for medium-severity. We credit the researcher in the advisory unless they prefer anonymity.

We do not pursue legal action against good-faith research that follows the disclosure timeline. We do reserve the right to delay public disclosure until the affected deployments are patched.

[ 08 ]  ·  NAMED: WHERE ATTESTATION LIVES

Built to the controls. Run on your certified infrastructure.

The platform is built to the control requirements that HIPAA, SOC 2 Type II, Loi 25 Quebec, and GDPR examine. The architecture supplies the substrate for those controls: in-tenant deployment, no-training and no-retention arrangements with the LLM and voice partners, the append-only audit trail, the tombstone mechanism for consent revocation, and region placement set per deployment.

In an in-tenant deployment the certifications that matter belong to your infrastructure. The platform runs inside the cloud account you already had audited, so your SOC 2, HIPAA, or regional attestation covers it the same way it covers everything else you run. For buyers who want help, a managed deployment is available where Nexa operates more of the stack under contract.

The subprocessor attestations (Cloudflare, Anthropic, ElevenLabs), our DPA, the subprocessor list, and a current security questionnaire are available under NDA through . For an in-tenant deployment, your team assesses the platform against your own framework.