Quorum

Infrastructure and security

Every chapter runson its own system.

Its own server, its own database, its own files, its own keys. No other chapter shares any of them.

Mission Control THE LIST OF CHAPTERS · THEIR VERSIONS · THEIR HEALTH ServerITS OWN WORKERDatabaseITS OWN D1FilesITS OWN R2 BUCKETKeysITS OWN SECRETS YOUR CHAPTER ANOTHER CHAPTER A THIRD CHAPTER NO CONNECTIONNO CONNECTION Mission Control VERSIONS · HEALTH ServerITS OWN WORKERDatabaseITS OWN D1FilesITS OWN R2 BUCKETKeysITS OWN SECRETS YOUR CHAPTER ANOTHER CHAPTER A THIRD CHAPTER NO CONNECTION

Three chapters, three separate systems. Each one reports only its version and health to Mission Control.

One chapter, one system

Nothing is shared between chapters.

Most software keeps every customer in one database and separates them with rules in the code. Quorum gives each chapter a separate system.

ABC
Most softwareOne shared databaseRules in the code keep customers apart. One wrong rule can show one customer another’s data.
ABC
QuorumOne system per chapterThere is no shared database, so there is nothing to cross.
  • Its own serverCloudflare Worker
  • Its own databaseCloudflare D1
  • Its own filesCloudflare R2
  • Its own keysDerived per chapter
  • Its own addressHost-only sessions
  • Its own regionSix to choose from
Technical detail
Compute
One Cloudflare Worker per chapter. The server is written without frameworks and has no third-party packages in production.
Database
One Cloudflare D1 (SQLite) database per chapter. No query can span chapters because no chapter’s server holds a connection to another chapter’s database.
Files
One Cloudflare R2 bucket per chapter.
Keys
Each chapter’s encryption keys and its service token are derived with HKDF-SHA-256 from a platform root, with the chapter’s name in the derivation. A chapter’s server never holds the root, so one chapter’s token is refused by every other chapter.
Sessions
HttpOnly, Secure, SameSite=Lax, and host-only on platform addresses. A browser never presents one chapter’s session to another chapter’s server.
Region
The database and the bucket are created with a location hint read from the chapter’s time zone: wnam, enam, weur, eeur, apac or oc.
Provisioning
An automated pipeline creates a new chapter’s server, database, bucket and keys. Nothing is typed on a chapter’s server by hand.

Between chapters

What passes between chapters, and what never does.

A member can belong to two chapters, and two chapters can host one event. A separate system, Mission Control, carries a short, fixed list of facts between them. If it is unreachable, every chapter keeps working.

One sign-in, two chapters

The second chapter does not accept the first chapter’s session. It accepts a pass signed by Mission Control, then opens a session of its own.

Chapter Awhere you sign in
Mission Controlsigns the pass
Chapter Byour other chapter

Sign-in pass

From
Chapter A
For
Chapter B and no other
Expires
2:00
Works
once

Used

The pass names the email, the chapter that checked it and the one chapter it is for. It expires in two minutes and works once.

What Mission Control knows

The list of chaptersEach chapter’s versionEach chapter’s healthOne-way codes of sign-in emailsShared event detailsSupport tickets

Never

RostersMessagesPhotosPaymentsPasswords

What a shared event passes

Title, date and venueSeats set asideReplies and guests’ names

Never

Email addressesPhone numbersHome addressesMoney

What Quorum’s support staff see

  • Standing in the chapter
  • Forums
  • App version
  • Email delivery status
  • Messages
  • Email contents
  • Passwords

Every operator action is logged for 400 days.

Technical detail
Control plane
A separate Worker and D1 database. It holds the chapter registry, release and health records, deploy pins, the operator activity log and the discovery index. It is off every member request path.
Discovery index
HMAC-SHA-256 of each sign-in email and mobile number, used to send a sign-in or a text reply to the right chapter. Raw emails and numbers are not stored.
Sign-in pass
Format qp1.payload.signature, ECDSA P-256 over SHA-256. The payload names the email, the vouching chapter, the target chapter, the issue time, a two-minute expiry and a one-time id. The target chapter verifies with Mission Control’s public key and records the id on first use, so a replay is refused. A refused pass counts against the same limit as a wrong password.
After the pass
The phone holds one session per chapter, reads each chapter from that chapter’s own server and combines them on the phone. The chapters never read each other.
Co-host broker
A chapter posts to Mission Control with its own bearer token. Every message is numbered, and a chapter ignores a number older than the one it holds. A reply carries a name, a title and company, the answer, the party size, the guests’ names and dietary needs. Replies are relayed and not kept on Mission Control. Each chapter bills its own members through its own Stripe account.
Support access
Mission Control reaches a chapter’s support routes with that chapter’s own derived token. The chapter’s server answers with the support card, which also says whether a password is set and lists recent emails by subject and status. Mission Control displays the card and stores none of it. Operators sign in with a password or a passkey.

Encryption

Private conversations can be read only by the people in them.

Three layers of encryption. The third is made on the member’s own device, with keys the servers never hold.

3 · End to end
Senderholds the key
1 · In transit
Quorum’s serversno key
1 · In transit
Recipientholds the key
Database and files2 · In storage

Try it

Type a message. The middle box shows what Quorum’s servers would store. This is real AES-256-GCM, running in your browser with a key made on this device.

1 · The sender’s phone

Encrypted here, before it leaves the phone.

2 · Quorum’s servers

chat
forum chat 31
from
member 214
sent
10:42 AM
size
62 bytes
message
q7Hk0wZ3vX1mPf2a.Jx8tQ0dYb2uV5nC1rL9sKe4hWm7pT3aZo6gUiB0yNfXc2RvMq8EdL1jSw5kHt9PzOa4GuY7bC3nVxI6mQe0

Visible to the servers: who, when, how large. Never the words.

3 · A phone in the chat

Board dinner moved to 7. Keep it in the forum.

Opened with the chat’s key, which only the devices in this chat hold.

Who can read a message

Private chats1Direct messages, forum chats, alumni chats, groups a member started
The people in the chatCan read
Your chapter’s officeNo key
QuorumNo key
A copy of the databaseEncrypted bytes
Chapter chatsAnnouncements, the Office Line, groups the office runs, event groups
The people in the chatCan read
Your chapter’s officeCan read
QuorumNot shown to staff2
A copy of the databaseEncrypted bytes

1 A private chat turns end-to-end encrypted once everyone in it has a version of Quorum that can read one, or after the chapter’s waiting period, once someone in it has. Earlier messages stay as they were.
2 The key is on the chapter’s server, so this is a rule in the software and not a missing key.

A member’s keys on a new device

  • New iPhoneArrive through iCloud Keychain
  • New AndroidArrive from the old phone or its backup
  • New browserScan a code, or use a passkey
  • Every device lostA 28-character recovery code
  • No code eitherReset. Quorum cannot recover the history
Technical detail
Key agreement, signatures
NIST P-256 ECDH and ECDSA with SHA-256 (FIPS 186-5, SP 800-56A).
Key derivation
HKDF-SHA-256 (RFC 5869).
Content encryption
AES-256-GCM with a 96-bit random nonce and a 128-bit tag (SP 800-38D).
Key wrapping
HPKE base mode: DHKEM(P-256, HKDF-SHA256), HKDF-SHA256, AES-256-GCM (RFC 9180).
Photos and files
Encrypted on the device before upload, as segmented AES-256-GCM in one-megabyte segments (the STREAM construction). A file altered or cut short fails to open.
Implementations
WebCrypto in browsers, CryptoKit on iOS and the platform providers on Android. No primitive is implemented by hand.
Chat keys
A 32-byte secret per chat, replaced at every membership change and wrapped with HPKE to each member’s public key, so a person who leaves cannot read what follows. Each key announcement is signed by its creator and chained to the one before it.
Devices
Each device has its own P-256 key and a certificate signed by the member’s account key. The server cannot add a device, because it cannot produce that signature.
Messages
Each message is signed by its sender. A server can delay or withhold a message. It cannot alter or invent one.
Private chats
Direct messages, forum chats, alumni chats, groups a member started and groups with Confidentiality Covered on.
In a browser
The phone apps take new code only through a store release. A web page is sent on each visit, so in a browser the encryption depends on the server sending honest code. Every web messenger has this limit, and the app says so in the chat.
What stays visible
That a chat exists, who is in it, when a message was sent and how large it is. A record made from a chat, such as an event or a payment, is a chapter record.
In transit
TLS on every host. Plain http is redirected, and Strict-Transport-Security holds a browser to https for one year.
Stored encryption
Per-chat key = HKDF-SHA-256(chapter key, chat id). The chat and author ids are bound as additional data, so a ciphertext moved to another row fails to open. With no usable key the server refuses the write and never stores plain text.
Review
The way the app combines these is written down as a specification and has had outside review.

Signing in

How members sign in.

A passkey or a password, with an optional code by text. A stolen copy of the database cannot be used to sign in as anyone.

Passkey

Face ID, Touch ID or the device PIN. It answers only to the real site, so a fake page gets nothing.

Password

Stored only as a salted hash. Nobody at the chapter or at Quorum can read it.

Code by text

An optional second step. Six digits, good for ten minutes.

Eight wrong guesses in 15 minutes pause sign-in for that email.

The database holds only hashes. A copy of it signs nobody in.

  • A password reset signs out every device
  • Face ID lock in the phone apps
Technical detail
Passkeys
WebAuthn, on the web and in the phone apps, verified on the server with WebCrypto: the challenge, the origin, the relying-party hash, user presence, the signature, and a counter that only moves forward.
Password hashing
PBKDF2-SHA-256, 100,000 iterations, a random salt per password. Sign-in does the same work for an unknown email, so neither the answer nor its timing reveals who has an account.
Sessions and links
Random tokens stored as SHA-256 hashes. Emailed links are single use.
Two-step code
Five wrong tries cancel a code. The check of the code and the new session are written in one database transaction, so a sign-out of every device cannot be raced.
Rate limit
Eight failures for one email, or thirty from one network address, in 15 minutes. Each attempt is recorded before it is counted, so parallel guesses cannot pass the limit together.
Email change
A new password alone cannot move an account to another email. It takes the established password or a code sent to the proven phone.
App lock
Face ID or the passcode when the app opens, and again after two minutes in the background, when the member turns it on.

Inside your chapter

Who can see what inside a chapter.

A forum opens only to its own members. The chapter office cannot open it, and neither can the top administrator account.

  • Officers see only what they are grantedView or manage rights for each console area, checked on every request.
  • Every console change is recordedWho and when, in a log that cannot be edited or deleted.
  • Screenshots can be blockedIn the phone apps, by the chapter’s own switch.
  • Your records stay yoursExport everything at any time. A member can ask for their account to be deleted.
Technical detail
Forums
Membership is checked on every request. An account with no seat in a forum is refused, whatever its role.
Audit log
One append-only row per successful change made in the console, never updated and never deleted. Finance keeps a second ledger of its own.
Deleting an account
A member asks from the app. When the office approves, sign-in ends on every device and the member’s contact details are removed.
The app switcher
The phone apps cover their content in the app switcher.
If a chapter leaves
The export stays available for 60 days. Then the chapter’s system and its data are deleted, and the backups age out.

The application

How the software is protected.

Every request passes the same four checks before any data is read.

  • No third-party code on the server
  • No outside scripts in the app, except Stripe’s payment form
  • Logs record no private values
  • Phone apps update only through the App Store and Google Play
Technical detail
Response headers
Strict-Transport-Security: max-age=31536000; includeSubDomains · X-Content-Type-Options: nosniff · Referrer-Policy: same-origin · X-Frame-Options: SAMEORIGIN with frame-ancestors 'self' · object-src 'none' · base-uri 'self'
Script policy
Every script element needs a per-response nonce (strict-dynamic). The sign-in pages also forbid inline event handlers.
Cross-site requests
SameSite=Lax cookies, plus a check of Origin and Sec-Fetch-Site ahead of routing.
Webhooks
Stripe HMAC signatures, Resend (Svix) signatures and Twilio request signatures, compared in constant time. A route with no secret configured refuses every request.
Photos and files
The session and the member’s section are checked on every media request. An upload uses a single-use, short-lived grant for one object of one declared type, and the grant token is stored as a SHA-256 hash.
Request size
JSON bodies are capped at 256 KiB unless a route names a larger budget.
Logs
Logs record which route failed and why. They do not record request addresses, which can contain private links, or the values a member typed.
Dependencies
The server has none in production. Advisories for the build tools and the phone app are checked on every change and again at release, and an unreviewed advisory stops the release.
Phone apps
New code arrives only through a store release. There is no over-the-air code update. Quorum sets the oldest app version a chapter accepts, so a version with a known flaw can be retired.

Payments

Card and bank numbers never reach Quorum.

Payments run on your chapter’s own Stripe account. Quorum never holds your members’ money.

Backups and recovery

How data is backed up and restored.

A chapter’s database can be returned to any minute of the last 30 days. A separate copy is kept every night for 90.

  • Backups hold no sessions or keys
  • Clean-up waits a week before it deletes
Technical detail
Point in time
The database keeps a continuous history for 30 days. A restore returns it to the minute before a mistake.
Nightly export
Every chapter’s database is exported each night and kept for 90 days, outside the live system. Sign-in sessions, emailed links and service keys are removed from the copy, so a backup cannot be used to sign in.
Restore drill
Each month the newest export of Quorum’s first chapter is restored into an empty database, with every link between records checked.
Clean-up
A file the system believes is unused is listed for a week before it is deleted.
Mission Control
Chapters do not depend on it to serve their members.

Releases

How a change reaches your chapter.

Quorum releases changes every day. No change goes to every chapter at once.

Technical detail
Database changes
Additive only. A new version adds tables or columns and never removes or renames one, so the previous version always runs against the newer database and a rollback is safe.
Rollback
Automatic after three failed checks of the live product. The pipeline then raises an alarm.
The order
The first chapter, at least six hours there, then the demo system, then every other chapter in groups of four. A failure on the demo system stops the release, and a failure in the first group stops the second.
Production access
A release reaches production only through the pipeline, from the main branch. The workflows that touch production refuse any other branch.
Version pins
A chapter can be held on a version for at most 14 days, with a recorded reason.

Providers

The other companies that handle chapter data.

  • CloudflareRuns each chapter’s server, database and files. Holds SOC 2 and ISO 27001 certifications.
  • StripeCard and bank payments
  • ResendEmail delivery
  • TwilioText messages
  • Apple, Google, ExpoPush notifications
  • AnthropicThe AI model behind the assistants
  • Intuit QuickBooksAccounting, when connected
What each one receives
Cloudflare
The chapter’s data, encrypted in storage with AES-256. Cloudflare holds SOC 2 and ISO 27001 certifications for these services.
Stripe
Payment details, typed directly into Stripe’s form.
Resend
The emails the chapter sends.
Twilio
A mobile number and the text, for members who turned texts on.
Apple, Google, Expo
The notification. For an end-to-end encrypted chat that is encrypted bytes and the words “New message”.
Anthropic
Only what a task needs. Anthropic does not train its models on it, and a chapter can connect its own account.
Intuit QuickBooks
Invoices and payments, only when the chapter connects its book.

Technical summary

The system on one page.

For the person who reviews the engineering

Architecture

Tenancy
One isolated stack per chapter: Worker, D1 database, R2 bucket, secrets and domain. No shared data tier.
Compute
Cloudflare Workers. One codebase, no frameworks, no third-party packages on the server.
Data
Cloudflare D1 (SQLite) per chapter, created in one of six regions. Cloudflare R2 for media.
Live updates
One Durable Object per chapter over WebSocket. It carries a signal that something changed. The data itself is read from the database.
Control plane
Mission Control, a separate Worker and database: registry, health, releases, the discovery index. Off the member request path.
Clients
iPhone and Android apps released through the stores, and the web app. One API.

Cryptography

Transport
TLS on every host, plain http redirected, HSTS for one year with subdomains.
At rest
AES-256 by Cloudflare for D1 and R2. AES-256-GCM by the application for chat text and travel documents.
End to end
P-256 ECDH and ECDSA, HKDF-SHA-256, AES-256-GCM, HPKE (RFC 9180). Per-chat keys replaced at every membership change. Signed messages, signed device certificates.
Passwords
PBKDF2-SHA-256, 100,000 iterations, per-password salt.
Tokens
Sessions, emailed links and upload grants stored as SHA-256 hashes.
Cross-chapter
ECDSA P-256 sign-in pass: two-minute expiry, single use, bound to one target chapter.

Operations

Recovery
Point-in-time restore for 30 days. Nightly exports kept 90 days, with credentials removed. A monthly restore drill.
Release
More than 11,000 automated tests, then the first chapter, a six-hour hold, the demo system, and the other chapters four at a time. Automatic rollback. Additive database changes only.
Audit
A permanent, append-only log of console changes in each chapter. A 400-day log of operator actions on Mission Control.
Access
Passkeys, optional two-step sign-in, per-area roles in the console, forums closed to everyone but their members.

Questions from your security reviewer?

Send them to us. We answer in writing, and we can go over any part of this page with your reviewer on a call.