Skip to main content

Diff engine

For a technical explanation of how the diff engine works internally, see Reference: Diff Engine.

Filter fields from diff output

$script:DiffIgnoreProperties in src/diff.ps1 controls which API fields are hidden in the diff preview, in emails, webhooks, and the HTML scan report. Fields in this list are skipped when rendering what changed; they do not affect change detection itself.

Edit the array in src/diff.ps1:

$script:DiffIgnoreProperties = [System.Collections.Generic.HashSet[string]]::new(
[string[]]@(
'@odata.context', '@odata.type', '@odata.id',
'id', 'templateId', 'target',
'createdDateTime', 'modifiedDateTime', 'createdUsing',
'lastModifiedDateTime', 'lastModifiedBy'
),
[System.StringComparer]::OrdinalIgnoreCase
)

Default fields and why they are filtered:

FieldReason
@odata.context, @odata.type, @odata.idOData protocol metadata, never user-controlled
id, templateIdAPI-assigned identifiers, not configuration
targetStructural rule scope (caller/level): identifies the rule, not its settings
createdDateTime, modifiedDateTime, createdUsingSystem-managed timestamps
lastModifiedDateTime, lastModifiedByAudit trail fields, not configuration

To hide an additional field, add its name to the array:

'id', 'templateId', 'target', 'myNoiseField',

To make a field visible again, remove it from the array. The field will then appear as a red/green diff line in notifications whenever it changes.

note

Field matching is case-insensitive. Adding 'displayName' also silences DisplayName.

Change object equality

By default, Test-ObjectEqual in src/diff.ps1 normalizes both objects to deterministic JSON and compares the strings. You can modify it to exclude fields before comparing:

function Test-ObjectEqual {
param($Left, $Right)
# Example: strip a field before comparing
$l = $Left | ConvertTo-Json -Depth 20 -Compress | ConvertFrom-Json
$r = $Right | ConvertTo-Json -Depth 20 -Compress | ConvertFrom-Json
$l.PSObject.Properties.Remove('lastModifiedDateTime')
$r.PSObject.Properties.Remove('lastModifiedDateTime')
return (ConvertTo-DeterministicJson $l) -eq (ConvertTo-DeterministicJson $r)
}

Change the assignment key

The assignment key determines how old and new assignments are matched. Edit Get-AssignmentKey in src/diff.ps1:

# Default for Directory Roles:
$key = "$principalId|$directoryScopeId"

# To also include roleDefinitionId (for multi-role scenarios):
$key = "$principalId|$directoryScopeId|$roleDefinitionId"

Change how removed entities are detected

By default, a role or group is considered removed if its folder no longer appears in the current fetch. To change the comparison (for example, match by display name instead of slug):

Edit Get-RemovedEntities in src/diff.ps1.

Change removed entity severity

By default, removed entities (roles or groups that disappear from the tenant) are classified as High. To change this:

Edit Get-RemovedEntities in src/diff.ps1:

$severity = "Medium" # was "High"