Skip to main content

Data flows

The architecture in one sentence​

MedJot is local-first: clinical data is created, stored and used on the device, and the server exists for authentication, licensing, support and optional AI — not for clinical storage.

What never leaves the device​

Held in browser local storage and an on-device IndexedDB database:

Autosave writes to the device only. There is no upload, no server-side backup and no sync of report content between devices. We hold no copy and have no mechanism to retrieve one.

What crosses the network, and when​

DataWhenDestination
Authentication and refresh tokensSign-in, and on session refreshGoogle Firebase
Subscription and licensing statusOn load and periodicallyMedJot API
Usage counters — a count and a dateOn starting a reportMedJot API
Account profile and consent answersWhen set or changedMedJot API
Redacted clinical summaryOnly when a clinician runs an AI featureMedJot API → Google Gemini
Report content, in memory for ≤10 minOnly on an explicit device transferMedJot API
Saved templatesWhen a user saves oneMedJot API
Support enquiriesWhen sentMedJot API
Product analytics eventsOnly after explicit opt-inMedJot API + Google Analytics
Payment detailsAt checkoutStripe directly — never through us

The AI path in detail​

This is the main route by which clinical content leaves a device, so it warrants precision:

  • Triggered only by a clinician pressing the button on an AI feature. Nothing happens in the background.
  • The request is assembled from structured application state, not from the report text on screen — meaning the content sent is an enumerable set of fields rather than arbitrary screen content.
  • Redaction runs on both the client and the server before transmission: emails, UK phone numbers, NHS numbers, postcodes, dates of birth, and names introduced by a title or a relationship word are stripped. The patient is referred to only as "Pt".
  • Neither the request text nor the response is stored. We log the feature name, token counts and cost — for billing and abuse prevention — and nothing else.

How the redaction is implemented​

Worth stating precisely, because "we redact PII" is a claim reviewers are right to press on:

PropertyImplementation
Two independent passesIn the browser before the request is made, and again on the server before the prompt is assembled. The client pass means identifiable text does not cross the network; the server pass exists because a server must not trust a client's assurance.
No drift between themThe two copies of the ruleset are run against a shared corpus by an automated test that fails the build if their output differs at all.
Whole-payload sweepThe request object is walked recursively and every string in it is redacted, rather than a maintained list of fields being cleaned. A field added later is covered by default.
Identifiers removed unconditionallyNHS number, phone, email, postcode and date-of-birth stripping applies on every AI route, in every mode, including inside observation blocks.
Name handling is tuned per routeNarrative routes additionally collapse any capitalised word pair to initials. Diagnostic routes do not, because collapsing clinical terminology degrades output and pushes users toward the least-protective feature. The identifier rules are unaffected.
Output redactionThe safeguarding tool redacts the model's response as well as the request, and its prompts forbid producing a full name.
Bounded, closed-vocabulary inputsFree-text lengths and conversation turns are capped; category fields accept only values from a fixed list, and drop anything else rather than sanitising it.
Tested against regression and ReDoSTests assert identifier removal, zero false positives on a standard set of vitals, the specific parsing traps the rules exist for, and linear-time behaviour on adversarial input.

The full rule-by-rule account, with worked examples, is in What gets sent, and what doesn't.

warning

Redaction is a best-effort heuristic, not a guarantee. It is pattern matching rather than named-entity recognition, and cannot reliably catch a name typed into free text with no surrounding cue. It is a defence-in-depth layer over the actual control, which is the product's standing instruction to clinicians to keep patient-identifiable information out of MedJot entirely — see Privacy and governance.

The device transfer path​

Report content is sent to our server, held in memory only — never written to disk or a database — under a one-time code for a maximum of 10 minutes, then deleted automatically. Users can delete it sooner. See Device transfer.

What we hold about a user​

Account record: name, email, phone, month and year of birth, country and county, role and sector, account creation and last sign-in dates, Premium status and Stripe customer reference, trial usage, daily report count and date, saved templates, consent answers, and a small set of hashed anti-fraud signals.

Not held: day of birth, employer, trust, station, professional registration number, address, town or postcode — none of which is collected. And no clinical content of any kind.

Anti-fraud signals​

A deliberately short list: a random browser-generated device identifier stored as a one-way hash; a salted one-way hash of the IP address — the address itself is not stored; a normalised form of the email address; and flags for automatically-generated-looking addresses or names.

No browser fingerprinting, no tracking pixels, no third-party trackers. Retained 12 months from last sign-in.

Retention​

DataRetention
Clinical data on the deviceUntil the user clears it. Not ours.
Device transfer payloads10 minutes, in memory, then deleted
Account, billing and template dataLife of the account, or until deletion is requested
AI usage logs — feature, tokens, cost; never contentCurrently indefinite, for billing and abuse prevention
Detailed analytics events (opt-in only)Up to 90 days, or until opt-out
Anonymous daily analytics totalsIndefinite — no identifier, not linked to anyone
Anti-fraud device and IP hashes12 months from last sign-in
Support enquiriesAs long as needed to administer them

Analytics, if you are assessing it​

Off unless the user opts in. Events come from a closed catalogue: every parameter is an enum, a boolean or a bounded integer. There is no free-text field anywhere in the system — not filtered, but structurally absent. The server revalidates every event against that catalogue and discards anything unrecognised.

Attribution — role, sector, region, entitlement, organisation, platform — is added server-side from the account record; the browser never sends it, so it cannot be spoofed.

No account identifier is ever sent to Google. Advertising features, Google Signals and ad personalisation are all disabled, and IP is anonymised. If the user has not opted in, the Google analytics code is never loaded.

Opting out purges that user's detailed event log.

Data residency​

Our infrastructure is UK-hosted. Google (Firebase, Gemini) and Stripe may process data outside the UK and EEA as part of their own global infrastructure, under their respective data protection commitments. See Subprocessors.

The consequence for inspection policy​

Because there is no clinical content in transit, decrypting MedJot yields no clinical visibility — while placing authentication and refresh tokens in front of the inspecting appliance. See TLS inspection.