mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
Changing which pillars count is an act the person performed, not something that happened to their health. Until now the week-over-week comparison could not tell the difference: both windows are computed in one request under whatever recipe is in force right now, so the pillar sets agree, the subtraction looks legitimate, and the dashboard could announce "your score dropped 14 points" to someone who had just come back from the settings page. The recipe now carries its own dated identity, and the delta guard compares against it the same way it already compares against the global method boundary: a recipe that changed between the two windows suppresses the delta with a new reason, config_changed, and the surfaces that gate on an unexplained delta stay quiet. The score record stores the recipe version and its change date on every write, resolved from the same stored blob the composition came from, so a row can say which recipe produced it. A new series module reads those versions back, marks the first day after a change as a break, refuses to join the composite line across it, and keeps the per-pillar rows running through it: a pillar is graded against its own reference band and stays comparable when the average of the pillars does not. The notice key folds the person's recipe version in beside the method version, so a change in either raises the existing dismissible notice once and dismissing one never dismisses the other. An account that never chose keeps its old key untouched.
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_casecolumns via@map(...), encrypted columns mostly suffixed*Encrypted(search the file; there are 24 encrypted column references). Thegenerator clientblock emits to../src/generated/prisma(imported as@/generated/prisma).migrations/— numbered, forward-only SQL migrations (0001_…upward).migration_lock.tomlpins the provider topostgresql.
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:
*Encryptedcolumns are written through@/lib/crypto(AES-256-GCM, versioned key ids); never store plaintext in an encrypted column. Key rotation isscripts/rotate-encryption-key.ts+docs/ops/encryption-key-rotation.md. - The generated client under
src/generated/prismais 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).