Architecture and workflow documentation for Amati, a personal health record platform built on HL7 FHIR R4. Solo-built, currently in private beta.
The product repository is private — it handles ePHI (electronic protected health information) architecture. This repo shares the parts that can be public: how the system is designed, how it defends health data, and how it gets built.
Author: Patricio Gómez — Senior Full Stack Engineer LinkedIn · GitHub
Diagrams are labeled in Spanish. Each section below explains the content in English.
Amati is built end to end by one engineer using an agentic AI workflow — not autocomplete, but a structured system of specialized agents and custom commands wired into the development lifecycle, with explicit human approval gates at the points that matter.
The three diagrams below document that system. They are the reason this repo exists.
~20 specialized Claude Code agents organized like a company: strategy, product, technical architecture, QA & security, and operational execution.
Two design decisions worth calling out:
- Model routing by task cost. Opus for strategic and architectural reasoning, Sonnet
for implementation-level work, Haiku for narrow mechanical tasks (
dev-junior, capped at ≤2 files). Capability is matched to the job instead of defaulting to the largest model. - Adversarial roles by design.
adversarial-qaactively attempts JWT bypass and ePHI leakage;ciso-agentowns HIPAA/ePHI review;code-reviewerchecks guards and audit trail. The system is built to argue with itself before code reaches a pull request.
18+ custom slash commands covering the full lifecycle — from /start-issue and /spec
through /crear-endpoint and /generar-tests, into /qa, /amati-review,
/security-review, and /create-pr.
Each command carries an explicit trigger condition (when to use it), which is what turns a
pile of prompts into a repeatable process. /amati-review is domain-specific: it checks
ePHI handling, authorization guards, and audit trail on every pre-merge diff.
The end-to-end path of a single user story, from issue to merge.
The important detail is where the human gates sit (marked ⏸): the founder approves the plan before implementation begins, and approves push and merge at the end. Agents do the work in between — planning depth is chosen automatically based on whether the change touches FHIR or ePHI — but no code reaches the default branch without human sign-off.
Automation is a means here, not the goal. Knowing where not to automate is part of the design.
Logical view with explicit trust boundaries: public zone, authenticated zone, and the internal core.
- web-app (Next.js) — specialist-facing, with a BFF layer: the access token never reaches browser JavaScript; the session travels as an httpOnly cookie and Server Actions hold the token server-side.
- mobile (Expo / React Native) — patient-facing, OAuth2 with PKCE, tokens in SecureStore.
- API (NestJS) — FHIR R4 over JSONB, guards in cascade (JwtAuth → Roles → Scopes), audit interceptor, ePHI sanitizer.
- Keycloak — OAuth2/OIDC, FHIR scopes, TOTP MFA.
- PostgreSQL — application data and identity data in two isolated databases, with field-level encryption via pgcrypto.
The boundary that matters most: the browser never holds an access token. Everything that touches health data crosses a guard cascade before it reaches the FHIR layer.
Defense in depth across five layers, with the specific threat each layer blocks:
| Layer | Control | Blocks |
|---|---|---|
| 1 · Perimeter & auth | OAuth2 PKCE S256, JWT, TOTP MFA | JWT bypass, brute force, credential stuffing |
| 2 · Authorization | Roles / Scopes / Org guards, fail-closed | Role escalation, scope abuse |
| 3 · Multi-tenant isolation | Mandatory tenantId, 404 anti-enumeration | Cross-tenant access, enumeration leaks |
| 4 · Consent | Active-consent check on every access, no cache | Access without consent, revoked-but-still-reading |
| 5 · Encryption & DB isolation | pgcrypto AES, isolated databases, SSL required | DB breach exposing readable identifiers |
Cutting across all five: an append-only audit log — action, resource type, user, org, scopes, changes — that is never updated or deleted, aligned with Mexico's NOM-024 standard for health record systems.
TypeScript · NestJS · PostgreSQL (JSONB + pgcrypto) · TypeORM · Keycloak · Next.js · React · React Native (Expo) · Docker · GitHub Actions · HL7 FHIR R4
These diagrams are versioned SVG in the product repo, next to the code they describe, so
architecture changes show up in git diff like anything else. A pre-push hook runs a
staleness check against a machine-readable diagram↔source mapping: if a change touches the
source a diagram reflects and the diagram is not updated in the same change, it warns.
Documentation drifts when nothing forces it to keep up. This is the forcing function.