mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
A guardian with a fresh second factor mints a one-time handover link (hlp_ token, HMAC hash stored only, 1/7/14 days, at most one open per profile, withdrawable) with a proposed access level per guardian: end, view only or manage, view only by default. The link is shown once with a copy button and a QR code; nothing is mailed. The panel sits at the end of each managed-profile row and hints when the person is under 16. The person opens /claim/<token>, sees a minimal preview (name, expiry, who keeps which access, no health data) and chooses a username, a required email and a password under the registration policy. The claim is one transaction under the managed-profile lock: the token is consumed, the credentials are set, the marker is cleared, every pending invitation the record offered is withdrawn, each guardian's access is set to its proposal, the disclaimer, onboarding and AI consent are reset, and every step is audited on the record and on each guardian's own account. A failure anywhere leaves the profile managed and the link unused. Each guardian is notified on their own channels. The new owner then sees each guardian's access on the first screen after signing in and decides finally; until then the proposal holds, and the decision waits at the top of Shared access. A guardian whose access moved since the claim is left alone. The same screen points the owner at their own notification channels, since reminders no longer reach the guardians. Both anonymous routes refuse a single-sign-on-only instance, refuse a live session before spending the per-address rate limit, check the link before probing names, and answer one 404 for every unusable token. The token travels in request bodies only; hlp_ joins the redaction and secret-shape rules and /claim/ the path-secret registry. Usernames starting with managed- are reserved. The session-surface and acting- account guards list the new surfaces with their reasons.
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).