Confidentiality
Your data is unreadable to anyone but you
Encryption is not a checkbox. It is a chain of cryptographic primitives — at rest, in transit, in proxy headers, in stored credentials, in error messages — and the chain is only as strong as its weakest link. We hold every link to a published, peer-reviewed standard.
Executive summary
High-risk fields use AES-256-GCM at rest. Transit uses TLS 1.3 with HSTS. Stored credentials, OAuth tokens, signing certificates, and webhook secrets are individually encrypted at the field level — a database dump alone does not yield usable secrets.
We also harden the layers people forget: client IPs are extracted from the rightmost public hop (never the spoofable leftmost), Unicode inputs are normalized against homoglyph attacks, and file paths are containment-checked.
Our commitments
Five rules across the cryptographic stack
No proprietary crypto, ever
Every primitive is a published, peer-reviewed standard with a NIST or IETF reference. We do not invent ciphers, hash modes, or key derivation functions.
Field-level encryption for high-risk values
Signing keys, OAuth tokens, webhook secrets, SAML private material — each carries field-level AES-256-GCM encryption and redact: true on the schema. They never reach logs, telemetry, or Inspect output.
The transport edge is the security boundary
TLS 1.3 with HSTS preload, certificate pinning on mobile, and trusted-proxy IP extraction. The rightmost public IP is the real client; the leftmost is whatever the attacker wrote in a header.
Inputs are sanitized at every layer
Unicode homoglyph normalization, atom-table protection on JSON deserialization, path traversal containment, and open-redirect URL validation. Each is its own audited module.
Post-quantum primitives are compiled in, with production wiring planned
CRYSTALS-Kyber and CRYSTALS-Dilithium primitives are present in our Rust NIF. Production callers are on the roadmap; no seals or credentials are signed with PQC today.
Implementation — at rest
Encryption at rest
Implementation — in transit
Encryption in transit
Implementation — input hardening
Where we don't trust user input
Encryption protects what we store. Input hardening protects what we accept.
The full picture
What is built, what is being built, and what we chose not to build
Live today
Field-level AES-256-GCM at rest
LiveCredentials, MFA secrets, signing-key material, and webhook secrets are encrypted before INSERT.
TLS 1.3 with HSTS
Live0-RTT disabled. Forward-secret cipher suites only. Origin restricted to Cloudflare proxy ranges.
Trusted-proxy IP extraction
LiveRightmost public hop in X-Forwarded-For; CF-Connecting-IP and Fly-Client-IP take precedence. Centralized in IpExtraction module — never parsed manually elsewhere.
Atom-table protection on every JSON boundary
LiveString.to_existing_atom on all untrusted input. Atom-exhaustion DoS is impossible by construction.
Unicode homoglyph normalization on user-visible strings
LiveMixed-script display names are flagged before they reach the directory or sealed documents.
File magic-byte verification on upload
LiveMislabeled file uploads are rejected at the boundary. A renamed .exe cannot pose as a PDF.
Building now
Certificate Transparency monitoring
Building nowAutomated alerts on any certificate issued for our domains by any CA. Detects mis-issuance within hours.
Mobile certificate pinning
Building nowPublic Key Pinning on the iOS/macOS/Android native clients to prevent CA-substitution attacks on hostile networks.
Roadmap
Hybrid post-quantum TLS
RoadmapX25519MLKEM768 (TLS 1.3 hybrid key exchange) once Cloudflare and Fly support is generally available.
Production wiring for post-quantum signatures
RoadmapCRYSTALS-Kyber and CRYSTALS-Dilithium primitives are present in the Rust NIF. Schema columns and signing callers are not yet wired.
Encrypted client-side telemetry
RoadmapIf we ever ship product analytics, the payload is encrypted client-side and we never see PII or document content.
Per-organization encryption boundary
RoadmapOrg-scoped data encryption keys so a compromise in one tenant cannot decrypt another tenant. Already true for documents; expanding to all org-scoped data.
Considered & rejected
DANE (DNS-based authentication of named entities)
Considered & rejectedDANE is the right idea, but DNSSEC adoption is too low and operationally fragile to build security on.
Why we rejected it: DANE depends on DNSSEC, which depends on every resolver in the chain implementing it correctly. In practice, that's still a small minority. We use Certificate Transparency monitoring instead — it gets us the same detection of CA mis-issuance with broader real-world coverage.
Customer-supplied symmetric ciphers
Considered & rejectedIf the customer asks for a non-standard cipher, the right answer is "AES-256-GCM," not "yes, let me roll that for you."
Why we rejected it: every "we accept your custom crypto" is a way to ship a worse default. The customers who actually need a different cipher (zero, in our pipeline) can wrap our envelope themselves before upload. We do not multiply the implementation surface to accommodate hypothetical asks.
TLS 1.2 fallback
Considered & rejectedTLS 1.3 is universally supported by clients we care about. Fallback paths are attack surfaces.
Why we rejected it: TLS 1.2 has known weaknesses (CBC padding oracles, downgrade attacks) and unbounded cipher-suite negotiation. Modern browsers, mobile OSes, and language stdlibs all speak TLS 1.3. Forcing 1.3 means saying no to a tiny long-tail of clients to keep the security floor high for everyone else.
Self-signed certificates anywhere in the production path
Considered & rejectedA self-signed cert is a "trust me" — exactly the property our Public Key Infrastructure exists to remove.
Why we rejected it: even for "internal" mTLS we use a customer-rooted CA chain, not self-signed. The whole point of PKI is that trust is delegated to a verifiable third party. Self-signed shortcuts are how internal-tools secrets escape into production.
Hashing user passwords with SHA-256
Considered & rejectedA fast hash on a low-entropy input is exactly the wrong tool. We use Bcrypt.
Why we rejected it: SHA-256 is fast — that's the feature for content hashing and the bug for password storage. Bcrypt has a tunable work factor specifically designed to slow down brute-force attempts. Different problem, different tool.
Compliance mappings
Controls this surface satisfies
Data Transmission and Disposal
TLS 1.3 in transit; AES-256-GCM at rest; cryptographic erasure on delete
Cryptographic controls
NIST/IETF-standardized primitives; key sizes documented
Network controls
HSTS preload; trusted-proxy IP extraction; HTTPS-only webhooks
Transmission Security
TLS 1.3 with forward-secret cipher suites only
Encryption and Decryption
AES-256-GCM at rest with field-level keys for high-risk data
Security of processing
State-of-the-art cryptography; pseudonymization where appropriate
For compliance teams
Questions you don't need to call to ask
Where are the encryption keys stored?
Is post-quantum cryptography in use today, or is this marketing?
What happens cryptographically when an organization is deleted?
How do you protect against key compromise?
Why do you extract the rightmost public IP from X-Forwarded-For instead of the first?
Can we audit the encryption implementation?
Encryption that holds up to your auditor and your future
Every primitive on this page is a published standard. Every claim is verifiable in source.