fix(store): preserve audit tables and real TLS modes during salvage #270

Merged
KofTwentyTwo merged 1 commits from story/m6-salvage-fidelity into dev 2026-07-31 17:01:40 +00:00
KofTwentyTwo commented 2026-07-31 16:59:49 +00:00 (Migrated from github.com)

Summary

  • Closes #248. Salvage recovery in crates/nuncio-store/src/recovery.rs had two data-safety bugs:
    1. Salvage never read or restored worm_audit_records / filter_execution_logs — a salvage silently lost the tamper-evident audit/ledger history.
    2. Salvage hardcoded every recovered account's imap_tls_mode/smtp_tls_mode back to ImplicitTls, regardless of the account's real configured mode — silently changing an account's security posture on recovery (e.g. a STARTTLS or intentionally-plain account became implicit-TLS).
  • Fix: SqliteRecoveryEngine::salvage now also reads and restores worm_audit_records/filter_execution_logs verbatim (including their hash-chain columns), and salvage_accounts reads the real imap_tls_mode/smtp_tls_mode text from each salvaged row via a new parse_salvaged_tls_mode helper, which WARN-logs the account id + raw value and falls back only when a raw value is genuinely unrecognized (never silently substituting a different real mode).
  • RecoverySummary gained salvaged_audit_records_count / salvaged_execution_logs_count fields.

Test plan

  • salvage_preserves_worm_audit_and_filter_execution_log_chains — seeds 2 WORM audit records + 2 filter execution log entries, runs salvage, asserts both survive with correct counts and that verify_worm_audit_chain/verify_execution_log_chain still pass on the restored ledgers (proving the hash-chain columns, not just row data, were preserved).
  • salvage_preserves_real_tls_mode_instead_of_downgrading_to_implicit — seeds an account with imap_tls_mode: StartTls, smtp_tls_mode: Plain, runs salvage, asserts the recovered account keeps those exact modes instead of being reset to ImplicitTls.
  • cargo fmt --all -- --check — clean
  • cargo check-all (clippy --all-targets --workspace -D warnings) — 0 warnings
  • cargo test-all — all green, 0 ignored (nuncio-store unit tests: 70 passed including the 2 new tests; full workspace: all suites passed)
## Summary - Closes #248. Salvage recovery in `crates/nuncio-store/src/recovery.rs` had two data-safety bugs: 1. Salvage never read or restored `worm_audit_records` / `filter_execution_logs` — a salvage silently lost the tamper-evident audit/ledger history. 2. Salvage hardcoded every recovered account's `imap_tls_mode`/`smtp_tls_mode` back to `ImplicitTls`, regardless of the account's real configured mode — silently changing an account's security posture on recovery (e.g. a STARTTLS or intentionally-plain account became implicit-TLS). - Fix: `SqliteRecoveryEngine::salvage` now also reads and restores `worm_audit_records`/`filter_execution_logs` verbatim (including their hash-chain columns), and `salvage_accounts` reads the real `imap_tls_mode`/`smtp_tls_mode` text from each salvaged row via a new `parse_salvaged_tls_mode` helper, which WARN-logs the account id + raw value and falls back only when a raw value is genuinely unrecognized (never silently substituting a different real mode). - `RecoverySummary` gained `salvaged_audit_records_count` / `salvaged_execution_logs_count` fields. ## Test plan - [x] `salvage_preserves_worm_audit_and_filter_execution_log_chains` — seeds 2 WORM audit records + 2 filter execution log entries, runs salvage, asserts both survive with correct counts and that `verify_worm_audit_chain`/`verify_execution_log_chain` still pass on the restored ledgers (proving the hash-chain columns, not just row data, were preserved). - [x] `salvage_preserves_real_tls_mode_instead_of_downgrading_to_implicit` — seeds an account with `imap_tls_mode: StartTls`, `smtp_tls_mode: Plain`, runs salvage, asserts the recovered account keeps those exact modes instead of being reset to `ImplicitTls`. - [x] `cargo fmt --all -- --check` — clean - [x] `cargo check-all` (clippy `--all-targets --workspace -D warnings`) — 0 warnings - [x] `cargo test-all` — all green, 0 ignored (nuncio-store unit tests: 70 passed including the 2 new tests; full workspace: all suites passed)
Sign in to join this conversation.