What PharmaFlow stores, and who can reach it
This page describes what the system holds, where it is kept, for how long and who can reach it. It is not a privacy policy: it names no data controller, states no lawful basis and makes no legal commitments, because none have been written. It describes the software as built.
Not published yet
Two things a privacy notice needs do not exist yet, and this page does not invent them.
- A data controller. No legal entity and no registered address has been published, so none is named here.
- A way to make a data request. No address, form or phone number for asking to see, correct or remove data has been published.
Pharmacy records
For each company: its name, workspace address, TIN, phone number, email address, postal address, status (and, while it is suspended, the status it had before), plan, time zone and expiry window. For each branch: its name, phone number, city, sub-city, address, licence number, manager, status and time zone. For its look: its colours, a logo and a favicon.
Staff accounts
For each person who signs in: full name, email address, phone number, role, branch, status (invited, active or deactivated), language, the time they were last active, and a password kept only as an argon2id hash. These are pharmacy employees, not customers.
Sign-in sessions
Each sign-in creates a session record: a hash of the session token, when it expires, when it was last used, whether it was revoked, the IP address the sign-in came from and the browser’s user-agent text. The IP address is stored but no screen shows it. The Active sessions screen shows each account holder only a device name and the last-active time of their own sessions.
Pharmacy operations
Products and categories; suppliers with a name, contact email, payment terms and lead time; stock batches with batch numbers, expiry dates and unit costs; and every change to stock, with the staff member who made it and, for adjustments and counts, the reason they typed. For each sale: a sale number, the staff member, whether it was over-the-counter or prescription-only, its lines, the amounts, the payment method, a status and, if it was voided, when and by whom.
No customer or patient is identified
A sale has no customer field, no patient field and no prescriber, and the system never asks who the buyer is. Personal information could still get in through free text, which is not checked: the optional notes on a sale, the reason typed for a stock adjustment, and the names typed for products, suppliers and branches. PharmaFlow cannot promise that nobody has typed something personal into them.
What anyone can see
Anyone who knows a company’s workspace address can read its identifier (a UUID), name, workspace address, time zone, colours and logo, because its sign-in page loads them before anyone has signed in. The identifier is public, so do not treat it as a secret handle, and a workspace address is not a secret either. A company can add one logo and one favicon; they are kept in file storage on the same server.
Visitors to the public pages
The public pages count a few events: a page view, a button click or a question opened. Each is stored as a name, a short detail, the page language and a time, and nothing else: no IP address, no browser, no referrer and no identifier. While an event is being received, the caller’s address is counted in the cache for 60 seconds to limit abuse, as described under Protection against guessing. The table has no key, the application’s database role can only add rows to it, and the database refuses event names outside a fixed list.
Protection against guessing
To slow down guessing and abuse, each caller’s attempts to sign up, check an address during signup, sign in, change a password, send an analytics event, look up a workspace address or load a sign-in page are counted. The counter is a hash of a string that contains the caller’s IP address and, for sign-in, the company and email address. The hash has no secret key, so an IPv4 address can be recovered from it in seconds: treat it as the address itself. Counters are normally kept in the cache and expire within 15 minutes of the first attempt; those for events, workspace lookups and sign-in pages last 60 seconds.
If the cache is unreachable, the sign-up, address-check, sign-in and password counters are written to a database table instead, and those rows are deleted once they are a day old. Workspace lookups and events are counted in the cache only and are refused while it is down; loading a sign-in page is counted in the cache only and goes uncounted while it is down.
In your browser
Signing in sets one cookie, pf_session, which scripts on the page cannot read and which lasts as long as the session. Choosing a language sets another, pf_locale, which remembers it for a year. The home page also keeps one flag in the tab’s session storage so that a counter animation runs once, and the signup form keeps what you have typed in the same session storage, except the passwords, until the tab is closed. The application sets no other cookies.
Where it lives
The database, the cache and the file storage all run on one server. No analytics service, mail service, payment service or error-reporting service receives any of this, because the system uses none. The server may be rented from a hosting company, which this page does not name.
One outside party is involved in running the site: the certificate authority that issues the HTTPS certificate for each address. It learns the workspace addresses, and public certificate transparency logs list them.
Logs
The API writes a log line for each request: the method, path, status, duration and a request number. It does not record IP addresses or browsers. A workspace address typed into the finder is part of the path, so it appears there, and error lines can include a company’s id and a person’s id. This page does not cover logs kept by the web tier, the proxy or the host, and the deployment files set no retention period for any log.
Who can reach it
- Staff of a pharmacy can reach that pharmacy’s records only, and only what their role allows. The database separates companies from each other, not just the application.
- PharmaFlow’s operators use a separate console. It shows each company’s business record and branches (name, city, sub-city, status and manager), and how many people are on staff and signed in. It lists no sales, stock or staff accounts.
- Anyone with administrator access to the server or its database can read everything on this page, including session IP addresses. The application does not separately encrypt stored values; passwords and session tokens are kept only as hashes.
How long it is kept
- A session lasts 12 hours. Signing out, or suspending the company, revokes it, although a cached copy can keep working for up to 5 minutes. The session record, with its IP address, stays in the database for 30 days after it ends, and is then deleted.
- The Starter plan shows 90 days of history. Older records are hidden from view, not deleted.
- Nothing in PharmaFlow deletes a company, a person, a sale or a stock record. Deactivating, closing, archiving or discontinuing something hides it. Only product categories and branch price overrides can be removed.
- No backup is scheduled. The database runs in one container on one server, with no replica, so there is no second copy to recover from if that server is lost.
Written on 13 October 2026 from the database schema and the code. It describes the software as built and may fall behind it.
Back to PharmaFlow