docs: product/encryption & persona docs badly out of sync with implemented ZK encryption #4

Closed
opened 2026-07-18 15:24:48 +00:00 by alvaro · 2 comments
Owner

Problem

The product-facing docs describing encryption and personas (all dated 2026-03-09) describe a system that does not match what is actually built. The June ADR (docs/adr/zero-knowledge-encryption.md) and the code tell a different, more advanced story. Anyone (human or agent) reading these docs to understand the system will be misled.

Drift found (code-grounded)

Doc claim Reality in code
docs/product/encryption.md marks zero-knowledge encryption as "📋 Planned / Not yet implemented" Fully implemented — client-side Web Crypto, AES-256-GCM, wrapped-DEK recovery. See web/normogen-web/src/crypto/ and docs/adr/zero-knowledge-encryption.md (Phase 1 + Phase 2 done)
PERSONA_AND_FAMILY_MANAGEMENT.md: "No dedicated API for profile CRUD" /api/profiles/me GET + PUT are wired (backend/src/app.rs:58-59)
Same doc + encryption.md: encryption is server-side AES-256-GCM with per-user server keys Reality is client-side Web Crypto with a wrapped-DEK model. Backend Cargo.toml has no crypto crates at all — the server is a blind store
encryption.md / jwt-authentication-decision.md: recovery = "client encrypts phrase with password" Actual recovery uses a recovery-phrase-derived KEK wrapping a random DEK — stronger than documented
jwt-authentication-decision.md: claims are {sub, exp, iat, token_type} Actual AccessClaims (backend/src/auth/claims.rs) carry email, family_id, permissions, jti too
encryption.md "Implementation Status: Security features 85% complete" Misleading — the ZK encryption it lists as planned is in fact shipped

Docs affected

  • docs/product/encryption.md — major rewrite needed (see #<desig_issue> for the sharing gap, but the rest can be rewritten now)
  • docs/product/ENCRYPTION_UPDATE_SUMMARY.md — obsolete; should be archived or folded into a rewrite of encryption.md
  • docs/product/PERSONA_AND_FAMILY_MANAGEMENT.md — needs honest "what exists today" section (single-profile, no family routes) separate from the vision
  • docs/adr/jwt-authentication-decision.md — update claims struct + recovery description to match implementation

Accurate reference

docs/adr/zero-knowledge-encryption.md is the only doc that currently matches reality. It should be the canonical source; the others should defer to it or be rewritten to match.

Proposed fix

  1. Rewrite encryption.md to describe the implemented wrapped-DEK / Web Crypto model (draft in progress in this branch).
  2. Archive ENCRYPTION_UPDATE_SUMMARY.md (it's a changelog for a rewrite that's now itself stale).
  3. Split PERSONA_AND_FAMILY_MANAGEMENT.md into "implemented today" vs "vision" — implemented = single profile per user, /api/profiles/me only.
  4. Update the JWT ADR's claims/recovery sections to match AccessClaims.

Labels: docs, bug (because docs actively misstate implementation).

## Problem The product-facing docs describing encryption and personas (all dated **2026-03-09**) describe a system that does not match what is actually built. The June ADR (`docs/adr/zero-knowledge-encryption.md`) and the code tell a different, more advanced story. Anyone (human or agent) reading these docs to understand the system will be misled. ## Drift found (code-grounded) | Doc claim | Reality in code | |---|---| | `docs/product/encryption.md` marks zero-knowledge encryption as "📋 Planned / Not yet implemented" | **Fully implemented** — client-side Web Crypto, AES-256-GCM, wrapped-DEK recovery. See `web/normogen-web/src/crypto/` and `docs/adr/zero-knowledge-encryption.md` (Phase 1 + Phase 2 done) | | `PERSONA_AND_FAMILY_MANAGEMENT.md`: "No dedicated API for profile CRUD" | `/api/profiles/me` GET + PUT **are wired** (`backend/src/app.rs:58-59`) | | Same doc + `encryption.md`: encryption is server-side AES-256-GCM with per-user server keys | Reality is **client-side** Web Crypto with a wrapped-DEK model. Backend `Cargo.toml` has **no crypto crates at all** — the server is a blind store | | `encryption.md` / `jwt-authentication-decision.md`: recovery = "client encrypts phrase with password" | Actual recovery uses a **recovery-phrase-derived KEK wrapping a random DEK** — stronger than documented | | `jwt-authentication-decision.md`: claims are `{sub, exp, iat, token_type}` | Actual `AccessClaims` (`backend/src/auth/claims.rs`) carry `email, family_id, permissions, jti` too | | `encryption.md` "Implementation Status: Security features 85% complete" | Misleading — the ZK encryption it lists as planned is in fact shipped | ## Docs affected - `docs/product/encryption.md` — major rewrite needed (see #<desig_issue> for the sharing gap, but the rest can be rewritten now) - `docs/product/ENCRYPTION_UPDATE_SUMMARY.md` — obsolete; should be archived or folded into a rewrite of `encryption.md` - `docs/product/PERSONA_AND_FAMILY_MANAGEMENT.md` — needs honest "what exists today" section (single-profile, no family routes) separate from the vision - `docs/adr/jwt-authentication-decision.md` — update claims struct + recovery description to match implementation ## Accurate reference `docs/adr/zero-knowledge-encryption.md` is the **only** doc that currently matches reality. It should be the canonical source; the others should defer to it or be rewritten to match. ## Proposed fix 1. Rewrite `encryption.md` to describe the implemented wrapped-DEK / Web Crypto model (draft in progress in this branch). 2. Archive `ENCRYPTION_UPDATE_SUMMARY.md` (it's a changelog for a rewrite that's now itself stale). 3. Split `PERSONA_AND_FAMILY_MANAGEMENT.md` into "implemented today" vs "vision" — implemented = single profile per user, `/api/profiles/me` only. 4. Update the JWT ADR's claims/recovery sections to match `AccessClaims`. Labels: `docs`, `bug` (because docs actively misstate implementation).
alvaro added the
docs
bug
labels 2026-07-18 15:25:02 +00:00
Author
Owner

Ok to go with the proposed fix

Ok to go with the proposed fix
Author
Owner

All four docs in this issue are now done (uncommitted, in the working tree):

  • docs/product/encryption.md — full rewrite to the implemented wrapped-DEK / Web Crypto model
  • docs/product/PERSONA_AND_FAMILY_MANAGEMENT.md — "Current reality" section added, old "Implementation Status" marked superseded, encryption section corrected
  • docs/product/ENCRYPTION_UPDATE_SUMMARY.md — archived to docs/archive/ with a header explaining why
  • docs/adr/jwt-authentication-decision.md — rewritten to match the implementation; original aspirational content preserved in a History section

Also updated docs/adr/README.md to list the new multi-person-sharing.md (draft ADR from issue #3) and mark the reconciled entries.

Bonus finding while doing this: backend/src/auth/claims.rs defines an AccessClaims struct (family_id, permissions, token_type, jti) that is dead code — not imported or used anywhere in the source. The real access-token claims are {sub, exp, iat, user_id, email, token_version} in backend/src/auth/jwt.rs. This corrects a mistake in issue #3 (posted a correction there). claims.rs should be deleted or intentionally wired; leaving that as a separate cleanup rather than expanding this issue.

Closing as done. Will commit as docs: rewrite encryption/jwt docs to match implementation, archive stale summary (#4) once reviewed.

All four docs in this issue are now done (uncommitted, in the working tree): - ✅ **`docs/product/encryption.md`** — full rewrite to the implemented wrapped-DEK / Web Crypto model - ✅ **`docs/product/PERSONA_AND_FAMILY_MANAGEMENT.md`** — "Current reality" section added, old "Implementation Status" marked superseded, encryption section corrected - ✅ **`docs/product/ENCRYPTION_UPDATE_SUMMARY.md`** — archived to `docs/archive/` with a header explaining why - ✅ **`docs/adr/jwt-authentication-decision.md`** — rewritten to match the implementation; original aspirational content preserved in a History section Also updated `docs/adr/README.md` to list the new `multi-person-sharing.md` (draft ADR from issue #3) and mark the reconciled entries. **Bonus finding while doing this:** `backend/src/auth/claims.rs` defines an `AccessClaims` struct (`family_id`, `permissions`, `token_type`, `jti`) that is **dead code** — not imported or used anywhere in the source. The real access-token claims are `{sub, exp, iat, user_id, email, token_version}` in `backend/src/auth/jwt.rs`. This corrects a mistake in issue #3 (posted a correction there). `claims.rs` should be deleted or intentionally wired; leaving that as a separate cleanup rather than expanding this issue. Closing as done. Will commit as `docs: rewrite encryption/jwt docs to match implementation, archive stale summary (#4)` once reviewed.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: alvaro/normogen#4
No description provided.