## User
- **User:** Mike Swanson (mike)
- **Machine:** GURU-5070
- **Role:** admin

## Session Summary

Worked two BirthBiologic migrations in parallel: the Datto Workplace → SharePoint migration and a
new Google Workspace → M365 mail migration. The Datto/SharePoint thread started as a "verify current
state" task but Mike clarified the migration host is a Jupiter VM, not BB-SERVER. Located it as the
libvirt domain "Windows Server 2016" (actual Windows hostname **ACG-DWP-X-BB**, actually Server 2019
build 17763) — an ACG-owned migration box running Datto Workplace Server + SPMT, **not enrolled in
RMM** and sitting on an APIPA address (no LAN). Diagnosed: host bridging was fine (vnet14 enslaved to
br0, carrier up); the guest simply wasn't getting a DHCP lease from pfSense after ~2 months parked.
Fixed with a static IP (172.16.3.45/22), installed the GuruRMM agent (enrolled under BirthBiologic /
Main Office), and confirmed Datto Workplace Server reconnected and is re-syncing. Established (via the
qemu guest agent and SPMT job storage) that the April 2026 migration only completed Supply Management
(160 files, custom script) + ITSvcs (excluded); the four large folders (Admin 5.8 GB, Donor Services
109 GB, Quality 28 GB, Activity Reports) were SPMT's job and last ran 2026-04-29 — completion still
unconfirmed. Per Mike, full reconciliation waits until Datto finishes re-syncing.

The larger thread was standing up the **Google Workspace → M365 mail migration** end-to-end. Confirmed
the Google super-admin (`sysadmin@birthbiologic.com`) lives in 1Password (Clients vault item "Google");
read it via the SOPS-vaulted 1Password service-account token and mirrored it into SOPS. Onboarded
BirthBio's tenant for **Exchange Operator** (already had Tenant Admin consented, so the suite was
provisioned programmatically — Exchange Operator SP created + Exchange Administrator role). Pulled the
authoritative Google roster via domain-wide delegation (20 accounts: 15 active, 5 suspended),
reconciled against M365, and surfaced two active accounts not on Mike's list (Dr. Chris Gillis
`medicaldirector@`, Michael Merritt `mmerritt@`) plus an address mismatch (Mindi is `mindim@` in
Google, `mmaher@` in M365).

Provisioned the M365 target side to Mike's licensing rules: active-12 → Business Premium (assigned BP
to Mei Mei + Valerie, freed Savanna's BP by moving her to Exchange-only); created Gillis + Merritt with
Exchange-only and vaulted their passwords; licensed the 4 disabled former employees with Exchange-only
(kept sign-in disabled) as future shared-mailbox targets. License math closed exactly: 14 Business
Premium + 7 Exchange Online Plan 1, all consumed.

Hit a real blocker creating the Gmail migration endpoint: Google returned `unauthorized_client … not
authorized for any of the scopes requested`. Root cause = the DWD grant had only 3 of Microsoft's
required **5** scopes (missing `m8/feeds` and `gmail.settings.sharing`); Google rejects the migration
token all-or-nothing. Verified the exact 5-scope string against live MS Learn + a Grok live-search
cross-check (Gemini CLI was down on this box), updated our runbook, and Mike re-authorized all 5 in the
BB Google console. After that the endpoint (`BB-Gmail`) created cleanly and **Batch 1 (14 live
mailboxes, mail + calendar + contacts) was created and auto-started — Status: Syncing**.

## Key Decisions

- **Datto VM gets a static IP (172.16.3.45), not a pfSense DHCP fix.** The fault was pfSense not
  leasing this MAC after a long park; a static on the ACG server range (172.16.3.x) is the reliable,
  convention-consistent fix. Follow-up: add a pfSense reservation or confirm it's outside the DHCP pool.
- **Enrolled the Datto VM under BirthBiologic / Main Office** (not AZ Computer Guru) since the box exists
  solely for BirthBio's migration and we had that site key; reversible (agents can be moved).
- **Former employees migrate to shared mailboxes via a temp Exchange-only license** (migrate into a
  licensed mailbox → convert to shared ≤50 GB = free → reclaim license). Source Google accounts must be
  **un-suspended** during migration (Gmail API can't read suspended accounts).
- **Licensing tiers (Mike's rules):** active-users-list → Business Premium; live Google accounts not yet
  in M365 (Gillis, Merritt) → Exchange-only ("E1" = Exchange Online Plan 1); formers → Exchange-only
  (reclaimable). `operations@` stays BP through migration. Existing BP users left on BP (not downgraded).
- **Batch sequencing:** live users first (Batch 1); formers as Batch 2 after un-suspending them in Google
  and freeing Workspace seats by suspending already-migrated live users.
- **Mindi mapped via the CSV `Username` column** (`EmailAddress=mmaher@`, `Username=mindim@`) — the
  proper MS mechanism — plus a belt-and-suspenders `mindim@` proxy on her mailbox.
- **Target delivery domain = `birthbiologic.onmicrosoft.com`** for Batch 1 (no routing subdomain exists;
  acceptable for a near-term cutover; MS prefers a subdomain for long coexistence).
- **Drove Exchange via REST `InvokeCommand`** (Exchange Operator app token) — the EXO PowerShell module
  isn't installed and the app has no vaulted cert, so app-only Connect-ExchangeOnline wasn't available.

## Problems Encountered

- **Datto VM on APIPA (no LAN).** Host bridging fine; pfSense wasn't leasing the MAC. Fixed with static
  172.16.3.45/22, GW 172.16.0.1, DNS 172.16.0.1+1.1.1.1. Verified gateway/internet/DNS + RMM check-in.
- **`vault.sh get-field` returned `null` (len 4)** for nested secrets until the field arg used dotted
  path: `credentials.client_secret`, `credentials.credential`. Plain leaf names don't resolve.
- **SPB skuId mismatch.** The scope doc's BP GUID (`cbdc14ab-d96c-4132-b7f4-1f3a3a819bb4`) was stale; the
  tenant's real SPB skuId is `cbdc14ab-d96c-4c30-b9f4-6ada7cdc1d46`. License assign 400'd until corrected.
- **License seat propagation lag** — Valerie's BP assign 400'd ("no available licenses") immediately after
  freeing Savanna's seat; succeeded on retry seconds later.
- **`proxyAddresses` read-only via Graph** — adding Mindi's alias required Exchange `Set-Mailbox` (EXO),
  not a Graph PATCH.
- **Gmail migration endpoint failed: `unauthorized_client … not authorized for any of the scopes
  requested`.** DWD had 3 of 5 required scopes. Got the verbatim 5-scope string from MS Learn + Grok;
  Mike re-authorized; endpoint then created.
- **`onboard365.sh` vault path** — looked at `/c/Users/guru/.claude/identity.json`; fixed by exporting
  `VAULT_ROOT_ENV=/d/vault` (logged as friction).
- **GCP API enable initially run as the wrong identity** — Mike first ran `gcloud services enable` as
  `sysadmin@birthbiologic.com` (no rights to ACG's project); succeeded once run as the ACG owner of
  `acg-msp-access`.
- **Gemini CLI down** (`throwIneligibleOrProjectIdError`, needs interactive re-login) — used Grok for the
  live-doc cross-check instead. Logged to errorlog.

## Configuration Changes

- **ACG-DWP-X-BB (Jupiter "Windows Server 2016" VM):** static IP 172.16.3.45/22, GW 172.16.0.1, DNS
  172.16.0.1 + 1.1.1.1 (persistent). GuruRMM agent installed (universal installer), enrolled BirthBiologic
  / Main Office, agent `a4524e85-8a07-45d0-91b1-51ce7e2ca74a`.
- **BirthBio M365 tenant (19a568e8-…):** onboarded Exchange Operator (+ Defender Add-on) SPs via
  `onboard365.sh provision`; roles assigned (Exchange Admin on Exchange Operator + Security Investigator,
  CA Admin on Tenant Admin, User Admin + Auth Admin on User Manager).
  - License changes: Mei Mei (`msenthavy`) +BP; Valerie (`vvaneaton`) +BP; Savanna (`sabron`) BP→EXO;
    created `medicaldirector@` (Gillis) +EXO and `mmerritt@` (Merritt) +EXO; licensed `aboutte`, `araso`,
    `khoffman`, `pnelson` with EXO (kept sign-in disabled).
  - `Set-Mailbox mmaher@` added secondary `smtp:mindim@birthbiologic.com`.
  - Created Gmail migration endpoint `BB-Gmail`; created + auto-started migration batch `BB-Batch1` (14
    users, TargetDeliveryDomain `birthbiologic.onmicrosoft.com`, NotificationEmails sysadmin@).
- **Vault (pushed):** `clients/birth-biologic/google-workspace.sops.yaml`,
  `clients/birth-biologic/m365-medicaldirector.sops.yaml`, `clients/birth-biologic/m365-mmerritt.sops.yaml`.
- **Repo:** updated `projects/msp-tools/runbooks/google-workspace-to-m365-migration.md` (exact 5-scope
  string + all-or-nothing gotcha + Contacts-API-retired/People-API + GCP-owner notes).
- **errorlog.md:** gemini CLI failure entry (+ onboard365 vault-path friction).

## Credentials & Secrets

- **Google Workspace super-admin** `sysadmin@birthbiologic.com` (source tenant) — sourced from 1Password
  Clients vault item "Google"; mirrored to SOPS `clients/birth-biologic/google-workspace.sops.yaml`
  (`credentials.password`, 19 chars). Used for admin.google.com console (DWD/API) + as the migration
  impersonation admin.
- **M365 mailbox — Dr. Chris Gillis** `medicaldirector@birthbiologic.com` — created this session; password
  vaulted at `clients/birth-biologic/m365-medicaldirector.sops.yaml` (forceChangePasswordNextSignIn=true).
- **M365 mailbox — Michael Merritt** `mmerritt@birthbiologic.com` — created this session; password vaulted
  at `clients/birth-biologic/m365-mmerritt.sops.yaml` (forceChangePasswordNextSignIn=true).
- App secrets used (already vaulted): Tenant Admin `msp-tools/computerguru-tenant-admin`
  (`credentials.client_secret`); Exchange Operator `msp-tools/computerguru-exchange-operator`
  (`credentials.client_secret`); Google SA `msp-tools/acg-msp-access-google-workspace`
  (`credentials.credential`, full JSON); 1Password service token
  `infrastructure/1password-service-account.sops.yaml`.

## Infrastructure & Servers

- **ACG-DWP-X-BB** — Jupiter libvirt domain "Windows Server 2016" (actually WS2019, build 17763). Windows
  hostname ACG-DWP-X-BB. NIC virtio 52:54:00:d4:8e:59 on br0 (vnet14). Static 172.16.3.45/22. Runs Datto
  Workplace Server (svc `datto_workplace_server.default`, proc WorkplaceServer) + SPMT (under
  Administrator profile). RMM agent `a4524e85-8a07-45d0-91b1-51ce7e2ca74a`. Datto source tree
  `C:\Users\Public\Desktop\Datto Workplace Server Projects`.
- **Jupiter** 172.16.3.20 (Unraid, virsh host). LAN 172.16.0.0/22, GW pfSense 172.16.0.1. guest-exec
  helper at `/root/gx.sh` on Jupiter.
- **BB-SERVER** — RMM agent `6c02baa7-0f1c-4990-b466-c9ab9eaefd3b`. Also has Datto Workplace Server + the
  original custom-script artifacts at `C:\GuruMigration` (bb-migration-state.json shows 160 Supply Mgmt +
  49 ITSvcs uploaded in April).
- **BirthBio M365 tenant** `birthbiologic.com` / `19a568e8-9e88-413b-9341-cbc224b39145`.
  - SPs: Tenant Admin `7a199b11-97fb-4e65-917d-f8d29a53ba49`; Exchange Operator
    `bab4699b-32a3-4434-9cad-7a4a08cc4d9e`; Security Investigator `bf684a4b-…`; User Manager `3347ebcc-…`;
    Defender Add-on `161b8f61-…`. New user objects: Gillis `1bd491e1-3ba6-4214-8c6d-46426f8681da`, Merritt
    `117a3367-cd5f-4565-af11-af5ff089224f`.
  - SKUs: Business Premium (SPB) `cbdc14ab-d96c-4c30-b9f4-6ada7cdc1d46` (14/14); Exchange Online Plan 1
    (EXCHANGESTANDARD) `4b9405b0-7788-4568-add1-99614e613b69` (7/7). Accepted domains: birthbiologic.com
    (default), birthbiologic.onmicrosoft.com.
- **Google project** `acg-msp-access` (number 806899474449). SA `acg-msp-access@acg-msp-access.iam.gserviceaccount.com`,
  OAuth2 client ID `102231607889615995452`. APIs enabled: Gmail, Calendar (calendar-json), People.
- **Google roster (DWD pull):** 15 active, 5 suspended. Active staff emails per `clients/birth-biologic/
  docs/migration/google-to-m365-scope.md`; Mindi = `mindim@` (Google) ↔ `mmaher@` (M365).

## Commands & Outputs

- **Required Google DWD scopes (exact, 5, comma-separated, no spaces):**
  `https://mail.google.com/,https://www.googleapis.com/auth/calendar,https://www.google.com/m8/feeds/,https://www.googleapis.com/auth/gmail.settings.sharing,https://www.googleapis.com/auth/contacts`
  (`m8/feeds` is a still-valid alias for the contacts scope, served by People API; legacy Contacts API
  retired 2022, not enableable, not needed.)
- EXO via REST: `POST https://outlook.office365.com/adminapi/beta/{tenant}/InvokeCommand` with Exchange
  Operator app token (`scope=https://outlook.office365.com/.default`), body
  `{"CmdletInput":{"CmdletName":"…","Parameters":{…}}}`. byte[] params (ServiceAccountKeyFileData, CSVData)
  passed as **base64 strings**.
- `New-MigrationEndpoint -Gmail -Name BB-Gmail -ServiceAccountKeyFileData <b64> -EmailAddress sysadmin@birthbiologic.com` → created.
- `New-MigrationBatch -Name BB-Batch1 -SourceEndpoint BB-Gmail -CSVData <b64> -TargetDeliveryDomain birthbiologic.onmicrosoft.com -AutoStart -NotificationEmails sysadmin@` → Status=Syncing, Total=14.
- Get-MigrationUser BB-Batch1 → 14 Provisioning, 0 skipped (normal initial state).
- Datto source counts (ACG-DWP-X-BB): Admin 6,279/5.8GB · Donor Services 56,826/109GB · Quality 3,714/28GB
  · Supply Mgmt 160/33MB · Activity Reports 1 · ITSvcs 52 (excluded).

## Pending / Incomplete Tasks

- **Batch 1 monitor → MX cutover.** Watch `BB-Batch1` Provisioning→Syncing→Synced. When Synced: flip MX in
  SiteGround → M365, update SPF (`include:spf.protection.outlook.com`), enable/publish DKIM (2 CNAMEs),
  autodiscover CNAME → autodiscover.outlook.com, run final delta, then **complete** the batch.
- **Batch 2 — 5 former employees → shared.** Un-suspend each in Google (free Workspace seats by suspending
  migrated live users), run a Gmail batch (targets already EXO-licensed: aboutte, araso, khoffman, pnelson,
  sabron), then convert to shared mailboxes and reclaim the 5 EXO licenses.
- **Datto → SharePoint reconciliation.** After ACG-DWP-X-BB finishes re-syncing with Datto cloud, compare
  source vs each SharePoint site to confirm what the April SPMT run left unfinished (Admin / Donor Services
  / Quality / Activity Reports).
- **pfSense:** add a DHCP reservation for 172.16.3.45 (MAC 52:54:00:d4:8e:59) or confirm it's outside the pool.
- **Valerie VanEaton** — active (receiving daily; last *sent* 2026-05-13). Julie to confirm whether the
  mid-May send drop-off = leave/departure; if departed, move her to the former→shared track.
- **Decisions still open:** confirm Merritt's long-term tier; whether `operations@` becomes shared post-migration.
- **Wiki:** BirthBio article is stale (says migration incomplete / 13 mailboxes) — recompile.

## Reference Information

- Migration scope doc: `clients/birth-biologic/docs/migration/google-to-m365-scope.md`.
- Runbook (updated): `projects/msp-tools/runbooks/google-workspace-to-m365-migration.md`.
- MS Learn: `manually-configuring-gsuite-for-migration` (scope string), `automated-migration-neweac`,
  `google-workspace-migration-prerequisites`, `perform-g-suite-migration`.
- RMM install one-liner (BirthBio site): `irm https://rmm.azcomputerguru.com/install/BRIGHT-PEAK-5980/windows | iex`.
- Discord DMs to Mike: message_id 1520034139900739627 (initial DWD), 1520055625302675537 (corrected 5-scope).
- Vault enrollment key: `clients/birth-biologic/gururmm-site-main` (site BRIGHT-PEAK-5980, id 3b20ef97-…).
