Skip to content

release: v1.3.3 — AD account status detection & opt-in SkipDisabledUsers (#21)#23

Merged
luigilink merged 2 commits into
mainfrom
release/1.3.3
Jul 9, 2026
Merged

release: v1.3.3 — AD account status detection & opt-in SkipDisabledUsers (#21)#23
luigilink merged 2 commits into
mainfrom
release/1.3.3

Conversation

@luigilink

Copy link
Copy Markdown
Owner

Closes #21. Ships the 1.3.3 release, which also includes the already-merged CI Node 20 action bumps (#22).

Why

Field analysis of the large Not Added population showed it is mostly departed employees the customer keeps in the SharePoint User Information List for permission history. Two departure shapes must both be handled — disabled (kept in AD) and deleted (gone from AD) — and the solution must work for every customer, so it relies only on universal AD signals, never on a customer-specific leaver process (no dedicated OU, naming convention, HR feed or retention policy).

What

Detection (universal). ConvertTo-SPSUserRecord reads the userAccountControl attribute (bit 0x2 = ACCOUNTDISABLE) and exposes two additive fields on every record: AccountStatus (Active / Disabled / NotFound) and Enabled. SPSyncUserInfoList carries AccountStatus into the JSON snapshot. A resolved entry with no userAccountControl (some non-AD LDAP directories) stays Active, unchanged.

Handling (opt-in, backward-compatible).

  • New SkipDisabledUsers in sync-settings.psd1 (default $false = pre-1.3.3 behaviour). When $true, SPSyncUserProfile reports Disabled accounts as Not Added instead of provisioning them.
  • Every Not Added entry is tagged with a NotAddedReasonAD_NOT_FOUND (deleted/departed, or a forest not declared in ad-domains.psd1), MISSING_ATTRIBUTES, or DISABLED — and the run prints the per-reason breakdown, so an expected miss is easy to tell apart from an actionable one.
  • The gate is isolated in a testable Split-SPSProfileUser helper.

Visibility. The SPSyncUserInfoList HTML report gains an AD Status column and a Disabled in AD summary card (with a note pointing at SkipDisabledUsers), so disabled/departed accounts are visible before the profile sync runs.

Guarantees for every customer

Leaver shape Universal signal used
Account disabled, kept in AD userAccountControl bit 0x2
Account deleted from AD null lookup → AccountStatus NotFound

No dependency on OU layout, naming, HR feeds or retention. Defaults preserve current behaviour; nothing changes unless SkipDisabledUsers is set.

Compatibility

  • AccountStatus is additive; older consumers ignore it, and a pre-1.3.3 snapshot (no AccountStatus) reports 0 disabled and provisions exactly as before.
  • SkipDisabledUsers acts on the status written by SPSyncUserInfoList 1.3.3+, so regenerate the JSON snapshot after upgrading for it to take effect (documented in the release notes / wiki).
  • [Int32]::TryParse (2-arg) keeps parsing Windows PowerShell 5.1 / .NET Framework safe (same lesson as the 1.3.2 [Enum]::Parse fix).

Tests

  • ConvertTo-SPSUserRecord: active / disabled (514) / disable-bit-with-other-flags (66050) / string uac / no-uac (backward compatible) / null entry → NotFound.
  • Split-SPSProfileUser: eligible vs Not-Added routing, reason tagging, SkipDisabledUsers on/off, pre-1.3.3 snapshots.
  • Export-SPSUserReport: AD Status column + Disabled card + note, and backward-compat (no AccountStatus).
  • Full suite green locally (100 passed, 0 failed); PSScriptAnalyzer clean. End-to-end JSON round-trip verified.

Follow-up (not in this PR)

  • An undeclared-domain warning in readiness/InfoList to split AD_NOT_FOUND into "forest not declared" (actionable) vs "deleted in a reachable forest" (expected).

luigilink added 2 commits July 9, 2026 20:32
Handle departed employees correctly using only universal Active Directory
signals, so it works for every customer regardless of their leaver process.

- ConvertTo-SPSUserRecord reads userAccountControl (bit 0x2 = ACCOUNTDISABLE)
  and exposes AccountStatus (Active/Disabled/NotFound) and Enabled. A resolved
  entry with no userAccountControl (some non-AD LDAP directories) stays Active,
  unchanged from before. PS 5.1-safe [Int32]::TryParse.
- SPSyncUserInfoList carries AccountStatus into the JSON snapshot, and its HTML
  report gains an 'AD Status' column and a 'Disabled in AD' card (note pointing
  at SkipDisabledUsers) so disabled/departed accounts are visible at a glance.
- SPSyncUserProfile: new opt-in SkipDisabledUsers (default $false = unchanged
  behaviour) reports Disabled accounts as Not Added instead of provisioning
  them. Each Not-Added entry is tagged with a NotAddedReason (AD_NOT_FOUND,
  MISSING_ATTRIBUTES or DISABLED) and the run prints the breakdown. Logic
  extracted into a testable Split-SPSProfileUser helper.
- Resolve-SPSADUserBatch fallback records gain the two fields for shape parity.
- Tests: account-status projection, Split-SPSProfileUser routing, and the report
  AD Status column / Disabled card (+ pre-1.3.3 backward-compat). Docs updated.

Fixes #21
Bump module to 1.3.3; changelog and release notes for AD account status
detection + SkipDisabledUsers and the UserInfoList report AD Status column
(#21), plus the CI Node 20 action bumps (#22).
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Pester Test Results

100 tests   100 ✅  3s ⏱️
 24 suites    0 💤
  1 files      0 ❌

Results for commit c60fa4d.

@luigilink luigilink merged commit dfcfb2e into main Jul 9, 2026
4 checks passed
@luigilink luigilink deleted the release/1.3.3 branch July 9, 2026 18:40
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.

AD account status detection (active / disabled / deleted) for correct handling of departed users

1 participant