Files
claudetools/clients/birth-biologic/docs/migration/2026-06-26-corruption-recovery-plan.md
Mike Swanson 1f15a6bc79 sync: auto-sync from GURU-5070 at 2026-06-29 11:05:52
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-06-29 11:05:52
2026-06-29 11:06:44 -07:00

7.2 KiB

BirthBiologic — 2026-06-26 migration corruption: recovery + corrected re-migration plan

Status: PLAN (approved direction 2026-06-29 by Mike — corrected re-migration from intact Datto source; Datto 06-24 accepted as Master Donor source). Execution gated per phase.

Summary of the incident

The 2026-06-26 Datto -> SharePoint push corrupted a large set of files. Root cause is fully diagnosed: the upload path wrote each file's byte array as space-separated DECIMAL TEXT instead of raw binary (a "$bytes" stringification bug in the base64/stdout-capture upload workaround used during the 06-26 session). Proof:

  • Corrupt .xlsx begin 80 75 3 4 20 0 6 0 ... = decimal of 0x50 0x4B 0x03 0x04 0x14 0x00 0x06 0x00 (the real PK.. OOXML signature).
  • Corrupt .pdf begin 37 80 68 70 ... = decimal of 0x25 0x50 0x44 0x46 (%PDF).

Because it operated on raw bytes, the bug is format-agnostic.xlsx, .docx, and .pdf were all hit, and corrupt files are inflated ~3-4x (each byte became 2-4 ASCII chars + space).

Blast radius (as of 2026-06-29, read-only probe on ACG-DWP-X-BB)

  • 15 of 16 locally-cached files modified 2026-06-26 in C:\Users\Administrator\OneDrive - Birth Biologic, LLC\ are corrupt. Includes HR PII (K Steen Confidential Disclosure Agreement.pdf, Handbook Acknowledgement, Safety & Health Policy), Finance, Quality Designee docs, the Master Donor Spreadsheet, and Inventory 2025/2026.
  • ~3,298 additional files modified 2026-06-26 are OneDrive cloud-only (dehydrated) and were skipped to avoid mass-hydration. They are almost certainly corrupted the same way — i.e. the true scope is likely the entire 06-26 push (hundreds-to-thousands of files).

Data-loss assessment: NONE expected

  • The Datto Workplace source copies are intact (C:\Users\Public\Desktop\Datto Workplace Server Projects\), confirmed clean PK headers on the affected spreadsheets.
  • Even a corrupt file with no source is losslessly recoverable — it literally contains the original bytes as decimal numbers; split on whitespace -> [byte] -> WriteAllBytes.

Authoritative source & path mapping

  • Source of truth: C:\Users\Public\Desktop\Datto Workplace Server Projects\ (ACG-DWP-X-BB).
  • Target libraries: C:\Users\Administrator\OneDrive - Birth Biologic, LLC\<Library> - Documents\ (OneDrive-synced SharePoint libraries on the same host).
  • Mapping rule: dest "<Folder> - Documents\..." <-> source "<Folder>\..." (strip the - Documents suffix). Confirmed pairs: Admin, Donor Services, Supply Management (verify Quality Department + any other library before execution).

Why this method (corrected re-migration, not file repair)

The corruption is systemic to the 06-26 batch, so file-by-file repair is the wrong altitude. The clean fix exploits that both trees live on the same machine with OneDrive sync available: copy intact source files into the OneDrive library folders and let OneDrive sync them up — native, integrity-checked, no custom byte handling, no Graph chunked-upload, no RMM timeout. (SPMT is the bulk alternative; the buggy custom-script upload path is retired for this work.)

Plan

Phase 0 — Freeze & notify (do first)

  • Tell client/Annise: do not open/edit/trust files in the migrated SharePoint libraries dated 2026-06-26 — they are corrupt and will be replaced.
  • Pause OneDrive editing on ACG-DWP-X-BB for those libraries during the re-push to avoid sync conflicts (409s).

Phase 1 — RESULTS (completed 2026-06-29, read-only)

Method: local metadata enumeration on ACG-DWP-X-BB (size vs Datto source) + header reads; Graph (Tenant Admin app, BirthBio tenant 19a568e8-...) for SharePoint-side spot checks.

  • 3,371 files modified 2026-06-26 across the OneDrive libraries.
  • 84 CONFIRMED CORRUPT (decimal-text header, not a valid signature):
    • By library: Donor Services 67, Admin 12, Supply Management 3, Quality Department 2.
    • By type: 59 .pdf, 20 .docx, 5 .xlsx.
    • Recovery routes: 83 RESTORE-FROM-SOURCE (clean Datto source confirmed) + 1 DECODE-OR-FIND-SOURCE (Donor Services\Suitability\3c. Cord For Life - Donor Suitability Datto Copy.docx — no mapped source; decode the decimal-bytes or locate its source).
  • ~3,197 clean (3,168 size-matched to source + 29 header-verified).
  • 89 DEFERRED — cloud-only OneDrive files at >=260-char (MAX_PATH) paths, no Datto source mapping (Quality 59, Admin 30). Unassessable by header: Graph driveItem-by-path 404s them and local [IO.File]::Open fails MAX_PATH even with \\?\ + .NET long-path switches. Must be checked/handled with a long-path-native tool (robocopy / SPMT) in execution. Lower corruption risk (no Datto source = not part of the Datto->SP byte-push) but NOT cleared.

Artifacts (committed):

  • 2026-06-26-corruption-manifest.csv — full 3,371-row inventory (verdict, sizes, source state).
  • 2026-06-26-remediation-list.csv — the 84 corrupt files + recovery route (Phase 3 input).

Phase 1 — Full-scope inventory (READ-ONLY) [method, for reference]

  • Enumerate all files (any type) modified 2026-06-26 across every OneDrive library on ACG-DWP-X-BB; classify corrupt (header != type signature / decimal-text) vs clean.
  • Handle cloud-only files: either controlled batch-hydrate + header-check, or check via Graph (Tenant Admin app, Sites.ReadWrite.All) against the SharePoint side.
  • Output: authoritative corrupt-file manifest with, per file: dest path, mapped source path, source-validity (clean header? exists?), and recovery route.

Phase 2 — Pre-flight validation

  • For each corrupt file confirm a clean source exists in the Datto tree (verify header).
  • Partition into: A restore-from-source · B decimal-decode-recover (no clean source) · C no recovery available (investigate; expected empty).

Phase 3 — Corrected re-push (GATED — explicit go required)

  • List A: copy source -> OneDrive library path (overwrite corrupt copy); let OneDrive sync. Work in batches; after each batch verify dest header flips to a valid signature.
  • List B: decode decimal-text -> binary, write, verify header.
  • Master Donor Spreadsheet: use Datto 2026-06-24 13:32 source (2,292,743 B) per Mike's call.

Phase 4 — Verification & reconciliation

  • Re-scan libraries: confirm 0 corrupt remaining in the 06-26 set.
  • Spot-open Master Donor, an Inventory, and a sample PDF to confirm they actually open.
  • Reconcile file counts/sizes source vs dest. Update wiki/clients/birth-biologic.md + CONTEXT.

Phase 5 — Root-cause closure

  • Retire the custom-script byte-capture upload path for this client. If any custom upload remains, write binary with [IO.File]::WriteAllBytes — never stringify a byte array.
  • Confirms logged in errorlog.md (migration/datto-to-sharepoint, 2026-06-29).

Open items before execution

  • Decide cloud-only handling for Phase 1 (batch-hydrate vs Graph) — Graph avoids 3,300 downloads.
  • Confirm full library list + mapping (esp. Quality Department).
  • Confirm no genuine 06-24->06-26 edits exist only in corrupt copies for files other than Master Donor (those would use the decimal-decode route to preserve latest content).