Files
temetro/backend
Khalid Abdi 36461a5498 feat: patient blood type & phone + clinic location setting (v0.9.0)
Patient record:
- Add `bloodType` and `phone` to the patient model (schema, canonical types on
  both backend + frontend, zod validation). `phone` is a demographic field
  (reception can read/write); `bloodType` is clinical PHI, redacted for the
  reception role. Surface both in the record sheet, chat summary card, and the
  add/edit patient form. Migration 0033.

Clinic location:
- New org-scoped `clinic_settings` table (address/city/country + optional
  lat/long), service, and routes: GET /api/clinic/settings (any clinician) and
  PUT /api/clinic/location (owner/admin). Edited in Settings → Signing → Clinic
  location. Consumed later by the wallet app. Migration 0034.

i18n:
- Translate all new keys into every shipped locale (en/de/fr/ar/so) and document
  the "translate into every locale" rule in frontend/CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 22:07:27 +03:00
..
2026-06-17 20:50:09 +03:00

temetro backend

TypeScript + Express + Postgres API for temetro. Authentication is powered by Better Auth (email/password with verification, password reset, and multi-tenant organizations with role-based access control). Patient records are scoped to an organization (a clinic) and exposed over a small REST API that mirrors the frontend's Patient shape exactly.

Quick start (Docker)

docker compose pull          # fetch prebuilt images from Docker Hub (fast)
docker compose up -d         # db + backend + frontend — no setup needed

docker compose up --build instead builds from source (for development). The Compose file references the published khalidxv/temetro-backend and khalidxv/temetro-frontend images with a build fallback, so the same file serves both clinics and developers. Update with docker compose pull && docker compose up -d (see ../RELEASING.md).

No .env or manual secret generation is required: on first start the backend generates any missing secrets (BETTER_AUTH_SECRET, AI_CREDENTIALS_KEY) and persists them to a Docker volume, so they stay stable across restarts. Create a .env (from .env.example) only if you want to override something — your own auth secret, SMTP, etc.

Run only the API + database: docker compose up db backend. Browse the DB with Adminer: docker compose --profile tools up adminerhttp://localhost:8080.

Migrations are applied automatically on container start (node dist/migrate.js).

Local development (without Docker)

npm install
cp .env.example .env          # point DATABASE_URL at a local Postgres (localhost:5432)
npm run db:migrate            # apply migrations (drizzle-kit)
npm run dev                   # tsx watch on http://localhost:4000

Auth & schema workflow

The Better Auth tables are generated into src/db/schema/auth.ts from src/auth.ts. Re-run after changing auth config/plugins, then regenerate the SQL migration:

npm run auth:generate   # better-auth CLI -> src/db/schema/auth.ts
npm run db:generate     # drizzle-kit -> ./drizzle/*.sql
npm run db:migrate      # apply

API

All patient routes require a signed-in user (Better Auth session cookie) and an active organization; access is gated by the caller's clinic role.

Method Path Permission Notes
GET /api/patients patient:read list patients in the active clinic
GET /api/patients/:fileNumber patient:read one patient (404 if absent)
POST /api/patients patient:write create (409 if file number exists)
PUT /api/patients/:fileNumber patient:write replace the full record
DELETE /api/patients/:fileNumber patient:delete remove a patient

Other org-scoped resources follow the same pattern (CRUD, role-gated):

Resource Base path Permission Notes
Appointments /api/appointments appointment:* list / create / update / delete
Prescriptions /api/prescriptions prescription:* prescriber defaults to the signed-in user
Tasks /api/tasks task:* PATCH /:id for partial updates / the done toggle
Notes /api/notes — (author-scoped) private to the signed-in author
Activity GET /api/activity — (any member) audit feed of record changes
Analytics GET /api/analytics — (any member) computed clinic aggregates
Conversations /api/conversations — (participant-scoped) staff messaging; real-time over Socket.io
Notifications /api/notifications — (per-recipient) auto-generated; read-all + per-id read
Version GET /api/version — (public) running version + GitHub-release update check
Network GET /api/network — (public) detected LAN addresses for sharing the app

Real-time messaging and live notifications are delivered over Socket.io, attached to the same HTTP server; the handshake is authenticated with the Better Auth session cookie.

Auth endpoints (sign up / in / out, verify email, reset password, organizations & invitations) are served by Better Auth under /api/auth/*.

Roles

Role Patient access Prescriptions Lab results Clinic management
owner read / write / delete read / write / delete read / write full
admin read / write / delete read / write / delete read / write members, invitations, settings
doctor / member (clinician) read / write read / write / delete read / write
reception read / write (demographics)
pharmacy read read / write
lab read read / write

Environment

See .env.example. If SMTP_HOST is unset, verification / reset / invitation emails are printed to the server console instead of being sent — no setup required for local development.