Skip to content

Change-volume guard counts linked accounts; quieter linking for deactivated accounts; AD deactivate writes EmployeeID — release 26.10.9.1 - #16

Merged
SamSCN merged 2 commits into
mainfrom
feature/linked-accounts-guard
Oct 9, 2026
Merged

SamSCN merged 2 commits into
mainfrom
feature/linked-accounts-guard

Conversation

@SamSCN

@SamSCN SamSCN commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Three changes from reviewing a live run at a students-only district.

  • The change-volume guard counts linked accounts, not an OU, in both directories. Each directory's population was "users at or below userRootOU", and that miscounted on both sides:

    • AD: the shipped templates put the trash OU inside the root, so every disabled, trashed account counted and the population grew every year. Unsynced accounts under the root (staff at a students-only site) counted too.
    • Google: userRootOU could name only one OU, so /Students + /Staff meant undercounting, or '' and counting every admin, kiosk and archived account. A root that doesn't exist (seen at a district: /Colby) silently turned the guard off.

    The population is now the active accounts carrying IDBridge's personID link, wherever they sit:

    • AD: enabled with an EmployeeID (Get-ADManagedUserCount). This assumes nothing else writes EmployeeID.
    • Google: not suspended or archived, with an organization externalId (Get-GoogleManagedUserCount).

    Both are read from directory state only, so a broken feed can't shrink them. Google.userRootOU is retired: ignored with a Trace line, and dropped from the config template (TemplateVersion 4). AD.userRootOU is now only Initialize-IDBridgeADServiceAccount's delegation OU.

  • Quieter linking for already-deactivated accounts. Linking matched every unlinked source user and logged "will link EmployeeID" at Info. For a user who is inactive or unprovisioned in a directory and whose account there is already disabled (AD) or suspended/archived (Google), nothing ever wrote the link, so the line repeated every run. It now logs at Trace as "nothing to reconcile". The match is still returned, and every other case keeps its Info line word for word.

  • AD deactivation persists the EmployeeID. Disable-IDBridgeADUser now sets EmployeeID on name-matched accounts in the same disable write, mirroring Google's deactivate step. Get-ADUsersToDeactivate logs it at plan time.

  • Release 26.10.9.1 as the last commit.

Behavior change

The guard's percentages change at every site. Usually it gets stricter, because trashed, unsynced and unlinked accounts no longer pad the population. A fresh tenant has nothing linked yet, so the guard skips with a Warn until the first run links accounts. Onboarding a new source type is measured against the accounts already linked: review with -Preview, and run once with -SkipChangeThreshold if it trips.

Verification

  • Pester before (main at 26.10.9.0): 259 passed, 0 failed. After: 274 passed, 0 failed (13 new cases + 2 structural). Each new behavior case was written first and failed against the old code; the regression guards (the Info "will link" line staying put) passed against it. Test-ModuleManifest passes at 26.10.9.1.
  • Disable-IDBridgeADUser's write is execute-phase, which the suite doesn't cover. It was verified with stubbed Set-ADUser/Move-ADObject/Remove-ADGroupMember (the script aborts unless the stubs shadow the real cmdlets): a name-matched account gets EmployeeID in the disable write, and an already-linked account is not rewritten.
  • Not executed: a live run against AD or Google.

After merge

Tag the merge commit v26.10.9.1, which publishes to the Gallery and creates the GitHub Release. Sites can delete Google.userRootOU from their config after updating.

🤖 Generated with Claude Code

SamSCN and others added 2 commits October 9, 2026 15:22
…g for deactivated accounts; AD deactivate writes EmployeeID

Guard: each directory's population is now the active accounts carrying IDBridge's personID
link, wherever they sit - AD: enabled with an EmployeeID (Get-ADManagedUserCount); Google: not
suspended/archived with an organization externalId (Get-GoogleManagedUserCount). The old
root-OU count included disabled accounts in the AD trash OU (inside the root) and unsynced
accounts, and Google.userRootOU could name only one OU (a nonexistent one silently disabled the
guard). Google.userRootOU is retired (ignored with a Trace line; dropped from the config
template, TemplateVersion 4); AD.userRootOU is now only the service account's delegation OU.

Linking: a user who is inactive or not provisioned in a directory and whose account there is
already disabled/suspended/archived was logged "will link EmployeeID" at Info every run while
nothing ever wrote the link; it now logs at Trace as "nothing to reconcile".

AD deactivate: Disable-IDBridgeADUser sets EmployeeID on name-matched accounts in the disable
write (Google's deactivate already persisted its link), and Get-ADUsersToDeactivate logs it at
plan time.

Tests for all decide-phase changes; the AD disable write was verified with stubbed cmdlets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SamSCN
SamSCN merged commit f3e2730 into main Oct 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant