Skip to content

api/client: preserve device keys on read errors - #577

Open
basnijholt wants to merge 1 commit into
matrix-construct:mainfrom
mindroom-ai:fix/device-key-read-errors
Open

api/client: preserve device keys on read errors#577
basnijholt wants to merge 1 commit into
matrix-construct:mainfrom
mindroom-ai:fix/device-key-read-errors

Conversation

@basnijholt

Copy link
Copy Markdown
Contributor

What does this PR do?

While reviewing the remaining device-key changes in the fork, I noticed that the exact-copy check in /keys/upload also hides errors reading the existing keys. The is_ok_and chain turns a database or decoding error into false, then the handler writes the uploaded keys over the stored row. A failed read is not evidence that no keys exist or that they differ.

This distinguishes a missing row from a failed read. A genuinely missing row still permits the first upload; other read or decoding errors return a server error and leave the stored device-key bytes untouched. Malformed keys in the request are still rejected as a client error before this check.

The successful cases stay the same: uploading different valid device keys still replaces the existing keys, and an exact-copy retry is still ignored so it cannot strip the existing cross-signing signatures. The fork has a stricter identity-replacement policy, but that policy is not part of this PR.

The regression uses the existing server-booting HTTP harness with a real database. It checks first upload, valid replacement, and signature-preserving retries, then inserts malformed stored rows: missing required fields, invalid JSON syntax, truncated JSON, and invalid UTF-8. Each corrupt-row upload must return HTTP 500 and preserve the original bytes. These fixtures exercise decoding failures; they do not simulate physical storage I/O failures.

Verified in the pinned Nix dynamic shell (Rust 1.95.0 and nightly rustfmt):

  • cargo fmt --all -- --check
  • cargo clippy --offline --locked --workspace --all-targets --all-features -- -D warnings
  • cargo test --offline --locked -p tuwunel --all-features --test device_key_read_errors — passed.
  • cargo test --offline --locked --workspace --all-targets --all-features — 1,079 passed, 0 failed, 4 ignored, matching upstream's ignored count.

I also ran the regression against unchanged upstream: all four corrupt stored rows returned HTTP 200 and were overwritten. Test runs used isolated networking and storage, with debug symbols disabled.

Checklist

  • Nightly formatting and pinned stable Clippy/rustc checks pass; the unused shared-harness helpers have a scoped, reasoned lint expectation.
  • Complement was not run locally; no compliance-result changes are claimed.
  • No public configuration options changed, so no example-config regeneration is needed.
  • This fixes existing endpoint error handling without adding an operator-facing feature or setup requirement.
  • I agree to the Apache-2.0 licensing terms and the project's Code of Conduct.

Distinguish missing stored device keys from read or decoding failures. Return internal errors before identity writes while retaining first-upload, replacement, and signature-preserving retry behavior. Exercise real HTTP uploads against corrupt stored rows and verify byte preservation.
Copilot AI balanced review requested due to automatic review settings September 6, 2026 17:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The fix is well-scoped, tested, and has no unresolved issues.

Pull request overview

Preserves stored device keys when existing-key reads or decoding fail.

Changes:

  • Distinguishes missing keys from read failures.
  • Returns HTTP 500 without overwriting unreadable rows.
  • Adds end-to-end regression coverage.
File summaries
File Description
src/main/tests/device_key_read_errors.rs Tests uploads, retries, corrupt data, and byte preservation.
src/api/client/keys/upload_keys.rs Propagates stored-key read errors safely.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@basnijholt

Copy link
Copy Markdown
Contributor Author

I reproduced the current nightly formatting and Clippy failures on unmodified main. The shared fix is in #578, so I've kept that cleanup out of this diff. The flagged service files are unchanged here. Once #578 lands, this PR can be rebased onto it and CI rerun.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants