Files
HealthLog/prisma
Marc-André Bombeck a1dbd9c831 fix(medications): apply the post-opening clock only where a container has one
A supply container went EXPIRED 30 days after its first use no matter what
kind of container it was. That window exists because puncturing an injection
pen exposes its contents and the product information caps how long the rest
stays usable; a blister of tablets has no such limit, every tablet sits in
its own sealed cavity, and pressing the first one out says nothing about the
rest. The state machine never read `containerType`, so a tablet pack opened
five weeks ago had its remaining stock written off.

The clock now keys off the container kind. PEN and AMPOULE carry it: both are
a single sealed reservoir that the first dose breaches. BLISTER, INHALER,
BOTTLE and OTHER do not: their units stay individually sealed, or the
arrangement is simply unknown, and a fixed 30 days would be a number nobody
entered. The printed expiry still applies to every kind, so an unknown
container is not an unbounded one.

`computeExpiresAt` takes the kind too, so a clock-less container with no
printed date now persists no `expiresAt` at all and the daily expire scan
never sees it.

The per-item PATCH gains a way back out: `markAsFirstUseAt` accepts null and
clears the opening date, which is the correction a container needs after the
intake hook auto-opened it from a back-dated dose.

Also drops `daysRemainingInUse`. It had no caller anywhere in the tree and
its docblock described a chip that does not exist.
2026-07-26 18:00:07 +02:00
..

prisma/

The database layer. HealthLog runs PostgreSQL 16 via Prisma 7. This directory holds the single schema file and the forward-only migration history; the generated client is emitted elsewhere.

Contents

  • schema.prisma — 61 models, one file. cuid() primary keys, snake_case columns via @map(...), encrypted columns mostly suffixed *Encrypted (search the file; there are 24 encrypted column references). The generator client block emits to ../src/generated/prisma (imported as @/generated/prisma).
  • migrations/ — numbered, forward-only SQL migrations (0001_… upward). migration_lock.toml pins the provider to postgresql.

Migration workflow

# author a migration from a schema edit
pnpm dlx prisma migrate dev --name <short_snake_case_name>

# regenerate the client after any schema change
pnpm dlx prisma generate

Number a new migration with the next free prefix. The production entrypoint runs prisma migrate deploy on boot, so every migration must apply cleanly forward — there is no down-migration path. Always include the migration file in the same change as the schema edit.

Conventions

  • Encryption is fail-closed: *Encrypted columns are written through @/lib/crypto (AES-256-GCM, versioned key ids); never store plaintext in an encrypted column. Key rotation is scripts/rotate-encryption-key.ts + docs/ops/encryption-key-rotation.md.
  • The generated client under src/generated/prisma is build output — do not edit it.
  • Schema-touching changes that affect the API surface must regenerate docs/api/openapi.yaml (see ../CLAUDE.md).

Related: ../src/lib/README.md (db.ts, rollups/), ../docs/ops/ (migrations + backup runbooks).