Swazee mark Product (type slug) Tool (chevron-wrench) Experiment (4-point star) Active (filled diamond) Shipped (hollow diamond) Shelved (diamond + slash) External link (↗) Search (angular magnifier) Filter (funnel) Close / Esc (chunky X) Move down (j) Move up (k) Return / Enter
SWAZEENET
VOL. I · NO. 01 · EST. MCMLXXXVII
BROADSIDE 12 active · 2026·05·14
№ 07 · tool · PowerShell 5.1+ · 2025—

corvus,
an audit of who you are, across systems.

A read-only PowerShell module that triages duplicate Active Directory user objects in environments federating Oracle HCM, Workday, UKG, SailPoint, CyberArk, AD, and Entra ID.

powershell identity

corvus is one PowerShell module file --- ~1500 lines, 29 exported functions --- that runs against an existing AD environment and writes JSON / CSV / summary artifacts. It is read-only by design. Detectors investigate and report; nothing in the module ever calls Set-AD* or Remove-AD*. The wrapper script Invoke-Corvus.ps1 runs preflight + a full sweep and lands a run folder under %TEMP%\Corvus\<RunId>\.

ITech scope

IIWhat “read-only” means here

The module never calls a write cmdlet against any directory. Detectors investigate and report; remediation is the operator’s responsibility, performed in their own change-control process under their own approvals. This is preserved as an invariant: every new detector is reviewed against the rule, the test harness uses a mock directory whose write methods throw NotImplementedException, and a contributor adding a Set-AD* or Remove-AD* call would have to do so deliberately and against active resistance. The "RO" plate above is a contract, not a description.

The deeper reason is that auditors and IGA leads have to be able to point at corvus and say "this can’t make the problem worse." A triage tool that holds write credentials introduces a new compromise vector by existing; corvus eliminates it by construction.

IIIIdentity normalization

Every connector has its own definition of "the same person." Workday’s worker id is canonical inside Workday and meaningless to AD; SailPoint’s identityName may match Entra’s userPrincipalName but only after a normalization pass that strips domain suffixes and Unicode case-folds. corvus does the normalization explicitly — the rules live in $script:Config.IdentityKeys as data, not as code, so a triage-time rule change is a config edit rather than a module re-publish. Idempotency is non-negotiable: the same input across the same seven sources yields a byte-identical duplicate ledger across runs, which is what makes corvus reports comparable week over week.

IVOutput

One run produces three artifacts in %TEMP%\Corvus\<RunId>\, where RunId is an ISO-8601-ish stamp plus a four-character entropy suffix so concurrent runs from a shared host don’t collide:

Fig. I.
01pull 02normalize 03match keys 04score duplicates 05report
as of 2026-04-26
Fig. II.
AD1200021% Entra1100019% Workday900016% HCM850015% UKG810014% SailPoint780014% CyberArk9002%
as of 2026-04-26

VSurface

The surface is a PowerShell module: Import-Module corvus; Invoke-CorvusTriage -Sources @(...). Read-only by contract — the module is configured with read-only credentials for the seven sources, so the worst it can do operationally is exhaust a connector’s rate budget. Output is a normalized inventory table per source (one row per identity record, with a stable schema across vendors) plus a cross-source duplicate ledger keyed on a deterministic identity hash. The hash is the join key that lets a duplicate cluster span Workday + AD + Entra without depending on any one vendor’s notion of canonical id.

VIConstraints

Every connector has its own definition of “the same person.” Workday’s worker id is canonical inside Workday and meaningless to AD; SailPoint’s identityName may match Entra’s userPrincipalName but only after a normalization pass that strips domain suffixes and Unicode case-folds. corvus does the normalization explicitly and exposes the rules as data (in $script:Config.IdentityKeys), not as code, so a triage-time rule change is a config edit rather than a module re-publish. Idempotency is non-negotiable: the same input across the same seven sources yields a byte-identical duplicate ledger across runs, which is what makes corvus reports comparable week over week and trustworthy as evidence in an audit conversation.

:/ ESC