Trust

Trust isn't a checklist. It's what's in the source.

Every claim on this page corresponds to code we run today. Where a control does not yet exist, §06 says so explicitly.

01 / What we claim · with the code-grounded fact

Six controls that already exist in the running platform.

Each card states a control plus the one specific fact about it that you can verify against the source if you become a design partner.

Tamper-evident audit log

previous_hash → entry_hash

Every audit row carries the hash of the previous row plus its own. Twenty-plus event types — reads, writes, deletes, logins, customer-data access, config changes, flow execution. Append-only by convention: only INSERT and SELECT, never UPDATE. Default retention 7 years (the SOC 2 minimum); auditors don’t wait on us — every tenant queries its own audit history through GET /admin/compliance/audit.

Application-layer key encryption

AES-256-GCM · key outside DB

Customer API credentials are encrypted at the application layer with AES-256-GCM. The encryption key is a deployment-held secret, kept outside the database. Plaintext is zeroized on drop. Other data relies on storage-layer encryption — see §04 for the honest two-tier picture.

Logical multi-tenant isolation

WHERE client_id = $1

Every data query is scoped by client_id at the query layer. RBAC middleware extracts the client id from the request path and validates it against the JWT claims before the handler runs — a token issued for tenant A cannot read tenant B’s data even if the path is forged. Logical isolation in a shared database; physical separation available on request.

Configurable retention with scheduled purges

data_retention_policies

Per-tenant retention windows in data_retention_policies. A RetentionEnforcer actually runs scheduled purges (interval and batch size both configurable), so retention isn’t just a written policy — it’s enforced. Defaults seeded conservatively; every row is overridable. Full table in §03.

GDPR Article 15 + 17, real handlers

/dsar · /erasure

Subject access request (Article 15) exports cases, interactions, emails, voice calls, auto-response log, and audit entries. Erasure (Article 17) anonymizes by SHA-256 hash replacement of email, phone, and name in a single transaction. Both endpoints are SuperAdmin-only and write an audit row of their own.

JWT auth, configurable

HS256 / RS256 · default 24h

JWT auth with HS256 (RS256 also supported), default 24-hour expiry, configurable per environment. Audience is configured per environment, not per tenant. Rate limits are configurable per API client and per dashboard user.

02 / Audit trail · the hash chain

Every audit row carries the hash of the previous row. A single tampered entry breaks the chain.

Auditors don't have to wait on us to pull a report — every tenant queries its own audit history through GET /admin/compliance/audit.

Representative event categories · all per-tenant queryable

DataReadDataWriteLoginFailedConfigChangedCustomerDataAccessedCustomerDataExported

Six categories shown. Full event taxonomy (~25 types covering data access, identity, configuration, customer-data lifecycle, and security signals) is provided to design partners under NDA.

03 / Data lifecycle · retention & subject rights

Every default below is configurable per tenant.

Defaults are seeded into data_retention_policies on tenant provision. Override any row through the admin API or console; RetentionEnforcer picks up changes on its next run.

Voice calls (records)365 daysCall metadata and case-linked records.
Recordings (audio)90 daysShorter than the call record itself; tunable by tenant policy.
Transcripts365 daysFull-fidelity text. PII is not redacted today — see §06.
Email threads730 daysInbound and outbound, linked to the case spine.
Audit log2,555 days7 years — the SOC 2 minimum. Lower allowed; higher allowed.

GDPR Article 15 · Subject access

Exports the subject's cases, interactions, emails, voice calls, auto-response log entries, and audit trail. SuperAdmin-only. The export itself writes a CustomerDataExported audit row.

GDPR Article 17 · Erasure

Anonymizes by SHA-256 hash replacement of email, phone, and name. Wrapped in a single transaction so a partial failure rolls back. SuperAdmin-only; writes a CustomerDataDeleted audit row.

04 / Encryption · the honest two-tier picture

We don't say "all data encrypted at rest." Here's what we actually do.

"Encryption at rest" is the most over-claimed control on every Trust page on the internet. Here are the two tiers we run and exactly which data sits in each.

Tier 1 · application-layer AES-256-GCM

API credentials only

Rows in client_api_credentials are encrypted in our application before they hit the database. The encryption key is a deployment-held secret — it lives outside the database, not in any column.

  • ·Algorithm: AES-256-GCM
  • ·Key location: deployment-held secret, outside the database
  • ·Plaintext zeroized on drop

Tier 2 · storage-layer (TDE / SSE)

Everything else

Transcripts, recording URLs, email bodies, audit rows, case data — protected by whatever your storage layer provides (database TDE, object-store SSE, etc). Our application doesn’t add a second layer on top.

  • ·Database TDE / object-store SSE per deployment
  • ·No application-side double encryption
  • ·BYOK / KMS-backed customer keys: roadmap, not today (§06)
05 / Subprocessors · published

We publish the list. No surprises during procurement.

Most tenants will only touch the default-tier providers. Premium providers are gated by API-key configuration; if a key isn't set, the provider isn't called.

We publish the full subprocessor list — vendors, regions, data-flow diagrams — to design partners under NDA. The shape, in plain prose:

  • Language model

    Managed LLM provider with a self-hosted fallback. Active route is a deployment-held config, not a per-tenant choice.

  • Speech

    Self-hosted STT and TTS by default. Optional premium SaaS providers for either side, gated by API-key configuration.

  • Email

    OAuth-integrated Google and Microsoft. Customer-provided IMAP/SMTP also supported — that mailbox isn’t our subprocessor in the GDPR sense.

  • Recording, telephony, observability

    Deployment-managed. Provider choice depends on the engagement; we adapt rather than mandate.

DPA negotiated per engagement during pilot onboarding. Drop a line and we'll send the current draft.

06 / What we don't claim · the honest list

Where a control doesn't exist yet, we say so explicitly.

These are the things we deliberately do not claim today. If any of them are blocking for your security review, that's a real conversation worth having before pilot.

  • No certifications today

    No active audit in flight. We’ll say something here when there’s something honest to say.

  • PII not auto-redacted

    Customer email, phone, and booking ref are stored in plaintext under audit and transcript surfaces. Configurable redaction is on the roadmap.

  • TLS minimum version not pinned in app

    TLS is terminated at the deployment layer. We don’t pin a minimum version in application code; the operational answer depends on the reverse proxy your deployment runs.

  • No verified end-to-end 2FA flow

    Two-factor enrolment isn’t surfaced as a verified end-to-end flow today. We’d rather omit it than claim a control we can’t yet point at in full.

  • No account lockout / IP rate-bucketing

    Per-user and per-API-client rate limits exist (§01.06). Account lockout after failed logins, IP-bucket rate limiting, and behavioural anomaly detection are not implemented today.

  • No customer-managed keys

    Application-layer encryption uses our deployment-held key. BYOK / KMS-backed customer keys are on the roadmap; not in production today.

  • No third-party pen test report

    No third-party pen test report to share today. When that changes we’ll publish the executive summary here.

  • Single region deployed today

    Deployed in eu-west today; additional regions on request. Note that egress to LLM, STT and TTS providers can cross regions depending on configuration — operational, not code-grounded.