# 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\ - Documents\` (OneDrive-synced SharePoint libraries on the same host). - **Mapping rule:** dest `" - Documents\..."` <-> source `"\..."` (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).