From 6d6af67f2fb627f6eb3a8656e0bb897fe617cd8d Mon Sep 17 00:00:00 2001 From: goose Date: Sun, 19 Jul 2026 22:13:51 -0300 Subject: [PATCH] fix(rekey): echo stored DEK values in response, not the pre-image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rekey_rotates_owner_share_and_keeps_listed_recipients failed in CI: the response's wrapped_profile_dek was 'owner-dek-v1' (old) instead of 'owner-dek-v2' (new). update_wrapped_dek uses find_one_and_update, which returns the document as it was BEFORE the update by default — so reading the new value from the returned doc gives the pre-image. Fix: echo the request values (exactly what was stored) in the response instead of reading them back. Unambiguous and avoids the ReturnDocument::After plumbing. The write itself was always correct (the stored value was v2) — only the response was stale, which is why the other rekey tests (which check state via fresh reads, not the response body) passed. Now CI-green (clippy/fmt clean; integration tests will re-run). --- backend/src/handlers/profile_share.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/backend/src/handlers/profile_share.rs b/backend/src/handlers/profile_share.rs index e2f4338..3895fb1 100644 --- a/backend/src/handlers/profile_share.rs +++ b/backend/src/handlers/profile_share.rs @@ -613,7 +613,10 @@ pub async fn rekey_profile( } // 3. Rotate the owner share (store the new account-wrapped profile DEK). - let updated = match profiles + // update_wrapped_dek uses find_one_and_update, which returns the PRE-image + // by default — so we don't read the new values back from it; we echo the + // request values (exactly what was stored) in the response below. + match profiles .update_wrapped_dek( &profile_id, &owner, @@ -622,7 +625,7 @@ pub async fn rekey_profile( ) .await { - Ok(Some(p)) => p, + Ok(Some(_)) => {} Ok(None) => { return Err(( StatusCode::NOT_FOUND, @@ -636,7 +639,7 @@ pub async fn rekey_profile( Json(serde_json::json!({ "error": "database error" })), )); } - }; + } // 4. Upsert each submitted recipient envelope (fresh ECDH-wrapped DEK + // ephemeral pubkey, replacing the old envelope). Preserve the original @@ -695,8 +698,10 @@ pub async fn rekey_profile( StatusCode::OK, Json(RekeyResponse { profile_id, - wrapped_profile_dek: updated.wrapped_profile_dek, - wrapped_profile_dek_iv: updated.wrapped_profile_dek_iv, + // Echo the request values (exactly what was stored). Avoids the + // find_one_and_update pre-image gotcha. + wrapped_profile_dek: req.new_wrapped_profile_dek, + wrapped_profile_dek_iv: req.new_wrapped_profile_dek_iv, retained_recipient_user_ids: keep, }), ))