This is a factual, code-grounded description of real security controls, not a certified security posture or a contractual commitment.

Security

Subprocessor register version 1.0.0, effective from 2026-10-05.

Encryption

At rest: third-party API credentials (AI provider keys, data-connector OAuth tokens, SSO and webhook secrets) are sealed with AES-256-GCM under a per-organisation data key, and each data key is itself wrapped by a master key held outside the database. A stolen database dump is not enough to open any of them.

The master key: in production the master key lives in an external key-management service, so the application can ask for a data key to be unwrapped and no human account can. A master key sitting in an environment variable beside the database connection string is the arrangement envelope encryption exists to replace, and the code refuses to start with that configuration in production rather than warning about it.

In transit: this application is designed to run behind HTTPS/TLS. Enforcing that in production (e.g. HSTS, TLS termination, certificate management) is a real deployment/hosting-platform responsibility, not something hard-coded in the application itself — confirm it’s actually configured for any given deployment rather than assuming it.

What this does not mean: at the moment a secret is used, its plaintext is in the memory of the process using it. No design stops someone with root on a running host from reading memory. What this achieves is no standing access — reading a secret requires deliberately compromising the live system, and with a key-management service it leaves an audit record. It never means a database query or a backup is enough.

Provider keys — nobody reads them back

Bringing your own provider keys only means something if nobody can retrieve them afterwards. There is no read path, and that is a property of the code rather than a policy:

  • No API response, screen, export or report returns a stored key — not to the person who entered it, not to an administrator, not to support, not to us. A key can be replaced, never revealed.
  • Every secret is held in a type whose string, JSON and console representations are all a mask, so a key cannot reach a log or an error report by accident. Unwrapping it is a single named call, and a lint rule confines that call to the files that make provider requests.
  • Every decryption is recorded with which key, which run and when. A decryption with no corresponding measurement is an incident, and that is checkable rather than assumed.

Support access

When someone here needs to look at an organisation's account to answer a question, that access is a real, bounded record rather than a shared admin login:

  • Each support session names the administrator, the organisation, a written reason and an explicit scope, carries an expiry, and can be revoked before it expires.
  • A support session never includes provider keys, because no read path for them exists for anyone (above).

The honest gap: these sessions are currently visible to us and not to you. A customer cannot yet see, in their own account, that a support session was opened against their organisation. That surface is not built, and until it is, this control is auditable internally rather than transparently.

Subprocessors

Every third party that receives any of your data, what it receives, and where it is processed. Published as a versioned record so that a change to it is dated rather than discovered.

We give 30 days notice before any addition to this list takes effect. This is version 1.0.0 of the register, effective from 2026-10-05.

SubprocessorPurposeWhat it receivesWhereStatus
StripeSubscription billing and payment processingBilling email address, organisation name, the amount and currency of each charge, and the card details the payer enters directly into Stripe's own hosted fields. Card numbers never reach SignalOS.United States, with EU processing under Stripe's own data-residency termsIn use
ResendTransactional email — verification, invitations, alerts, billing noticesRecipient email address, the subject and body of the message sent, and delivery statusUnited StatesIn use
SentryApplication error monitoringError messages, stack traces, request paths and user and organisation identifiers. Provider keys and other secrets are wrapped in a type that renders as a mask, with a second scrubbing layer in the Sentry integration itself.United States or European Union, depending on the configured Sentry regionConfigurable, not currently enabled
Amazon Web Services — S3Object storage for generated reports, data exports and uploaded assetsThe contents of generated reports and exports, and any logo or asset an organisation uploadsThe AWS region configured in S3_REGIONConfigurable, not currently enabled
Amazon Web Services — KMSWrapping the data keys that encrypt provider credentials and other secretsEncrypted data keys only. No credential, no customer content and no plaintext secret is ever sent to KMS — it receives a 32-byte key to seal and returns it sealed.The AWS region configured in KMS_REGIONConfigurable, not currently enabled

Entries marked as configurable are listed because enabling them is a configuration change rather than a code change. A register that named only what is switched on today would be wrong the day one of them is switched on.

The AI providers are not our subprocessors

You hold the account, the contract and the bill with each AI provider; we hold the key you gave us and call the provider on your behalf. That makes them your processors rather than ours, which is a real difference in who is responsible to you and not a technicality. They are named here anyway, because a subprocessor register that was silent about where the measurement text goes would be hiding the most important answer in it.

  • OpenAI — What is sent: The question text being measured
  • Anthropic — What is sent: The question text being measured
  • Perplexity — What is sent: The question text being measured
  • Google — What is sent: The question text being measured
  • Microsoft — What is sent: The question text being measured
  • xAI — What is sent: The question text being measured
  • DeepSeek — What is sent: The question text being measured

Access control

  • Capability-based role-based access control (RBAC) — six roles, permissions enforced centrally on every request, not scattered per-route checks.
  • Real SAML 2.0 and OIDC single sign-on, with just-in-time provisioning gated on a pre-existing active membership — a valid SSO assertion alone never creates account access.
  • A full SCIM 2.0 implementation for automated user provisioning/deprovisioning from an identity provider.
  • TOTP-based two-factor authentication, and a real, visible list of active sessions a user can review and revoke.
  • An append-only audit log — every record-changing action is written with actor, action, before/after values, and IP/user-agent, and the log itself is protected by a real database trigger that rejects any UPDATE or DELETE against it, not just an application-level convention.

Data handling

  • Every tenant’s data is logically isolated by organization on every real table.
  • Free-text customer data (support tickets, call notes) is scanned for personal information — emails, phone numbers, payment card numbers, street addresses, and explicitly-labeled names — and redacted before it is ever stored or sent to an AI provider.
  • A self-service full data export, and a self-service permanent-deletion path for an organization’s own content, both real and described at /legal/data-processing.

Incident response

No formal, documented incident-response runbook exists in this codebase or organization today — this is a real gap, not a claim of readiness. A real incident-response plan (severity classification, escalation path, customer-notification commitments and timelines) needs to be written and owned by whoever operates this deployment before it can be honestly described here.

Penetration testing

No third-party penetration test has been performed on this application. A real cadence commitment (e.g. annually, or before each major enterprise deal) should be set once a real test is scheduled — nothing here should be read as implying one has already happened.

SOC 2 readiness

No SOC 2 audit — Type I or Type II — has been performed or started. A real path to SOC 2 Type I readiness looks like:

  • Select the Trust Services Criteria in scope (Security is the mandatory baseline; Availability and Confidentiality are the most relevant additions for this kind of product).
  • Formalize the controls already real in code (RBAC, SSO/SCIM, encryption at rest, the immutable audit log, access review) into written policies a human owns and can produce evidence for.
  • Close the two real gaps named above — a documented incident-response process and a completed penetration test — before an auditor would consider the control environment ready.
  • Engage a licensed SOC 2 auditor for a Type I (point-in-time control design) assessment; Type II (operating effectiveness over a real observation window, typically 3-12 months) follows only after Type I.

No timeline is committed here — this is the real, ordered list of what readiness requires, not a date.