Security
How your travelers’ data is protected
Describes the product as of September 8, 2026
The short version
- One tour company’s data is never visible to another. Every request the server answers is filtered by the account behind the sign-in token, and the automated tests check that a stranger is refused.
- Passwords and guide PINs are stored as scrypt hashes with a random salt. We cannot read them, and neither can anyone who steals the database.
- Sign-in tokens are random, carry no information, and are stored hashed, so a stolen copy of the database does not sign anyone in.
- Two-factor sign-in is available to every office account.
- The database is backed up every night to a separate, private vault with its own keys, and kept for 14 days.
- Exactly one person can reach production: Levi Johnson, the founder.
- What we do not have — a SOC 2 report, a penetration-test report, an uptime guarantee, 24/7 monitoring — is listed below in the same size type.
This page is the plain-language version of the security section of our Data Processing Addendum. Nothing here is aspirational: every line describes what the product does today, and the things it does not do yet are said outright.
Your data, and only yours
Cordelle hosts many tour companies on one system. What keeps them apart is not a setting in the dashboard but a rule in the server: every request for office data is filtered by the agency behind the staff member’s sign-in token, every request from a traveler’s phone is scoped to that one traveler, and a guide’s sign-in opens exactly one departure. The automated test suite includes a test that signs in as one company and tries to read and change another company’s departures, travelers, tours and country guides, and expects to be refused every time.
Signing in
- Office passwords are hashed with scrypt — a deliberately slow function built for passwords — each with its own random salt. The rule is a minimum of eight characters; there is no forced rotation.
- Wrong passwords lock one account, not the company. Eight failures lock that account for 15 minutes; a password reset clears the lock. The count is kept on the account record itself, so it holds across servers and deploys.
- Two-factor sign-in can be turned on by any staff member, using an authenticator app and the standard six-digit codes. Recovery codes are one-time and stored as scrypt hashes. The secret shared with the authenticator app is sealed with AES-256-GCM under a key that lives only in the server’s environment, never in the database. A code that has been used cannot be used again.
- Sign-in tokens are opaque. A session token is 32 random bytes; the database stores only its SHA-256 hash, so a database dump yields a fingerprint, not a key. Staff sessions last 30 days. Traveler and guide sessions last 180 days, so the app never asks for a login mid-trip. Expired sessions are deleted daily.
- Rate limits. The sign-in and join endpoints accept ten attempts a minute per address, on top of the per-account lock.
- Password-reset links work once, and setting a new password signs that account out on every other device.
Guides and travelers
- Join codes are identifiers, not secrets. They are printed in packets, emailed and read aloud, so they are treated accordingly: six characters from an alphabet with no 0, O, 1 or I, and a code stops working 90 days after the departure’s end date.
- A guide’s code opens guide mode; a traveler’s opens the guest app. Neither opens the other.
- Guide PINs are chosen by the guide, stored as scrypt hashes like a password, and lock for 15 minutes after eight wrong tries. The screens holding travelers’ care notes and emergency contacts sit behind the PIN and lock again once the app has been closed a while.
- Cutting a guide off is one tap. Issuing a new guide code from the dashboard ends every session on the old one at that moment; archiving a guide does the same.
- The traveler app cannot change the trip. It reads a published copy, and what it sends back is limited to small things — that the trip synced, that a message was read, a position the traveler chose to share, the token for push notifications — and, if the traveler taps one, a status picked from three fixed choices (On my way, Running late, Sitting this one out). There is no field to type into, so it is never free text.
In transit and at rest
- Everything travels over HTTPS. cordelle.io and the operator dashboard send strict transport security headers, so a browser that has visited once will not go back over plain HTTP.
- The database is managed Postgres at Neon, in the United States. Neon encrypts the storage underneath it.
- Card details never reach us. Billing runs through Stripe; your card goes straight to Stripe and Cordelle holds only the subscription’s identifiers.
- Every free-text field is capped at 10,000 characters before a request is processed, and logo uploads are size-capped, so no single record can be used to flood the store.
- API keys are stored hashed, shown once, revocable, and can reach only the small /api/v1 surface — never billing, your team, two-factor settings or key management.
Backups, and where they live
- Every night a full copy of the database is taken by a separate small application on Fly.io — not the API server — and written to a private object-storage bucket at Tigris, reached through Fly.io. Fourteen days of copies are kept; older ones are deleted.
- The backup application has its own keys. The API server holds none of them, so a break-in to the API cannot reach or delete the backups.
- What a backup holds in the clear: traveler details and join codes. What it does not: passwords, sign-in tokens, reset links and two-factor secrets are hashed or sealed, and are not usable from a backup.
- A written restore procedure exists. It has not yet been rehearsed end to end, and we would rather say so than imply otherwise.
- Checking that last night’s backup ran is a manual step today. The job can report to a dead-man’s-switch service that alarms when reports stop; that alarm is not wired up yet.
- A second layer: Neon keeps its own short point-in-time restore window, for the “I broke it five minutes ago” case.
Who can see production
One person: Levi Johnson, the founder. There is no support team that can browse your roster — and there is no second pair of eyes checking that one person’s work, either; you should weigh both halves. Anyone added later will be under a written confidentiality obligation before they are given access, and this page will change when that happens.
What is not in place
A security page that lists only strengths is not much use to a buyer, so:
- Cordelle holds no SOC 2, ISO 27001 or comparable certification, and there is no third-party audit report to send you.
- There is no penetration-test report. Cordelle has not been tested by an outside firm.
- There is no uptime guarantee: no service-level agreement, no credit scheme, and no 24/7 support rota. The traveler and guide apps are built to keep working from the copy on the phone when our servers are not there, and that is the honest shape of the promise.
- There is no 24/7 security monitoring and no on-call rota. Alerting is what our hosting providers offer plus our own checks.
- There is no customer-facing audit log of who in your office viewed which traveler.
- There is no self-serve data export yet. Ask, and we produce a machine-readable copy by hand within 14 days.
- There is no bug-bounty program.
Each of these is a fact about a small company, not a plan to hide one. As they change, in either direction, this page changes.
Reporting a problem
If you find a security problem — in the apps, the dashboard, the API or this website — write to [email protected] with “Security” in the subject line. It reaches the one person who can fix it, and we would rather hear it from you than find out another way. Please give us a reasonable chance to fix it before publishing details. The Terms ask you not to probe, scan or load-test the service without permission; a report of something you stumbled on is welcome all the same.
If a breach ever affects data we hold for you, we notify your account owner by email within 72 hours of becoming aware, with what we know at the time and what we suggest you do — the commitment is in § 14 of the Data Processing Addendum.
In more detail
The formal version of this page is § 9 of the Data Processing Addendum, which also lists every company that touches the data and where it sits. What is collected, and for how long, is in the privacy notice. Questions about any of it: [email protected].