# temetro backend TypeScript + Express + Postgres API for [temetro](../). Authentication is powered by [Better Auth](https://better-auth.com) (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) ```bash cp .env.example .env # set a strong secret: # openssl rand -base64 32 -> paste into BETTER_AUTH_SECRET docker compose up # db + backend + frontend ``` - Frontend → http://localhost:3000 - Backend → http://localhost:4000 (health: `GET /health`, auth health: `GET /api/auth/ok`) - Postgres → localhost:5432 Run only the API + database: `docker compose up db backend`. Browse the DB with Adminer: `docker compose --profile tools up adminer` → http://localhost:8080. Migrations are applied automatically on container start (`node dist/migrate.js`). ## Local development (without Docker) ```bash 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: ```bash 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 | Auth endpoints (sign up / in / out, verify email, reset password, organizations & invitations) are served by Better Auth under `/api/auth/*`. ### Roles | Role | Patient access | Clinic management | | --- | --- | --- | | `owner` | read / write / delete | full | | `admin` | read / write / delete | members, invitations, settings | | `member` (clinician) | read / write | — | | `viewer` | read | — | ## 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.