docs: decide multi-person ZK sharing ADR; reconcile jwt/encryption docs
Some checks failed
Lint and Build / format (pull_request) Successful in 37s
Lint and Build / clippy (pull_request) Successful in 1m40s
Lint and Build / build (pull_request) Successful in 3m44s
Lint and Build / test (pull_request) Failing after 0s

Rewrite the encryption/persona/JWT docs to match the implemented code and
record the multi-person sharing design.

- multi-person-sharing.md (NEW): ADR for per-profile DEK + X25519 envelope
  sharing. All five original open questions resolved 2026-07-18. Covers
  divorced-parents, pets, graduation, and elderly-parent care; adds an
  admin permission tier for owner-incapacity. Decided, not yet implemented.
  (#3)
- encryption.md: full rewrite to the implemented wrapped-DEK / Web Crypto
  model; the old version described ZK encryption as 'planned'. (#4)
- jwt-authentication-decision.md: rewritten to match implementation
  (PBKDF2 not bcrypt, no Redis, token_version revocation, real Claims).
  Original aspirational content preserved in a History section. (#4)
- PERSONA_AND_FAMILY_MANAGEMENT.md: 'Current reality' section added, old
  'Implementation Status' marked superseded, encryption section corrected. (#4)
- ENCRYPTION_UPDATE_SUMMARY.md: archived (changelog for a rewrite that
  itself went stale). (#4)
- ADR README index updated for the new + reconciled entries.
This commit is contained in:
goose 2026-07-18 19:26:43 -03:00
parent 6a569da3b1
commit e322145ffb
6 changed files with 737 additions and 990 deletions

View file

@ -1,10 +1,16 @@
# Persona and Family Management - Product Definition
**Document Version**: 1.0
**Date**: 2026-03-09
**Status**: Draft - For Refinement
**Document Version**: 1.1
**Date**: 2026-07-18 (reconciled with code; original draft 2026-03-09)
**Status**: Vision doc — implementation status section corrected to match code
**Purpose**: Consolidate all current information about persona and family management features for further product refinement
> **How to read this doc.** Sections marked **Vision** describe the target
> product and are still valid for discussion. Sections marked **Today (code)**
> describe what is actually implemented and have been verified against the
> codebase as of 2026-07-18. Where the two diverge, the gap is called out and
> linked to the relevant Forgejo issue.
---
## 📋 Table of Contents
@ -35,6 +41,28 @@ Normogen supports **multi-person health data management** through a persona and
---
## Current reality (as of 2026-07-18)
This section corrects the earlier "Current Implementation Status" section below,
which described an earlier state. Verified against the code:
| Capability | Status | Notes |
|---|---|---|
| Single profile per user account | ✅ Done | `GET/PUT /api/profiles/me`; profile is auto-created as `profile_{user_id}` at registration. Display name is client-encrypted. |
| Multi-profile (child/dependent) within one account | ❌ Not built | `ProfileRepository::find_by_user_id` returns a single profile; no create/list/switch endpoints. `profileId` can be tagged onto medications but there is no backing entity beyond the owner's. |
| Family groups | ❌ Not built | `Family` model exists but has **no handler and no routes**. JWT carries `family_id` but nothing populates or checks it. |
| Cross-user sharing (spouse, caregiver) | ❌ **Blocked by design** | `/api/shares` routes exist but cannot grant decryption access — all data is encrypted under the owner's DEK and there is no key-distribution mechanism. See **[issue #3](https://gitea.soliverez.com.ar/alvaro/normogen/issues/3)**. |
| Caregiver roles / permissions | ❌ Not built | `permissions` field exists on Profile and in JWT claims but is not enforced. |
| Zero-knowledge encryption of health data | ✅ Done | Client-side Web Crypto, wrapped-DEK recovery. See [`encryption.md`](encryption.md). |
**Implication for the family/caregiver personas below:** the single biggest
open question is architectural — *how does sharing work under zero-knowledge?*
That must be decided before family/caregiver features can be implemented. Until
then, the realistic near-term scope is **multi-profile within a single account**
(one login managing several people's data, no cross-account sharing).
---
## User Personas
### Primary: Privacy-Conscious Individual
@ -167,7 +195,12 @@ User Account: jane.doe@example.com (Jane)
---
## Current Implementation Status
## Current Implementation Status (superseded — see "Current reality" above)
> The detail below was written 2026-03-09 against an earlier state and
> overstates what existed then. It is retained for history. For the accurate
> current picture, read the **Current reality** section near the top of this
> document, and [`encryption.md`](encryption.md) for encryption.
### ✅ Implemented (Backend)
@ -595,16 +628,23 @@ if profile.role == "child" || profile.age < 18 {
### Encryption
**Zero-Knowledge Encryption**:
- Profile names are encrypted (AES-256-GCM)
- Family names are encrypted
- Only users with correct password can decrypt
- Server cannot see profile names
> **Correction (2026-07-18):** the bullets below described a planned
> server-side scheme that was never built. The shipped system is
> **client-side** zero-knowledge via the browser's Web Crypto API with a
> wrapped-DEK model. The server has no crypto code at all — it is a blind
> store. Profile/medication/appointment data is encrypted in the browser
> before upload and the server cannot read any of it. Full details:
> [`encryption.md`](encryption.md) and
> [`adr/zero-knowledge-encryption.md`](../adr/zero-knowledge-encryption.md).
**Encrypted Fields**:
- `profile.name` - Person's name
- `family.name` - Family group name
- Medication data (when implemented)
**What's actually encrypted (client-side, today):**
- Medication data blob (name, dosage, frequency, route, notes, …)
- Appointment data blob (title, provider, date/time, …)
- Profile display name
**What stays plaintext (queryable by the server):**
- IDs (`profileId`, `medicationId`, `userId`, `appointmentId`)
- Medication `active` flag, appointment `status`, `doseSchedule`, timestamps
---