Fermentation Tracker · security
How we protect your brewery's data
The system holds your batches, stock, customers, invoices, attendance and customer signatures. Here is what protects them from outsiders, from other breweries and from mistakes.
Layers of protection
Each layer works on its own
From what the browser sees down to the database itself. A fault in one layer does not open the data.
Each brewery sees only its own data
Breweries are kept apart by the database itself, not only by the app. On every request it checks that you are a member of the brewery the data belongs to. Even if the app had a bug, the database would not hand over another brewery's data.
Row Level Security on every table
An automatic check on every change to the system
A test signs in as a user of one brewery and, in every table with brewery data, tries to read, change and delete another brewery's records. If even one row could be read, the test fails. The same test makes sure no new table is added without protection.
80+ tables · read, update, delete
Team roles
Owner, admin, brewer, sales and reader. Everyone can change only what belongs to their job, and a delivery driver confirms only the stops on their own run. The rules live in the database, not just on the buttons.
owner · admin · brewer · sales · reader
Signing in
Passwords are stored only as a hash the password cannot be read back from, so not even we know them. Sign-in attempts are limited, a Cloudflare check that you are not a robot guards signing in and signing up, and every sign-in and failed attempt is logged. The PIN on the attendance terminal locks for 10 minutes after 5 wrong tries.
bcrypt · Cloudflare Turnstile · sign-in log · PIN lock
Two-factor sign-in
Besides the password, a code from an app on your phone (Google Authenticator, Microsoft Authenticator, Authy). A stolen password is then not enough: the database releases the brewery's data only after the code. A brewery can require it of all owners and admins.
TOTP · checked in the database · required for managers
Encrypted connection
The app runs over HTTPS only and the browser remembers that, so an unencrypted version cannot be slipped in. The database is encrypted on disk too.
HTTPS + HSTS · AES-256 encryption at rest
Protection in the browser
The app cannot be embedded in another site, so nobody can trick you into a fake click. The browser does not guess file types and does not pass addresses with secret links, such as a customer's stock offer, on to other sites.
X-Frame-Options · CSP · nosniff · Referrer-Policy
Files and signatures
Scanned invoices, customer signatures and incident photos are kept in private storage. They have no public address and only members of your brewery can open them.
private storage per brewery
Change history
Changes to important records are logged: who changed what and when. Issued documents can no longer be rewritten; they are corrected with a credit note.
change history · locked documents
Daily backups outside the database
Every night the database and all files are backed up to a separate provider in the EU. The backup is encrypted with a key that none of the providers holds. Before it is stored, each backup is automatically restored as a test and checked that every record is there. Daily backups are kept for 30 days, monthly ones for 12 months.
nightly · encrypted · EU · test restore
Secret keys stay on the server
Keys to the database, e-mail and AI never leave the server. The browser only gets a public key, which opens nothing without signing in and the database rules.
keys kept out of the browser
Security updates
GitHub automatically watches the libraries the system is built on and warns as soon as a vulnerability becomes known. Security fixes go out first, and every change passes the full set of automated tests before it is deployed.
Dependabot · automated tests before every deploy
Daily limits
A safeguard against misuse
Some features cost money every time they are used. A limit protects against a stolen account and against a bug stuck in a loop. It counts the last 24 hours per brewery.
| Feature | Limit | Once reached |
|---|---|---|
| Reading a supplier invoice with AI | 50 / 24 h | The document can be entered by hand |
| E-mails to customers (documents, reminders) | 200 / 24 h | Sending waits until the next day |
GDPR
Where your data is
The data is stored in the European Union. Some providers are US companies, so transfers are protected under the GDPR: by the EU – US Data Privacy Framework or by standard contractual clauses.
| Provider | Where | What for |
|---|---|---|
| Supabase | EU – Frankfurt | Database, sign-in, files |
| Vercel | EU – Frankfurt | Running the app |
| Resend | EU – Ireland | Sending e-mails with documents and notices |
| Cloudflare | EU + global | Encrypted backups in the EU (it cannot read them), bot check on Cloudflare's global network |
| Anthropic | USA | Reading a supplier invoice with AI, only when you use it |
- DPAA data processing agreement is ready in Slovak, Czech and Romanian. I will send it on request.
- 48 hIf your data were ever breached, we would tell you within 48 hours of finding out and help you report it to the authority. The procedure is written down in advance.
- 30 daysWe tell you 30 days in advance before adding or replacing a provider.
A question about security?
If you want to ask how the system handles your data, or you have noticed something suspicious, write to me.