## User - **User:** Mike Swanson (mike) - **Machine:** GURU-5070 - **Role:** admin ## Session Summary Consolidated BirthBiologic's Quality content in SharePoint and reconciled it against the Datto Workplace source of truth, then handled the migration-corruption fallout. The session began by ensuring sysadmin@birthbiologic.com had access to the BirthBio SharePoint content sites: granted owner+member on the canonical **Quality Systems Department** (QSD) site via its M365 group (he had no access); confirmed existing owner access on Donor Services, Supply Management, and the old Quality Department. The `[admin]` communication site and four empty `Quality Systems Department-*` spoke sites have no M365 group, so they require a site-collection-admin grant via PnP (commands DM'd to Mike; not runnable by the app — `Unsupported app only token` on SP REST). Investigated why two Quality sites existed (`Quality Department`, created 2026-04-20, the original migration landing site; `Quality Systems Department`, created 2026-06-02, canonical) and treated Datto Workplace on ACG-DWP-X-BB as the authoritative source. Enumerated the Datto "Quality Department" project (3,812 files / 28 GB). Reconciled QSD to Datto: removed 811 byte-identical duplicate files (kept the Datto-aligned copy of each, verified by quickXorHash), removed 195 SP-only files older than the current week (kept 11 recent), and backfilled 31 files Datto had but QSD lacked (30 via server-side copy from the old site, 1 — `2025.requested items for bone bank audit.pdf` — uploaded from the Datto host via a pre-authenticated upload session). Final QSD ~3,766 files with 0 Datto files missing; the only remaining diff is 13 files under a renamed folder (`Lab Log.2020 to Current` vs Datto's `2020 to 2024`). Archived the duplicate site: copied the divergent `Processor Contact Information...Surgenex 8.21.24.xlsx` from the old site into QSD alongside its counterpart, ran a pre-delete safety delta (0 unaccounted recent edits), then deleted the old `Quality Department` M365 group/site. The Tenant Admin app 403s on group DELETE (has GroupMember write, not Group.ReadWrite.All); the **User Manager app** performed the delete (HTTP 204). Group soft-deleted (restorable ~30 days; site recycle ~93 days). Then handled migration corruption: the Surgenex xlsx Mike tried to open errored ("file format not valid"). Diagnosed the byte-array->decimal-text corruption (header `80 75 3 4...` instead of `PK\x03\x04`); the 64 KB QSD copy was corrupt, the 20 KB old-site copy clean and newer — deleted the corrupt copy and renamed the clean one to canonical (after a WOPI lock cleared). A QSD-wide sweep found **81 corrupt files** (60 docx/17 pdf/2 xlsx/2 doc), more than a parallel session's earlier 47 (my reconciliation propagated corrupt orphans via byte-preserving copy). Coordinated with the parallel session (coord todo 28e3e7ab): appended reconciliation caveats + the live 81 count as child todos, and graduated their recovery tool `bb-recover.py` from session scratchpad into the repo at `clients/birth-biologic/scripts/`. Recovery itself remains deferred per Mike. Finally, on a context switch, ran a read-only DC health verification on Peaceful Spirit's PST-SERVER (192.168.0.2) via RMM: PST-SERVER healthy (all 5 FSMO, dcdiag clean, SYSVOL/NETLOGON shared, SYSVOL Event 4602 from the 06-13 D4 restore), but PST-SERVER2 unreachable (ping fails, RPC 1722, ~16 days stale) — Gate-4 DFSR work blocked until SERVER2 is back online. ## Key Decisions - **Datto = source of truth** for the Quality reconciliation; the Datto-aligned path is the keeper in any duplicate pair. Confirmed dupes removed only when a byte-identical Datto-aligned twin remained in QSD (no unique data lost). - **Did not bulk-delete by path.** Path comparison flagged 1,016 SP files "not in Datto," but 921 were the same files reorganized into different folders. Switched to hash-based dedup to avoid destroying real data; surfaced this to Mike rather than executing the literal rule. - **Backfill via server-side copy from the old site** (not Datto host upload) for 30 of 31 files — cheaper and byte-identical; only the 1 file absent from the old site needed a host upload. - **In-place reconstruct is the right recovery method** (the parallel session's bb-recover.py PUTs recovered bytes to the same item id, preserving share links) — better than my re-copy approach. Graduated their tool rather than writing a competing one. - **Deleted the old site via the User Manager app** after the Tenant Admin app 403'd on group delete — different app tier for the privilege. - **Surgenex fix by swap, not reconstruct** — a clean newer copy existed on the old site, so swapping it in was more reliable than reconstructing the corrupt bytes. - **All destructive ops gated behind dry-runs + recycle bin** — every deletion recoverable ~93 days. ## Problems Encountered - **Path-based "not in Datto" was misleading** — 921 of 1,016 were reorg copies; resolved by switching to content-hash dedup. - **Timestamp filter poisoned by migration copies** — 1,007 orphans carried today's date from my earlier copy; used the old site's lastModified as the true-age signal instead. - **Tenant Admin app cannot delete M365 groups** (403, GroupMember-only) and cannot manage SP site state (`Unsupported app only token`) — used the User Manager app for group delete; SP site lock/spoke-site grants pushed to Mike via PnP. - **WOPI lock (HTTP 423)** blocked the Surgenex swap while the file was open in Excel; retried after Mike closed it. - **RMM stdout capped** the base64 of the 6.8 MB file (got 786 KB of 6.8 MB) — switched to a pre-authenticated Graph upload session so the host PUT the bytes directly. - **bash `${var/pat/repl}` mangled the upload URL** (& separators) — rewrote the PS script via Python and dispatched with `jq --rawfile`. - **Corruption scan kwarg bug** (`requests.get got multiple values for 'headers'`) — fixed the retry wrapper to merge headers. - **errorlog.md rebase conflict** on sync (concurrent top-prepends from another session) — resolved keeping all entries. - **bb-recover.py was stranded in another session's scratchpad** (session-local path) — graduated to the repo so any machine can run it. ## Configuration Changes - Created `clients/birth-biologic/docs/migration/2026-06-29-quality-dept-archival-plan.md` (then marked COMPLETED). - Created `clients/birth-biologic/scripts/bb-recover.py` (graduated recovery tool; pushed in 801ff788). - Modified `errorlog.md` (friction: group-delete app gap; + conflict resolution). - SharePoint (QSD, tenant 19a568e8-...): +sysadmin@ owner/member on QSD group; 811 dupes deleted; 195 stale SP-only deleted; 31 files backfilled; Surgenex corrupt copy deleted + clean copy renamed. - Deleted old `Quality Department` M365 group/site (soft-deleted). - Coord todos: appended children 5162f79f (caveats) + ac832238 (live 81 count) under 28e3e7ab. ## Credentials & Secrets - No new credentials created or discovered. Used (read-only) from vault: - `msp-tools/computerguru-tenant-admin.sops.yaml` field `credentials.client_secret` (app 709e6eed-0711-4875-9c44-2d3518c47063) — Graph app-only against BirthBio tenant. - `msp-tools/computerguru-user-manager.sops.yaml` field `credentials.client_secret` (app 64fac46b-8b44-41ad-93ee-7da03927576c) — used for the M365 group delete (has Group.ReadWrite.All). - bb-recover.py reads the Tenant Admin secret via env `BBSEC` (not embedded). ## Infrastructure & Servers - **BirthBio M365 tenant:** 19a568e8-9e88-413b-9341-cbc224b39145 - **QSD site:** birthbiologic.sharepoint.com/sites/QualitySystemsDepartment (site id ...,3173c017-58bd-406a-8858-2c969667336f,...; single drive "Documents") - **Old (deleted) group id:** f24b2e10-2d73-49d7-ab06-fe63065301d1 (QualityDepartment@), deletedDateTime 2026-06-29T22:23:15Z - **Datto source host:** ACG-DWP-X-BB (172.16.3.45), RMM agent a4524e85-8a07-45d0-91b1-51ce7e2ca74a; source tree `C:\Users\Public\Desktop\Datto Workplace Server Projects\Quality Department` (3,812 files) - **Peaceful Spirit:** PST-SERVER 192.168.0.2 (all 5 FSMO, Server 2016, RMM 87293069-33b6-45e8-a68f-6811216cdb96); PST-SERVER2 192.168.1.127/192.168.1.5 (RMM 5d2d7ba0-3903-4aa3-9e97-6ca4424ffe65) — UNREACHABLE. ## Commands & Outputs - Graph app-only token: POST login.microsoftonline.com/{tenant}/oauth2/v2.0/token, scope graph.microsoft.com/.default, grant client_credentials. - Dedup keep-rule: same quickXorHash, keep copy whose path is in the Datto path set. - Group delete: `DELETE /groups/{id}` — 403 via Tenant Admin app, **204 via User Manager app**. - Pre-auth upload: `POST /drives/{id}/root:/{path}:/createUploadSession` -> host PUTs bytes to uploadUrl. - DC verify (PST-SERVER): dcdiag Advertising/FSMOCheck/Services PASSED; `repadmin /replsummary` PST-SERVER2 fails 5/5 error 1722; ping PST-SERVER2 = False. ## Pending / Incomplete Tasks - **BirthBio QMS corruption recovery (DEFERRED, todo 28e3e7ab):** ~81 corrupt files in QSD. Run `clients/birth-biologic/scripts/bb-recover.py birthbiologic.sharepoint.com:/sites/QualitySystemsDepartment` (dry-run) then `--apply` (set BBSEC). Re-scan live; do NOT trust the saved 47-list. Then widen the scan tenant-wide (Admin/Donor Services/Supply were in the same 6/26 corrupt batch). - **Spoke + [admin] site access:** Mike to run the PnP grant (DM'd) for sysadmin@ on the 5 groupless sites. - **Quality ticket write-up** (drafted in Mike's voice) NOT yet posted — needs ticket # (assumed #32187), visibility (customer/internal), and billing decision. - **Surgenex two-version note** moot now (corrupt copy removed; one clean file remains). - **Peaceful Spirit:** PST-SERVER2 is dark — confirm whether it should be online; Gate-4 DFSR (backlog drain, re-add folder/root targets) blocked until it is. If PST-SERVER was full-restored, run a deeper post-restore DC pass (USN/invocationID, dcdiag /test:Replications, DNS SRV). - **6 files** returned fetch-errors during the corruption sweep — re-check on recovery run. ## Reference Information - Coord todos: 28e3e7ab-f77d-4d4f-b2e0-15f0254155ea (parent recovery), 5162f79f-de05-49d3-9f16-546f8d11c241 (caveats), ac832238-69f0-421f-9cc3-e9a7537d8ede (live 81 count). - Pushed commit: 801ff788 (bb-recover.py graduation + errorlog). - Recovery tool: clients/birth-biologic/scripts/bb-recover.py (BBSEC env = tenant-admin client_secret). - Archival plan: clients/birth-biologic/docs/migration/2026-06-29-quality-dept-archival-plan.md - Peaceful Spirit runbook: clients/peaceful-spirit/AD-DC2-REBUILD-RUNBOOK.md