Fixes #1148.
The reporter's diagnosis is right, and I reproduced it. Since #993, MoveSourceCleanupPolicyResolver returns null for SourcePolicyRevision and TargetPolicyRevision on a DeleteAfterVerifiedCopy authorization, but MoveQueueService.ValidateSourceCleanupAuthorization still requires TargetPolicyRevision to be present (and the source one to be present whenever there is a source root). So every move between two healthy configured roots throws "Verified source deletion requires a complete root-folder policy snapshot" before it is queued. Moves that resolve to RetainSource skip that check, which is why only some setups notice.
Measured repro, with controls
New tests in MoveSourceCleanupEnqueueTests run the real MoveSourceCleanupPolicyResolver on two configured roots and feed its result into IMoveQueueService.EnqueueMoveAsync. The existing tests never chain the two; EfMoveQueuePersistenceTests hand-supplies SourcePolicyRevision: 2, TargetPolicyRevision: 4.
- Resolver then enqueue, delete authorization: on canary at 192f5a9 it throws the
ArgumentExceptionquoted above (measured with a separate repro test usingAssert.ThrowsAsyncon the unmodified source; that repro test is not part of this PR). This PR carries the same scenario as a test that expects success: it passes with the change, and with only the source change reverted it fails with that exception. - Control 1: the same command with the revisions hand-fed (
0, as the pre-#993 resolver would have supplied) enqueues fine on canary and with the fix. - Control 2: a move whose destination is outside any configured root resolves to
RetainSourceand enqueues fine on canary and with the fix.
The fix
ValidateSourceCleanupAuthorization now checks only the storage-contract snapshot: a positive target root id, a target storage contract revision, and source root id and source storage contract revision either both present or both absent. The two policy-r...
Automated Canary build