mirror of
https://github.com/temetro/temetro.git
synced 2026-07-26 11:58:14 +00:00
964c069236
- emailAndPassword.requireEmailVerification = false so users can sign in immediately; verification emails are still sent and /verify-email still works. Flip back to true to make it mandatory later (TODO noted in code). - Add backend/CLAUDE.md documenting stack, commands, the auth/schema generation workflow, and runtime gotchas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.5 KiB
3.5 KiB
CLAUDE.md
Guidance for Claude Code when working in backend/. See the root ../CLAUDE.md for the project
vision and README.md here for run/setup instructions.
What this is
The temetro API: TypeScript + Express 5 + Postgres (Drizzle ORM), with authentication and
multi-tenant clinics via Better Auth. Serves the ../frontend app. ESM ("type": "module"),
Node ≥ 20. This is its own git repo — commit changes here with the
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> trailer.
Commands
npm run dev # tsx watch on http://localhost:4000
npm run build # tsc -> dist/
npm run typecheck # tsc --noEmit
npm run auth:generate # Better Auth CLI -> src/db/schema/auth.ts (re-run after auth config changes)
npm run db:generate # drizzle-kit: schema -> ./drizzle/*.sql migration
npm run db:migrate # drizzle-kit: apply migrations (local dev)
npm run db:apply # node dist/migrate.js — runtime migrator (used by Docker)
No test runner is configured. Verify by running the stack (docker compose up) and curling, or
npm run dev against a local Postgres. See README.md.
Architecture
src/auth.ts— the Better Auth config (the CLI auto-discovers it). Email/password, organization plugin (clinics) with custom RBAC fromsrc/lib/access.ts(owner/admin/member/viewer+ apatientresource). Mounted insrc/index.tsviatoNodeHandler(auth)at/api/auth/*.src/db/—index.tsis the Drizzle client (no schema passed; we use the core query builder).schema/auth.tsis generated by the Better Auth CLI;schema/patients.tsis hand-written and references the generatedorganization/usertables.src/services/patients.tsmaps DB rows ⇆ the canonicalPatientshape (src/types/patient.ts, mirrors../frontend/lib/patients.ts).src/routes/patients.tsis org-scoped CRUD, gated bysrc/middleware/auth.ts(requireAuth→requireOrg→requirePermission).src/lib/email.ts—sendEmaillogs links to the console when SMTP is unset.
Gotchas / conventions
- Schema generation order (circular bootstrap):
auth.ts→db/index.tsmust NOT pull in the patient schema, so the Better Auth CLI can loadauth.tsto (re)generateschema/auth.ts. After any auth/plugin change:npm run auth:generate→npm run db:generate→npm run db:migrate. - Express 5 needs a named wildcard:
app.all("/api/auth/*splat", …), and the Better Auth handler must be registered beforeexpress.json(). - Secure cookies key off
BETTER_AUTH_URLscheme (https), notNODE_ENV— otherwise login breaks overhttp://localhostin the production-mode Docker stack. - Rate limiting needs a client IP; behind no proxy we backfill
x-forwarded-forfrom the socket inindex.tsso it still applies. - Env:
src/env.ts(zod) treats empty strings as unset (compose passes${VAR:-}as"") and has dev defaults so the CLIs can load the config offline. - Email verification is wired but NOT enforced at sign-in
(
emailAndPassword.requireEmailVerification: falseinauth.ts) — re-enable by flipping it totrue(and route signup back to/verify-emailin the frontend). - Docker: migrations run on container start (
node dist/migrate.js);docker-compose.ymlexposes a configurablePOSTGRES_PORThost port.
Not built yet
The AI /chat endpoint (LLM proxy) and the signing / patient-owned-storage / approval flow.