Case files / PAN-142
Notes that freeze when signed
Practice management and clinical records for a physiotherapy practice, built so other disciplines can be added by configuration. It runs from the booking to signed notes with diagnosis and tariff codes, the account, a double-entry ledger, payroll, and lab and imaging exchange. Each rule that matters is checked by a script against the database, not by looking at the page.
Control flow
- Book: the diary refuses a double room
- Consult: note, codes, sign, freeze
- Order: lab or imaging goes out
- Results: matched exactly, or queued
- Bill: note lines become the account
- Ledger: postings balance to the cent
Industry: Medical · Stack: Next.js 16 · TypeScript · PostgreSQL · Prisma · HL7 and FHIR · Seed species: Sinew
Problem
A practice’s records have to be right in three directions at once: clinically, for the patient; financially, for the account; and legally, for whoever reads them later. Most systems let a note be edited after the fact and let the bill drift from the note.
How it works
A signed clinical note is frozen. A correction is an addendum, never an edit. The database refuses a double-booked room. A double-booked practitioner is flagged instead, at the practice’s request.
The consultation note, the quotation and the invoice are copied from the same lines and match to the cent. An invoice is a draft until someone authorises it.
Lab and imaging orders go out, and results come back over HL7, FHIR and DICOMweb. A result that cannot be matched exactly waits for a person to match, reject or retry it. A clinician signs off each result before it is released to the patient.
ID numbers are encrypted at rest and masked on screen, and never sent to labs or imaging partners; the practice’s own file number goes instead. Every read of a clinical document is audited. Exported records are password-locked PDFs, and the password is not stored.
Method
Eleven verify scripts check the rules against the database. One books twelve appointments into the same slot at the same moment and checks that exactly one succeeds.
Billing modifiers were read from a scanned government notice. Four rates could not be confirmed, so they ship switched off, each with a note on what to check.
Built with AI: about thirty commits co-authored by Claude models. The agent never types passwords or one-time codes, so it never clicked through the newest screens; their logic is checked by scripts only.
What broke
The production build passed while pages failed at runtime: a server page imported helpers from a client module, and a client component dragged the database client into the browser bundle. The first admin had no staff profile, so their own staff page returned a 404.
Limitations
Not deployed yet. Payroll arithmetic is verified; its legal reading is not. The practice has tested a build, not run on one.
Next
Confirm the four rates that ship switched off and the tax tables, choose an SMS provider, then deploy.