Security
A plain-language explanation of how we protect your data – for users and curious engineers alike.
Overview
Security is built into the foundation of Sonaa. We believe that privacy is not just a feature, but a fundamental requirement for any software you use to manage your life. Sonaa Week inherits this architecture, offering two encryption modes so you can choose how much trust you place in our servers, and an authentication layer designed to be secure by default.
Encryption modes
Standard
Encrypted on our serverIn standard mode, your content (titles, notes, subtasks) travels between your browser and our servers over TLS, and our server encrypts it before storing it in the database. This means:
- your data is encrypted in transit;
- it is encrypted in our database with AES-256-GCM, using a separate key for each account derived from a server secret that is kept outside the database – a copy of the database or a backup alone shows only ciphertext;
- our server holds that key, so we – as the server operator – can technically read your content;
- you can reset a forgotten password without losing anything.
If you do not want our server to hold the key to your content, choose end-to-end encryption when you set up your account.
End-to-end encryption
Client-side keyWith end-to-end encryption, the titles, notes and subtasks of your tasks are encrypted in your browser before they are sent to our API, with a key that only your password can unlock. Our database stores this content only as ciphertext, together with the key in its locked form – never the unlocked key or the plaintext.
How it works, step by step
- You choose end-to-end encryption when you set up your account. It is a one-time choice and cannot be switched off later.
- Your browser generates a random data key and derives a second key from your password using a KDF (details below). The data key is wrapped with the password key; only that wrapped form is stored on our servers.
- Each piece of content is encrypted with the data key using AES-GCM before leaving the browser.
- The ciphertext and a random initialization vector (IV) are sent to our API and stored in the database.
- When you sign in on a device, your password unwraps the data key locally, and your browser decrypts your content with it.
Your password never leaves your browser
Your browser runs your password through Argon2id once and derives two separate keys from the result: one unlocks your data key, the other is what signs you in. Only the sign-in key is ever sent to us, and neither your password nor your data key can be computed from it. This applies to every account, in both modes.
Cryptographic parameters
- Algorithm
- AES-256-GCM
- IV
- 96-bit random per record (Web Crypto API)
- KDF
- Argon2id – 3 passes, 64 MiB memory, parallelism 1
- Key storage
- Non-extractable key in this browser's IndexedDB; the server holds only the password-wrapped key
What it protects against – and what it does not
- Protected: anyone who obtains a copy of our database or backups – including us, browsing it – sees only ciphertext for titles, notes and subtasks. Opening it would require guessing your password against the KDF above.
- Not encrypted: everything our server needs to sync and order your week – dates, times and durations, reminders, colors, completion status, recurrence rules, order, and the names of your shelves and calendar – as well as your account data (email, name, sessions).
- Not protected: the app itself is delivered by our servers. Someone who took control of them – or we ourselves, if we deliberately changed the app – could ship a version that reads your password or your decrypted content in your browser the next time you use it. End-to-end encryption protects your stored content and your password from our servers; it is not a guarantee against a compromised or malicious app. Accounts created before 8 October 2026 send their password once more, at their next sign-in, to switch to a sign-in key.
Transport security
All communication between your browser, the web app and our API is over HTTPS. Both send HSTS headers, so browsers keep using HTTPS for later visits.
Requests reach us through Cloudflare, which shields our servers from attacks. It ends the HTTPS connection and opens a new one to our servers, so it can technically see a request in transit, including Basic content. End-to-end encrypted content passes through it as ciphertext.
Authentication
Password security
- Passwords must be 8–128 characters long.
- Passwords are rated for strength with zxcvbn at registration, reset and change; weak or easily guessed passwords are rejected. The check runs in your browser – nothing is sent to us or to a third party.
- Sign-in, sign-up and password endpoints are rate-limited to slow down guessing.
- Your password never reaches our server: your browser sends a sign-in key derived from it with Argon2id, and our server stores only a hash of that key (scrypt, via better-auth).
Email verification
Every new account must verify its email address before the app stores any of its content on our servers. Verification codes expire after 10 minutes and are one-time use only.
Sessions
- Session tokens are stored in HttpOnly, Secure, SameSite=Lax cookies – inaccessible to JavaScript on the page and not sent with requests started by other websites.
- You are asked to sign in again at the latest 90 days after signing in.
- Changing your password signs out every other device.
- Resetting a forgotten password signs out every device.
- Each session records the IP address and user-agent so you can audit active sessions and revoke them individually.
One-time passwords (OTP)
Changing your email address requires your current password and a one-time code sent to the new address. Deleting your account requires your password and a confirmation link sent to your email. Codes expire after 10 minutes and are single-use.
Infrastructure
- Our database runs on PostgreSQL, hosted by Hetzner Online GmbH in Germany (EU).
- Production credentials are kept in environment secrets and are never committed to source code.
Account deletion
Deleting your account permanently removes all associated data – tasks, sessions, and account details – from our production database immediately after you confirm the emailed link. Deleted tasks are purged within 30 days. Backups are purged on their normal rotation schedule. Deletion is irreversible.
Responsible disclosure
We welcome security researchers. If you discover a vulnerability, please report it to us privately before making it public:
- Email: contact@henrikzabel.com
- Please include a clear description and reproduction steps.
- We aim to acknowledge reports within 48 hours.
- We request a reasonable coordinated-disclosure window (90 days) to develop and deploy a fix before public disclosure.
We do not currently run a formal bug-bounty program, but we genuinely appreciate responsible reports and will credit researchers publicly if they wish.