Inspiration
Sharing a patient record today is binary — a regulator, insurer, or researcher either gets the full chart, or gets nothing. GNU Health, real open-source hospital software adopted by the UN as a Digital Public Good and deployed in national health systems across Argentina, India, Jamaica, Laos, Cameroon, and Suriname, has no way to prove one narrow fact about a patient — a vaccination status, a lab result, a critical flag — without exposing the entire record. We built Chart to add exactly that missing piece, using Midnight's zero-knowledge proofs.
What it does
Chart adds a real "Request Disclosure" action to GNU Health's own patient record view. A clinician or institution commits a patient's vaccination, lab result, and critical-flag data as cryptographic bundle commitments — the raw data never leaves the hospital's system. The institution then issues a scoped, expiring, revocable disclosure token to a specific outside identity — a regulator, insurer, or researcher — limited to exactly the bundle category they need. That external party, using a standalone verifier app with zero access to the hospital system, runs a real zero-knowledge proof and receives back one thing: pass or fail. Nothing else about the record is ever disclosed.
How we built it
- Contracts: 7 Compact circuits (submitRecordBundle, withdrawRecordBundle, issueDisclosureToken, revokeToken, and three typed verify circuits — verifyVaccinationBundle, verifyLabResultBundle, verifyCriticalFlagsBundle), 52 passing tests, real compiled proving/verifying keys for each.
- Bridge service: a Node/TypeScript service wrapping the Midnight SDK, deployed against a persisted, stable contract address (survives service restarts by rejoining rather than redeploying).
- Tryton module: a custom GNU Health module (
health_midnight_disclosure) adding a real "Request Disclosure" action to the patient form, pulling that patient's actual vaccination/lab/critical-flag data from GNU Health's own database. - Standalone verifier app: a separate frontend an external party uses to check a disclosure — generates its own identity locally, never touches the hospital system.
- All demo data is GNU Health's own official synthetic demo dataset
(
gnuhealth-50-demo) — no real patient data was used anywhere.
Challenges we ran into
- A duplicate WASM module bug:
midnight-js-protocolpinned an older, separately-loaded copy ofonchain-runtime-v3than our own dependencies, causing aninstanceofmismatch (expected instance of StateValue) on every real circuit call. Root-caused by tracing the exact package pin, fixed by forcing a single resolved version tree-wide via an npm override. - A silent
nullrejection: Midnight'slevelPrivateStateProviderunconditionally rejects a legitimately-storednullprivate state — fixed by using{}instead. - WSL2 networking:
host.docker.internaldoesn't route into the WSL2 network namespace where our bridge listens — fixed by using WSL2's own interface address directly. - A Tryton UI dead end: clicking a patient's name in the list view follows
a
many2onerelation to an unrelatedparty.partyrecord, not the actual patient record — traced by reading Tryton's own client source, fixed by targeting the list row itself. - Contract address instability: the bridge deployed a fresh contract on every restart. Fixed by persisting the deployed address and having every subsequent startup rejoin the existing contract instead.
Accomplishments we're proud of
A complete, honest, end-to-end chain: real hospital software, real synthetic patient data, real compiled circuits, a real cross-language integration (Python/Tryton to TypeScript/Midnight), and a real independent verifier identity that never touches the hospital system — including real on-chain rejection of tampered data and out-of-scope access attempts.
What we learned
Integrating a mature, real-world open-source application is a genuinely different kind of challenge than building a privacy layer from scratch — most of the hardest problems here were in the seams between systems (Python and TypeScript, WSL and Docker, an unfamiliar ORM and an unfamiliar ZK runtime), not in the zero-knowledge design itself.
What's next
Real credential issuance for institutions (currently a hackathon-scope simplification), a fully in-UI token-issuance flow inside Tryton (currently one step still requires a direct API call), and dynamic Merkle-based supplier/ institution verification in place of the current pre-verified-flag approach.
Built With
- compact
- docker
- express.js
- gnu-health
- midnight
- node.js
- postgresql
- python
- react
- tryton
- typescript
- zero-knowledge
- zk-snarks

Log in or sign up for Devpost to join the conversation.