Skip to main content
Mohamed Noor
Back to projects
Healthcare and fintech platformsExample project

Clinician-facing records platform

Role-aware interfaces for a patient records product, where what a user can see depends on their relationship to the record and every read is auditable.

Role
Front end and API
Period
2024 to 2025
Stack
  • React
  • Next.js
  • Node.js
  • PostgreSQL
  • TypeScript

This is a seeded example project, not client work. It is here so the structure of a case study is right from day one, and it is replaced before this site goes live.

Measured

  • Enforced server-side

    Access rules

    Every query scoped in the repository layer, not in the view

  • Every record read

    Audit coverage

    Append-only log written in the same transaction as the read

  • All authorization logic

    Test coverage

    Unit tests on the permission resolver, run in CI

Problem

Clinicians needed a fast view of a patient record, but not every clinician was allowed to see every field, and the rules depended on the viewer's relationship to the patient rather than on a flat role.

The existing prototype resolved permissions in the interface, which meant the API would return data the screen then chose to hide. Anyone reading the network tab could see everything.

Approach

Permission resolution moved to the server and into the data layer. The API cannot return a field the viewer is not entitled to, so the interface never has to be trusted to hide anything.

The rules were written down and turned into unit tests before the screens were built, so the edge cases were argued about while they were still cheap to change.

  • Authorization resolved in the repository layer, never in a component
  • Rules captured as tests before any interface work
  • Deny by default: a new field is invisible until a rule grants it

Architecture

Next.js front end against a Node API over Postgres. Every query is scoped by the viewer at the point of access, so there is no code path that can forget.

Reads and writes to a record append to an audit table inside the same transaction, which means a successful read cannot exist without its log entry.

  • Postgres row scoping applied in one place
  • Audit writes share the transaction with the operation they record
  • Personal data kept out of logs and error reports

Outcome

The team could answer who had seen a record and when, which they could not do before.

Adding a new field became a two-line rule change plus a test, rather than an audit of every screen that might display it.