Problem
#369 proposed a periodic chain-reconciliation sweep for guardian switches that never reach the push path. It was closed COMPLETED on 2026-08-06, but it was closed by the merge of #375 — which fixed the first-tx reconstruction bug on the push path, not the sweep. On current main, release_if_guardian_switched still fires from exactly two push-triggered sites (services/delta_commit.rs and the canonicalization processor); jobs/canonicalization/reconciliation.rs is the unrelated #345 retained-delta sweep. No startup scan, no periodic chain check.
So every blind spot #369 enumerated still exists: switches predating v0.15.1, clients older than v0.15.0, failed best-effort pushes, and the offline switch path (which never pushes by design). The consequence is a permanent split-brain on the old operator: the account stays active (released_at: null), GET /state and /state/lookup serve stale pre-switch state, and the account holds capacity forever. No custody risk — the old operator's co-signatures are invalid on-chain — but recovery flows that query the old operator get convincingly stale state.
This is not hypothetical: 0xMiden/wallet#782 describes a switch executed while the old operator is network-dead — the exact case where the push can never land and only a chain-driven sweep can ever release the account.
Proposal
As in #369: a periodic job (or an extension of the canonicalization worker loop) that, for each non-released, non-EVM account, compares the stored commitment against chain via NetworkClient::verify_commitment, and on sustained mismatch where the on-chain guardian commitment differs from this server's ack key, runs the existing release path (release_if_guardian_switched semantics, accounts.release audit with operator_identity: system). Backoff/paging along the lines of the #345 sweep to keep it cheap.
Refs: #305, #311, #345, #369, #375.
Problem
#369 proposed a periodic chain-reconciliation sweep for guardian switches that never reach the push path. It was closed COMPLETED on 2026-08-06, but it was closed by the merge of #375 — which fixed the first-tx reconstruction bug on the push path, not the sweep. On current
main,release_if_guardian_switchedstill fires from exactly two push-triggered sites (services/delta_commit.rsand the canonicalization processor);jobs/canonicalization/reconciliation.rsis the unrelated #345 retained-delta sweep. No startup scan, no periodic chain check.So every blind spot #369 enumerated still exists: switches predating v0.15.1, clients older than v0.15.0, failed best-effort pushes, and the offline switch path (which never pushes by design). The consequence is a permanent split-brain on the old operator: the account stays active (
released_at: null),GET /stateand/state/lookupserve stale pre-switch state, and the account holds capacity forever. No custody risk — the old operator's co-signatures are invalid on-chain — but recovery flows that query the old operator get convincingly stale state.This is not hypothetical: 0xMiden/wallet#782 describes a switch executed while the old operator is network-dead — the exact case where the push can never land and only a chain-driven sweep can ever release the account.
Proposal
As in #369: a periodic job (or an extension of the canonicalization worker loop) that, for each non-released, non-EVM account, compares the stored commitment against chain via
NetworkClient::verify_commitment, and on sustained mismatch where the on-chain guardian commitment differs from this server's ack key, runs the existing release path (release_if_guardian_switchedsemantics,accounts.releaseaudit withoperator_identity: system). Backoff/paging along the lines of the #345 sweep to keep it cheap.Refs: #305, #311, #345, #369, #375.