Non-destructive, resumable migration from legacy object metadata to v2.
Legacy mutable version lists are used only as migration indexes. Each object is rebuilt as immutable versions plus one head and committed atomically with compatible blob descriptors and checksum-verified local location evidence. Legacy records are retained for rollback and read compatibility.
Run with object writes disabled. Source revisions are included in each transaction compare, so a concurrent legacy mutation fails closed instead of publishing a stale v2 chain.
Summary
Types
@type report() :: %{ objects_scanned: non_neg_integer(), objects_migrated: non_neg_integer(), objects_already_v2: non_neg_integer(), versions_migrated: non_neg_integer(), delete_markers_migrated: non_neg_integer(), blob_descriptors_created: non_neg_integer(), blob_descriptors_promoted: non_neg_integer(), blob_locations_created: non_neg_integer(), target_replication_factor: pos_integer(), missing_local_blobs: [binary()] }