Skip to main content

Trust & Security

Align is built to be deployed inside engineering organizations that care about how their decision data is handled. This section documents the controls Align implements, our data-handling commitments, and the subprocessors involved.

Compliance status

Align's security controls are implemented and mapped to the SOC 2 Trust Services Criteria. We're working toward SOC 2 Type II attestation. We are not certified, and we won't tell you an audit is underway when it isn't.

Architecture commitments

  • Tenant isolation, application layer (enforced by default). For any authenticated request the tenant comes from the verified auth token, and a client-supplied x-tenant-id header can never override it. The header is only consulted when there is no auth context, which covers trusted service-to-service calls (authenticated with a shared service token) and demo mode - it is not reachable as an ordinary authenticated user. getTenantFromReq resolves authTenantId || headerTenantId, and that precedence is locked by a regression test.

  • Tenant isolation, database backstop. Row-Level Security policies are defined with FORCE on all tenant-scoped tables but one (tenant_subscriptions, whose Stripe webhook and provisioning path still needs an owner connection - a tracked follow-up), and a CI test connects as the restricted, non-owner align_app role and asserts a real cross-tenant query returns zero rows. The backstop only takes effect once the application connects as that restricted role rather than the database owner - a table owner bypasses RLS regardless of FORCE. The installation guide walks a new self-host install through this as a documented step after migrations run - it is not automatic, the operator sets the role's password and adds it to the database secret; see Installation. An existing install, including our own hosted deployment as we complete this rollout, follows RLS Cutover to switch over.

  • Encryption in transit. TLS.

  • Encryption at rest. Provided by your infrastructure (RDS/EBS storage encryption, S3 SSE, ElastiCache encryption) and configured by you. Align does not add an application-level cipher over general decision data.

  • Application-level encryption of secrets. OAuth connector credentials are encrypted with AES-256-GCM using a master key you control, and the service refuses to start without that key rather than storing them in plaintext. Tenant LLM API keys are encrypted separately, at the database layer, using PostgreSQL pgcrypto with the same master key.

  • Key rotation. The OAuth-token master key rotates with zero downtime (dual-key decrypt plus a background re-encryption job). If you also store tenant LLM API keys, rotating the same master key requires a short re-encrypt step alongside the key-swap deploy, because pgcrypto has no multi-key fallback. See Encryption Key Rotation.

  • Source content retention. The extracted decision record drops the verbatim captured message shortly after analysis. Two paths currently retain raw content for longer: the connector capture buffer and historical import batches. A third, the S3 raw-event archive, is disabled unless you set S3_RAW_EVENTS_BUCKET and writes to a bucket you own. See Data Retention for the exact tables and windows.

  • PII redaction before LLM calls on analysis paths. Emails, phone numbers, SSNs, IP addresses, credit card numbers, proper names and API keys are redacted before text is sent to a language model on the decision-analysis, synthesis and historical-scan paths. Detection runs Microsoft Presidio (an NLP model, so PERSON is covered) followed by a regex pass, and it is on by default - ENABLE_PII_REDACTION disables it only when set explicitly to false. It does not yet run on every conversational endpoint. You can also point Align at a local LLM for zero cloud egress.

    Corrected 2026-08-06: this bullet previously said redaction was "pattern-based" and did not cover proper names. That described an earlier state in which Presidio was declared but never installed, so the live redactor was regex-only. Presidio is installed and running now; the sentence had outlived the defect it described.

Access control & auditability

  • SSO via OIDC (including Azure AD / Entra ID and any OIDC-compliant IdP) and Google; AWS Cognito federation. A SAML 2.0 service provider is implemented but its signing library is not bundled in the shipped image, so SAML is not currently available in a standard deployment - talk to us if you need it.
  • SCIM 2.0 provisioning (/Users and /Groups, including PATCH and deprovisioning).
  • Role-based access control with directory-group-to-role mapping.
  • An audit trail of mutations and access-control denials, retrievable by org admins via a filterable audit-log API. The application only ever inserts into it; note this is enforced in application code, not by a database constraint. Legal hold applies to decision snapshots, not to audit records.
  • Per-user data export and deletion endpoints (GDPR Article 15/17/20), with legal hold. These are admin API endpoints; there is no self-serve UI for them.

Reporting a vulnerability

See SECURITY.md for responsible-disclosure contact and process.