Back to home
Trust

Security

Last updated: [DATE]

1. Where your data lives

The PostgreSQL database and the Redis cache run on a Hetzner server in the Helsinki, Finland datacenter. That is where your clients, projects, invoices, transactions and everything else you type into Worklyn sits at rest.

Uploaded files and the exports the product generates go to Cloudflare R2. The bucket was created under Cloudflare's EU jurisdiction restriction. That is a setting on the bucket rather than a line in our code, so treat it as our statement rather than something you can read off this page.

The application itself is still served by Vercel while we finish moving it onto the same Helsinki box. So a request travels through Vercel, and the data it reads and writes lives in Helsinki. We would rather say that than round it up.

2. What is encrypted, and with what

We are not going to write "everything is encrypted" on this page. Here is the actual list of what gets encrypted on top of the transport and the disk it sits on.

  • Bank access tokens are encrypted with AES-256-GCM before they are written, using a 256-bit key that exists only in the server environment.
  • IBANs on connected bank accounts go through the same encryption.
  • Calendar, mailbox and accounting OAuth tokens use that same module and the same key. Google Calendar, Outlook, Gmail, Xero and QuickBooks connections all store their tokens encrypted rather than in the clear.
  • Credentials you share with a client through the portal are encrypted with AES-256-GCM using a separate server-held key. We can decrypt those, and we are saying so on purpose: your client has to be able to read them without knowing any passphrase of yours.

The project credential vault is different, and it is the strongest thing on this page. Logins and API keys you save against a project are encrypted and decrypted in your own browser with AES-256-GCM. The key is derived from your master password with PBKDF2, 100,000 iterations, SHA-256, and a random per-user salt. It is created as non-extractable, held in memory only, and cleared when you lock the vault or leave the page. What reaches our server is ciphertext and an initialisation vector. Your master password never leaves your device, and there is no code path anywhere in Worklyn that decrypts those fields on the server. The consequence is honest and worth reading twice: if you lose both the master password and the six-word recovery key, that vault is gone. We cannot open it for you, and neither can anyone who walks off with a copy of our database.

Everything else in the database is stored as ordinary columns. Client names, invoice lines, transaction descriptions and task titles are protected by access control and by the database not being reachable from the internet, not by per-field encryption. Traffic runs over HTTPS, and session cookies are httpOnly and marked Secure in production.

3. Signing in and getting access

  • Passwords are hashed with bcrypt. We never store the password itself, and we cannot read it.
  • Email verification is required before a password sign-in works.
  • Two-factor authentication is available on every account, using an authenticator app plus backup codes.
  • Sessions roll forward with use and abandoned ones are deleted by a nightly job once they have expired.
  • Roles. A workspace has owner, cofounder, manager, accountant and crew. The money side is gated by role, so a crew member on a project does not see your banking.

The client portalworks on emailed links, and both secrets in that flow are stored hashed. The invite token is kept as a SHA-256 hash, is single use, and expires. The session it creates is also stored only as a SHA-256 hash, in an httpOnly cookie that lasts 30 days. The verify endpoint is rate limited per IP. You can revoke a client's portal access from the client record, and revocation is checked on every portal request, so it takes effect on the next click rather than whenever their session happens to lapse.

Files. The app never hands out a permanent storage URL. It fetches objects with signed links generated per request that expire in five minutes, and streams them through our own domain so the storage key stays private. Generated export downloads use a longer signed link, up to seven days. One thing to know: a file link you copy and send to someone is a capability, so anyone holding it can open that file. Treat shared links like passwords.

4. What we deliberately do not store

  • Social sign-in tokens. Our auth library writes Google, Microsoft, LinkedIn and GitHub access, refresh and ID tokens to the accounts table in plaintext by default. A database hook nulls all three columns on every write. Nothing in the app reads them, so a secret that is never stored needs no key management and cannot leak.
  • Prompt and completion text. Every AI call writes one usage row: the operation, its category, the model, the provider, the plan tier, prompt and completion token counts, estimated cost, duration, status and any error code. The table has no column for message content, so there is nowhere for your prompts or the answers to land.
  • Your banking password. You authorise a bank connection on the bank's own screen through Plaid or Enable Banking. Those credentials never pass through us.
  • Your vault master password. The server holds only a salt, a verifier hash and a recovery-key hash. None of them can be turned back into the password or the key.

5. Bank connections are read-only

We checked this rather than assumed it. With Plaid we request the Transactions product and nothing else, with up to 730 days of history on first connect. With Enable Banking the consent we ask your bank for covers balances and transactions. No payment initiation product is requested anywhere in our code, which means Worklyn has no route to move your money even if someone got into it. Access tokens for both providers are stored encrypted, as described above.

6. Getting your data out, and closing the account

Export. Account settings has an Export Data button. It builds a ZIP containing JSON for clients, projects, tasks, time logs, expenses, proposals, invoices, contracts, portal history, AI conversations, calendar entries, ideas and your profile, plus every file you uploaded. Two things are left out on purpose: portal invite token hashes and the encrypted portal credential fields. Putting either into a downloadable ZIP would be a security hole, not a feature.

Delete. Same screen. It is a hard delete, not a flag on a row. Your files are removed from storage first, then the user record is deleted and every related record cascades with it. There is no soft delete, no 30 day grace period and no recovery window. That is deliberate: nobody, including us, can restore your account afterwards. Export first if you want a copy.

7. How long we keep things

Your workspace data stays for as long as your account exists. Operational data that has done its job gets swept by a job that runs every night. These are the defaults:

  • Notifications: read ones after 20 days, unread ones after 60, and every account trimmed to its newest 100.
  • Client portal sessions: expire 30 days after sign-in, and the row is deleted a day after that.
  • Portal invite tokens: wiped once expired, so an old link that leaks can never be replayed. The access record itself stays, because that is your record of who has portal access.
  • Workspace invitations: deleted once they expire.
  • App sessions: deleted a day after expiry.
  • Email verification and password reset tokens: deleted as soon as they expire.
  • AI usage rows: 13 months, which covers a full year plus a buffer for year-over-year cost comparisons.
  • AI assistant action log: 24 months, because it is closer to an audit trail than a metric.
  • AI conversations: deleted after 12 months with no new message in them.
  • Records we are legally required to keep, such as invoices and payment records, are kept for the statutory period.

8. Sub-processors

Every third party that touches Worklyn data, what it receives and where it runs, is listed at worklyn.co/sub-processors. It is the whole list, not a selection.

9. Reporting a vulnerability

Email hello@worklyn.co. The same address is published at worklyn.co/.well-known/security.txt. Include enough detail to reproduce the issue and we will get back to you.

What we commit to: a human reads every report and replies to acknowledge it. What we are not going to promise, because we are a small team and a promise we break is worse than none: a fixed patch deadline or a bug bounty. There is no paid bounty programme today. If that changes it will be on this page.

Two asks in return. Please do not run automated scans that degrade the service for people using it, and please do not access, modify or keep anyone else's data while testing. A description of the hole is plenty.

10. What we have not done yet

This section is forward looking on purpose, and nothing in it is a claim about today.

  • SOC 2 Type II is planned for 2027. We are not certified, no audit is in progress, and there is no report to send you. A Type II is not a form you fill in: it needs controls running for an observation window of several months and an external auditor watching them, so the earliest an honest report could exist is well into that year. We will say so here when it actually starts.
  • Backups. Nightly database backups to Cloudflare R2 with point-in-time recovery are built and documented, but we are not going to call them live on a security page until we have performed a restore from them ourselves. A backup you have never restored from is a hypothesis. This line changes when that is done.
  • No external penetration test has been carried out.
  • One region, one database server. There is no standby replica and no automatic failover. Recovery from a lost machine is a manual process.

Questions about any of this, or something we got wrong: hello@worklyn.co. We read them ourselves.