HTTPS everywhere
All traffic between your Twoody device, the mobile/web app and our servers goes exclusively over TLS 1.2 or higher. Plain HTTP is refused at the server level, not merely redirected.
How data travels between your devices and our servers, and how it is stored at rest.
Every byte that leaves your phone, browser or Twoody speaker travels over authenticated, forward-secret TLS. Once it reaches our database, anything sensitive (API keys, third-party credentials, session digests, voice profiles) is encrypted again with keys stored outside the database. A stolen backup is cryptographic noise; a captured packet is cryptographic noise; compromising either on its own yields nothing.
All traffic between your Twoody device, the mobile/web app and our servers goes exclusively over TLS 1.2 or higher. Plain HTTP is refused at the server level, not merely redirected.
Browsers are instructed to always use HTTPS for twoody.com and its sub-domains for one year, with includeSubDomains and preload. Our domain is submitted to the HSTS preload list so downgrade is impossible even on a first visit.
Connections negotiate TLS 1.3 when supported and fall back to TLS 1.2. Forward secrecy (ECDHE) is mandatory on every suite we accept, so a future leak of our private key cannot be used to decrypt recorded traffic.
Our Cloudflare edge blocks malicious bots (Bot Fight Mode), monitors certificate issuance (Certificate Transparency), enforces our WAF rules and absorbs DDoS traffic upstream of our origin.
Our DNS zone is signed, blocking cache-poisoning at resolvers that honor DNSSEC. Mail and subdomains pointed at <code>twoody.com</code> can't be silently hijacked at the DNS layer.
Sensitive columns (user API keys, third-party credentials, session digests) are encrypted with keys distinct from the main database key, via ActiveRecord Encryption. A database dump does not expose your secrets.
Production database backups are encrypted at rest and in transit, retained for a bounded window, and access is limited to the primary operator with per-action audit logs.
The strongest protection for a secret is to not hold it. We never store card numbers (Stripe does), we don't persist raw wake-word audio beyond what's strictly needed for matching, and we don't keep verbose logs of successful requests.
Our load balancer presents a modern cipher suite list: TLS 1.3 AEAD suites (AES-GCM, ChaCha20-Poly1305) first, then a short TLS 1.2 fallback that is ECDHE-only. Weak primitives (RC4, 3DES, export-grade, static RSA key exchange) are refused at the handshake — a client that can't negotiate forward secrecy gets a clean connection failure rather than a downgraded session. OCSP stapling is enabled so browsers can check certificate revocation without an extra round-trip to our CA.
The certificate chain uses Let's Encrypt ECDSA intermediates; we watch the Certificate Transparency logs and alert on any certificate issued for our domain that we didn't request.
We maintain three distinct encryption keys, stored in environment variables and never in the database: a primary key for non-deterministic columns (different ciphertext every write), a deterministic key for columns that need to be queried by equality, and a key-derivation salt. Our boot process refuses to start in production if any of the three is missing or still holds the dev placeholder — you can't accidentally ship a build with weak encryption.
Key rotation is a first-class operation. The primary key is versioned, so a rotated key encrypts new rows while existing rows stay readable under the previous generation; a background job can re-encrypt on demand.
Non-sensitive metadata — user IDs, timestamps, row counts, product SKUs — is stored in clear. Encrypting everything indiscriminately would break indexing, break analytics, and provide no real benefit; the attack model for that data is "they already have your database," in which case encrypted identifiers are no safer than plaintext ones.
We encrypt what matters (tokens, secrets, biometrics, third-party credentials), we document what we encrypt, and we rely on ordinary Postgres access controls for the rest.