Below is what's shipped in the product today — not a roadmap. Formal third-party certifications (SOC 2 Type II, ISO 27001) are on the audit calendar; the controls behind them already run in production. The full list is below.
Mid-market buyers send security questionnaires. Enterprise buyers send them with deadlines.
The controls they ask about — we've shipped them. TLS encryption in transit, HMAC-signed internal requests, TOTP MFA on admin sign-in (SOC 2 CC6.1), append-only audit logs, training excluded under the business-tier terms of our chat and embedding AI providers, self-serve website-data deletion and CSV export of your leads on every plan, private backend network, 72-hour breach notification. Forward this page to your security team and they'll find the answer they need to most rows on the questionnaire.
What we haven't shipped yet — SOC 2 Type II audit, SSO/SAML, on-prem deployment — is listed openly below. So a deal-blocker shows up before the contract, not after.
Traffic between your visitors, our backend, and AI providers is protected by TLS.
Your data is encrypted at rest. The database and cache live on a LUKS2 volume encrypted with AES-256. Uploaded files live in EU object storage and are encrypted with a key we hold and the storage provider does not keep, so the files are unreadable without us. Customer secrets — API keys, OAuth tokens, integration credentials — get a second layer of AES-256-GCM encryption on top, and off-site backups are encrypted as well.
The chat and embedding AI providers we use exclude training on your content under their business-tier terms, and we do not fine-tune models on your conversations ourselves.
Our API server sits on a private network with no public internet exposure. Outside traffic arrives through our edge, with one exception: the relay that carries a voice call's audio when two browsers fail to connect directly answers on its own public address, and it refuses to relay into private address ranges. The edge forwards to the API, to the servers that hand out the dashboard, staff console and widget files, and to our deployment panel behind its own sign-in — the database, the cache, and the page fetcher behind the API have no public address. What you reach through it is the chat widget's entry point and what a visitor's conversation needs behind it — lead capture, live chat with an operator, and the signalling that sets up a voice call; the routes the customer dashboard and staff console call; signing up, accepting an invitation, and recovering an account; the public plan catalogue and the contact forms on this marketing site; the unsubscribe link at the foot of a follow-up email; the pages you return to after checkout; the callbacks sent back to us by our payment provider and by the services you connect; and the health endpoints that report whether the service is up.
Our service-to-service API calls are signed with a timestamp and a one-time nonce; the rest of the internal traffic — dispatch to the page fetcher, and the database and cache connections — stays on the private network above rather than carrying a signature. Outbound lead webhooks are signed with HMAC-SHA256 using a per-integration secret you can rotate yourself. Your endpoint checks the signature to confirm the payload really came from us — the same approach Stripe, GitHub, and Slack use.
Device fingerprinting, server-signed tokens, and layered rate limits shut down scraping and automated abuse. Prompt-injection guardrails keep your agent from being talked into going off-script or damaging your brand.
Export your captured leads to CSV from the dashboard on every plan — your leads are yours, there is no tier gate on getting them out. Downloading the analytics overview as its own CSV is a Pro-and-up feature. You can also delete a website yourself; for a paid website the deletion takes effect at the end of the paid period and is then held recoverable for a grace period before the records are removed for good, while a website with no payment on record is removed at once. We act as the data processor; you, the website owner, remain the data controller.
When the AI assistant emails a lead on your behalf, it sends under your own display name from our outreach address on a separate sending domain, so a spam complaint about a follow-up is kept off the domain your account mail comes from, as far as mail providers judge the two domains separately — and replies route back to you. That separation is checked before a follow-up email goes out: where it is not in place, follow-up email is paused rather than sent from the main domain. Messages that go out without you reading them first are written only from your own settings, the booking details and a topic chosen by code from a fixed list; the only thing a visitor typed that reaches them is a first name, and only when the name as given holds only letters, spaces, apostrophes and hyphens and its first word has at most one apostrophe or hyphen inside it. Follow-up emails carry a one-click unsubscribe (RFC 8058); opt-outs are scoped to your site alone, are checked before a send on either channel, and do not apply to transactional mail. The text of a follow-up is scrubbed once it has gone out, except its subject line, which the email delivery log keeps for at most the period our Data Retention Policy publishes for that log; deleting the lead removes it sooner.
Sensitive actions — sign-ins, website changes, deletions, payments — are written to an append-only log that records who did it, when, and how it turned out. A database trigger rejects an attempt to modify or delete a record, and the application's own database role holds no update, delete or truncate privilege on the table, so no request reaching the product can alter the trail. Records are kept for the period set out in our Data Retention Policy — searchable for the first part of it, then held in an encrypted archive — and are removed only on that schedule, only once the archive has been written and verified, and not because of an action taken through the product.
When support looks into a reported issue, two server-side layers guard the conversation. The first is a strict allowlist that leaves out financial and business data entirely. The second works on the chat text before it leaves our systems: it masks email addresses written in unaccented Latin letters, telephone numbers written with a country code and a bracketed trunk zero (+44 (0) 20 7946 0958), in national groups (020 7946 0958), in dotted pairs (06.12.34.56.78), as two groups of four digits (2123 4567) or with a slash after the area code (0151/23456789), and card numbers, and it withholds a message that repeats an answer the visitor gave in one of your lead forms during that same chat and that support is not shown; a name, address, phone number or other identifying answer is also looked for word by word, from three characters. Very short answers and small numbers given to your other questions, yes or no answers, the form's own fixed choices and answers given in a different chat are not looked for. A word of a name or other identifying answer written in Chinese, Japanese, Korean or Thai is found even inside a longer run of letters, as names are usually written there, from two characters. What this layer does not recognise reaches the support screen as written, such as a name or a street address written into the chat without a lead form, or a telephone number written as ten digits with no space or separator (4155551234) or in four dotted groups with no plus sign (44.20.7946.0958). The same pattern masking covers logs and error reports. Support access is role-gated and logged, and seeing unmasked content takes a separate, MFA-protected workflow. The diagnostic records a support investigation produces stop being readable a week after they are made, and a daily sweep erases them a month after that, so roughly five weeks is the outer limit rather than a figure we round to.
Every staff account must hold a second factor — a time-based one-time code from an authenticator app (Google Authenticator, 1Password, Authy). It is not an option a member of staff can decline: once the password is accepted, an account with no confirmed factor is held at an enrolment screen, and its requests to our routes are refused except for the three that finish enrolment; only the sign-in library's own routes that read or end that account's own sessions stay open. That check runs as each request arrives rather than once at sign-in, so a half-enrolled account reaches only its own sessions. A code is demanded again before privileged actions, among them acting as a customer (including emergency break-glass access, which is that same path in an audited emergency mode), approving an account recovery, and resetting another staff member's second factor. Codes are verified on the server. Customers can enable the same protection on their own accounts if they want it.
A contractual commitment, written into our Data Processing Agreement: we notify affected customers within 72 hours of becoming aware of a personal data breach. The regulation itself sets no clock here. We are the processor and you are the controller, so GDPR Article 33(2) obliges us to tell you without undue delay and names no deadline; the 72 hours is ours, sized to fit inside the 72 hours Article 33(1) then allows you for reaching your supervisory authority.
Analytics queries are auto-anonymised after 90 days by default; you can set between 7 and 180 days for your site. Chat history is kept only as long as the service needs it. Deleting a paid website takes effect at the end of its paid period, is then held recoverable for a grace period, and only after that is permanent; a website with no payment on record is removed at once.
A SOC 2 Type II programme typically spans more than a year, and a “SOC 2 compliant” claim is only backed by an attestation report. Here's our actual calendar, with the milestones we'll mark as they land.
TLS, audit logs, RBAC, encryption, HMAC, rate limiting, MFA, soft-delete + grace period for paid websites — these controls are built into the product.
Scope: an internal gap analysis against the SOC 2 Trust Service Criteria (CC1-CC9), with documented policies, an evidence collection workflow and training records.
Target: an external auditor is engaged and the observation period begins. Such periods typically run about 6 months of evidence collection across access reviews, change management and incident response.
Target: the audit report is issued and offered under NDA to prospective customers, with re-audits each year after.
Common SIG-Lite / CAIQ topics answered up front so your procurement team doesn't have to email us for the basics. Need something not listed? Drop us a line.
| Topic | Answer |
|---|---|
| TLS versions accepted | Cloudflare-fronted endpoints (the product, not the marketing website). Between a browser and Cloudflare: TLS 1.2 or higher, which is the minimum set on our Cloudflare zone. Between Cloudflare and our servers: TLS 1.2 and 1.3 only, with a ciphersuite policy that follows Mozilla Intermediate (no RC4, no 3DES, AEAD-only). |
| Data at rest | The Postgres database and the cache are encrypted at rest on a LUKS2 / AES-256-XTS volume, auto-unlocked at boot. Uploaded files are held in EU object storage under server-side encryption with a customer-provided key: the key is ours, the storage provider discards it after each write and has no means to decrypt an object without it, and our servers do not hand out a direct link to the storage — downloads are served by our own API, which is what lets the key stay on the server side. Customer secrets (API keys, OAuth tokens, integration credentials, and the webhook destination URL — for Slack/Zapier-style receivers the address is itself the credential) get an extra application-layer wrap with AES-256-GCM, using a versioned envelope that supports key rotation. Off-site backups are encrypted with AES-256 (borg). |
| Audit log retention | Append-only audit table — UPDATE, DELETE and TRUNCATE are blocked by Postgres triggers, and the application's database role is granted no such privilege, so no request reaching the product can alter a record. Retention is set by our published Data Retention Policy (/docs/data-retention): a period online and searchable, then a further period in an encrypted archive, after which the expired partition is dropped — only once that archive has been read back and re-verified, and not on request. CSV export endpoint is gated to platform-admin staff only (SoD-enforced, Support Agent role explicitly rejected) for SOC 2 evidence pulls — customer accounts do not expose this endpoint. |
| Backups + RPO | Two independent paths. On the host, continuous WAL archiving gives point-in-time recovery with a recovery point of about one minute, behind a rolling four-week window of full backups. Off site, AES-256 encrypted archives (borg) ship to isolated storage under a separate account on a roughly six-hourly schedule and are retained 7 daily, 4 weekly and 12 monthly — so a recovery starting from the off-site copy has a recovery point measured in hours, not minutes. Restores are drill-tested end-to-end by restoring a real database from a backup and verifying row counts, not by checking that backup jobs ran — both from a database dump kept on the host and from the off-site copy. The point-in-time path has been restored once, in a drill whose record states no target time and no comparison against production, and a full-region recovery, with a new host provisioned around the restore, has not been timed end to end, which is why the committed recovery time for a full-region loss is listed as planned rather than stated. |
| RTO target | Recovering onto a surviving host takes about an hour: the restore itself is minutes — the database is under half a gigabyte — and the rest is provisioning and verification around it, which we have not timed end to end. We do not publish a committed recovery time for full-region loss: that path has not yet been drill-timed end to end, and we would rather quote no number than an unverified one. If your procurement needs a contractual RTO, that's part of the Custom contract conversation. |
| Incident response SLA | Detection alerting via Sentry + uptime probes, routed to the founder. We do not publish an acknowledgement target: there is no on-call rotation behind one today, so acknowledgement is best-effort by one person rather than a committed response time, and we would rather state that than quote a figure we cannot evidence. A rotation is listed under what we have not shipped yet. A customer whose data a personal data breach reaches is notified without undue delay, and within 72 hours under our Data Processing Agreement. That 72-hour figure is contractual rather than statutory: GDPR Article 33(2) requires a processor to notify its controller without undue delay and fixes no deadline. The 72 hours is the window Article 33(1) then gives you, as controller, to reach your supervisory authority, and we commit to landing inside it. |
| Pentest cadence | Formal third-party pentest not yet engaged — planned alongside the SOC 2 Type II audit window (Q4 2026). Internal threat modelling + secure-by-default code review on privileged code paths today. |
| Authentication factors | Email + password baseline, with optional Google sign-in; TOTP MFA (RFC 6238) is mandatory for every staff role — administrator, support and marketing accounts alike, held in an exhaustive role table so a role added later cannot default to exempt. Enrolment is intercepted before the application: the password is checked, and the account is then held at an enrolment screen with our routes refused except the three that finish enrolment, leaving open only the sign-in library's routes that read or end the account's own sessions. That check is re-evaluated as each request arrives rather than decided once at sign-in. The second factor is demanded again before impersonating a customer (break-glass emergency access is that same path in an audited mode), before approving an account recovery, and before resetting another staff member's second factor. Customer accounts may enable TOTP voluntarily. Password reset via an emailed link (30-minute expiry); only the newest link works, links are stored only as a hash, and completing a reset ends the account's existing sessions and cancels its other outstanding links. Changing the password or ending the account's sessions also cancels outstanding reset links, and the account holder is emailed whenever a password is set, reset or changed. |
| Session management | The session is a record in our own database; what the browser holds is a cookie naming it. That cookie is HttpOnly, so no script on the page can read it, and it is the only session credential a browser is given: no session credential is written to local or session storage and no bearer token is sent, so the dashboard and the admin console authenticate on that cookie alone, with a double-submit CSRF token accompanying state-changing requests. Ending a session deletes the record and marks the account in the same operation, so a cached copy of that session stops being accepted rather than living out its own window. Two sets of windows apply rather than one. A customer session has an absolute lifetime of 7 days and is reaped after 72 hours without activity. A staff session — administrator, support, marketing — is capped at 24 hours from sign-in and 1 hour without activity in that session, the NIST SP 800-63B Rev 4 limits for AAL2, the assurance level that the mandatory second factor on staff accounts places it at. Staff limits are checked as each API request arrives; the routes the sign-in library serves itself sit outside that check and rely on a five-minute sweep and on that library session cache of 30 seconds, so an expired staff session can still reach them for up to five and a half minutes. For a staff session, requests a console starts on its own — in response to a live event, a stream reconnect, a timer, or a check after its live stream drops — carry an X-Automatic-Request header and do not count as activity, alongside its live event stream, an armed health poll, the check that an impersonation session is still open, the live-chat presence heartbeat (the manual availability switch shares that route, so it does not count either) and the notice that a conversation is open on screen; what a person does, and a request a console sends later in such a chain without the mark, still counts. That header can only withhold renewal and does not extend a session. A customer session is renewed by its requests, automatic ones included. Administrator rights, the administrator flag and the wildcard grant, apply only in a session opened in the staff console; the same account signed in at the customer dashboard holds only what a customer could hold. The customer pair is enforced server-side by a sweep that runs at five-minute intervals, so the window actually in force is up to five minutes longer than the figure stated, and up to five and a half minutes longer on the routes the sign-in library serves itself, which also answer from that 30-second session cache; that sweep also ends a staff session left with only its event stream open. We do not force a short idle logout on an open customer tab — a documented decision, not an oversight, for a product that handles no payment-card or health data. Sessions are terminated on logout, on an administrator-forced logout, and when an account is suspended. |
| Webhook signature spec | HMAC-SHA256 over the raw payload; signature in `X-NovixAgent-Signature: sha256=<hex>` header; per-integration shared secret, which you rotate yourself from your own dashboard rather than asking us — a rotation takes effect at once, so deliveries after it are signed with the new secret and your receiver has to be updated in the same window. Outbound deliveries also carry `X-NovixAgent-Timestamp`, and the signed string is `<timestamp>.<body>`, so a replayed body is not valid with a fresh timestamp — receivers reject replays older than their own tolerance window, recommended ≤ 5 minutes (industry default). An attempt also carries `X-NovixAgent-Webhook-Id`, a fresh UUID for that attempt — a retry of the same delivery arrives with a new one, so de-duplicate on the payload rather than on that header. Implementation guide at /integrations/webhooks. |
| Sub-processor data minimisation | Chat inference (OpenAI / Gemini / Anthropic / Cohere / Speechify) receives the request payload, and on a customer's site personal data only where the visitor wrote it into the conversation. Four disclosures go beyond that by design, and we name them rather than average them away: our own in-product help assistant, which is not mounted on a customer's site, also sends the signed-in user's name, email address and account identifier to the model that answers; the higher-tier document reader sends an uploaded file itself to Gemini; where outbound follow-ups are switched on, the lead's first name and the topic of the enquiry go to the model that writes the message, and for an appointment reminder also the booking details and the host's name; and outbound AI calling sends the lead's phone number to Retell. Stripe sees payment metadata only, not chat content. The full recipient list is on /security, and the dated version with data categories is in the Privacy Policy. |
| Website data deletion | Self-service website deletion in the dashboard. For a paid website with a running subscription the deletion is scheduled for the end of the paid period; a paid website is then soft-deleted with a grace period for accidental-deletion recovery (at once when its subscription has already ended), and a hard-delete cron removes its records permanently after grace; a website with no payment on record is hard-deleted when the deletion is confirmed. Its length is published in our Data Retention Policy (/docs/data-retention) rather than restated here. Audit row written for both events. |
| AI follow-up email — unsubscribe & content retention | The assistant's proactive follow-up emails (cold-lead nudges and email appointment reminders) ship RFC 8058 one-click unsubscribe — List-Unsubscribe and List-Unsubscribe-Post headers plus a visible footer link. Opt-outs are recorded per (website, recipient email) and checked before an outbound send on either channel, so an opt-out also suppresses a WhatsApp reminder to the same lead; they are not applied to transactional mail. The WhatsApp reminder itself carries no unsubscribe link — WhatsApp has no equivalent header, and the message is a Meta-approved utility template for an appointment the recipient booked. Follow-up subject and body are nulled on the follow-up record once sent and purged from unsent drafts after a 30-day retention window. The subject line is also written to the email delivery log with the send event, and stays there for at most the period the Data Retention Policy (/docs/data-retention) publishes for that log, and is removed sooner when the lead is deleted; the body is not. The durable record is that logged send event, plus the owner's BCC copy unless the owner has switched that copy off. |
Vulnerability reports: see /.well-known/security.txt (RFC 9116).

Three commitments we put in writing — so an incident reaches you from a named person with the context and the authority to fix it, rather than from a ticket queue:
This is the complete list, not a selection. Under our Data Processing Agreement we impose the same data-protection obligations, by contract, on the providers we engage. Where the list says you connect, the account is yours and that provider's agreement with you governs the processing; where it says you designate, you supply the address, so the recipient is not named here in advance. The dated version, with the data categories each one receives, is in the Privacy Policy.
Other vendors list SOC 2, ISO 27001, SSO, self-hosting and multi-region residency as if they were check-boxes — in reality, most are multi-year programmes with third-party audits. We'd rather be straight about which controls run in production today and which are on the audit calendar.
Deal-blocker for you? Tell us — we'd rather know now than after you've signed.
Send us your security questionnaire and we will answer it.