feat: hard revoke / re-key (Phase C, #3) #15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/3-phase-c-rekey"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase C of the multi-person sharing ADR (§4 Revocation). An owner can now rotate a profile's DEK — generating a fresh key, re-encrypting all the profile's data under it (client-side), and re-wrapping to the owner share + kept recipients. A revoked recipient's cached old DEK stops working, closing the soft-revoke window the ADR requires for graduation / suspected compromise.
The server stays a blind store: it sees opaque old→new ciphertext blobs flow through, never the DEK or plaintext. No backend crypto.
Decisions (from clarification): full client-side re-key (rotate the DEK AND re-encrypt data); best-effort + resumable retry (no server-side write lock).
Backend
ProfileRepository::update_wrapped_dek— rotate the owner share (account-wrapped profile DEK), owner-scoped.ProfileShareRepository:find_active_for_profile+delete_for_profile_excluding— list current recipients and hard-delete omitted ones.POST /api/profiles/:id/rekey: validates each submitted envelope against existing active shares (no smuggling new recipients in via rekey — usePOST /sharesfor that), rotates the owner share, upserts recipient envelopes with fresh ephemeral ECDH keys, hard-deletes omitted recipients. Returns the surviving recipient list.rekey_tests.rs: owner-share rotation; hard-revoke from the recipient's view (omitted recipient'sshared-with-meand gate both 404); envelope-for-recipient-with-no-share rejected (400); non-owner rejected (404); rekey-with-no-envelopes revokes everyone.Frontend
useProfileStore.rekeyProfile(profileId, keepRecipientUserIds): fetches all profile data (meds + appointments + health-stats), re-encrypts each row under a new DEK, builds fresh ECDH envelopes per kept recipient, commits viaPOST /rekey, swaps the in-memory DEK.ProfileSharing: "Rotate encryption key (hard revoke)" action with a strong confirmation dialog. All currently-listed recipients are kept by default; the owner removes specific ones via the existing per-row revoke button first if they want them gone at the key level.Verification
cargo build+clippy --all-targets --all-features -D warnings+fmt --checkall clean. Tests compile.tsc --noEmitclean; 31/31 tests pass.Out of scope
Refs #3.