How your data is held
Keln is operated by Keln Holdings LLC. Every claim on this page describes something that is actually in the code today. Where a protection depends on how a deployment is configured, it says so, and where Keln has a known limitation, that is written down too — a security page that only lists strengths is a marketing page wearing a lab coat.
What Keln never holds
Subscription payments are handled entirely by Stripe. Card details are entered on Stripe's own pages and never reach a Keln server, which is why Keln has no card data to lose.
When a client pays for an appointment they use your payment link — your Stripe, PayPal or Square. Keln stores the URL and shows a button. The money moves between you and them; Keln is not in the path at all.
Passwords are hashed with scrypt and a per-account random salt before storage. There is no route, admin screen or support process that can reveal a password, because the original is never written down.
Protecting what is stored
Contact details are encrypted at rest
Names, emails, phone numbers, addresses and notes on your prospects are sealed field by field with AES-256-GCM before they touch the disk, under a key held in the deployment's environment rather than in the database. Someone who obtained a copy of the database file alone would not be able to read them. This requires an encryption key to be configured on the deployment; without one, Keln logs a warning at boot and stores those fields in the clear.
Writes are atomic, and the write is fsynced — so is the rename
Every save is written to a temporary file, flushed to the disk, and then renamed over the real one. Renaming within a filesystem is atomic, so a reader sees either the whole old database or the whole new one and never a half-written file. The directory itself is fsynced after the rename, which is what makes the publication of the new file survive a power loss — the step most "atomic write" implementations leave out, and the one that decides whether your data is still there after the lights come back.
Backups are verified before they are taken, and refuse rather than overwrite
The backup job parses the database before copying it. If it will not parse, nothing is copied and nothing is rotated away, so the last known-good snapshots stay exactly where they are. A backup system that faithfully copies a corrupt file, on a schedule, with a retention limit, will quietly destroy every restore point you have — this one is built not to.
Verified snapshots are then encrypted with AES-256-GCM and pushed off the machine, under a key that is separate from the one protecting the live database and that never leaves the server. Local snapshots sit on the same disk as the data they protect; only an off-site copy survives that disk dying. The restore path is a script we can run, not a procedure we have written down and never tried.
Two-factor authentication
Any account can add a time-based code from an authenticator app, and admin accounts must — the admin surface stays closed until it is on, because that account can reach every customer's data. Codes are verified against RFC 6238, and a code that has been used is never accepted again: without that, anyone who reads a code over your shoulder has up to ninety seconds to use it themselves. Ten single-use recovery codes are issued once, shown once, and stored hashed — so if you lose the printout, nobody at Keln can read them back to you either.
Sessions
Sign-ins are stored server-side in SQLite, not in the cookie. The cookie
itself is httpOnly (unreadable by any script on the page),
sameSite=lax, and marked secure in production so it is
never sent over plain HTTP. Changing your password invalidates every other
session, and the session identifier is regenerated at the moment you sign in — so a cookie
planted before sign-in is not the one that ends up authenticated.
Rate limits and bot protection
Sign-in, sign-up, password reset, email sending and portal bookings each carry their own rate limit, sized to what that route is for rather than to one global number. Sign-in, sign-up and portal bookings additionally require a Cloudflare Turnstile challenge that is verified on the server — a challenge that is only rendered and never checked is worse than none, because it reports a locked door that is standing open. Password reset, resend-verification and the waitlist carry the same check: each of them sends mail to an address the caller chose, which without a challenge makes them a free mailer running on our own domain reputation.
The client portal
Private links are stored hashed
The link that lets a client see their appointments without an account is a 256-bit random token. Only its SHA-256 hash is stored, so reading the database does not hand anyone another person's bookings. Each booking mints a fresh link and older ones keep working, so a returning client is never locked out.
A client can only ever see an allowlist
What a client sees of their own record is constructed field by field in one function — never copied wholesale from the stored row. That is a deliberate choice: it is the only way to be certain a client never reads their own pipeline stage, the value you put on the deal, a private note about them, or a line of their transit log. Ownership is checked against the token, so knowing an appointment's identifier is not permission to touch it.
A portal that is switched off returns "not found"
Not "closed", not "disabled" — the address behaves exactly as one that was never claimed. Turning your booking page off should not confirm to a stranger that it exists.
Your data is yours
Everything on your account can be exported as a single JSON file from Settings, at any time, without asking anyone.
Deleting your account erases the record rather than flagging it as hidden. A soft flag while the row still sits in the database would make the promise in our Privacy Policy untrue.
Your pipeline is not a dataset. It is not sold, and it is not used to target anything at you.
What we would tell an auditor
The honest list of what Keln is not, as of today. It is here because a security page you cannot check is worth nothing, and because these are the things we would rather you heard from us.
- Keln has not completed a SOC 2, ISO 27001 or equivalent third-party audit. Nobody external has verified any of the above.
- Two-factor authentication is optional for ordinary accounts. If you do not turn it on, your password is still the whole of your account security.
- Passkeys and hardware security keys are supported, and they are the only thing here that defeats a convincing phishing page — the signature is bound to this exact address, so a fake login page has nothing to collect. They are optional, and they are an addition rather than a replacement: your password and authenticator code still work, which is why losing the device holding a passkey is not losing the account.
- A passkey that only proves possession — a security key tapped with no PIN set — does not complete a sign-in on an account with two-factor on. It is still asked for the code, because one factor is one factor.
- Encryption at rest protects prospect contact fields. It does not cover every field of every record.
- Encryption at rest and off-site backups each depend on a key being configured on the deployment. Both log a warning when one is missing, and neither invents a fallback.
- There is now a written incident-response plan, published rather than filed, with the notification clocks in it. There is still no contractual uptime commitment. What we publish instead is measured status at getkeln.com/status.
- That plan is carried out by one person. The clocks in it are real commitments and none of them describes a 24-hour staffed rota, because there is not one.
- Keln Holdings LLC is a very small operation. Response to a report is fast, but it is not a 24-hour staffed rota, and we will not pretend otherwise.
Reporting something
If you find a vulnerability, write to support with the words "security report" in the subject. Tell us what you found and how to reproduce it. We will confirm receipt, keep you updated, and we will not threaten you for looking. Please do not run automated scans against production or access an account that is not yours — a proof of concept against your own account is enough, and it is what we would ask for anyway.