Public/New-KritTcmSnapshot.ps1

function New-KritTcmSnapshot {
    <#
    .SYNOPSIS
        Kick off a TCM configuration snapshot job - exports current tenant config
        across selected workloads to a declarative representation.

    .DESCRIPTION
        Wraps POST /v1.0/admin/configurationSnapshotJobs per the TCM API reference.
        Returns the job object with Id you can poll via Get-KritTcmSnapshot.

    .PARAMETER Workloads
        Subset of: Defender, Entra, Exchange, Intune, Purview, Teams.
        Default: all 6 workloads (full tenant snapshot).

    .PARAMETER DisplayName
        Friendly job name. Defaults to 'KritTcm-Snapshot-<utc>'.

    .EXAMPLE
        # Full-tenant snapshot
        $job = New-KritTcmSnapshot
        Get-KritTcmSnapshot -JobId $job.Id # poll status

    .EXAMPLE
        # Entra + Exchange only
        New-KritTcmSnapshot -Workloads Entra,Exchange -DisplayName 'preflight-2026-07'

    .NOTES
        Requires ConfigurationMonitoring.ReadWrite.All app permission on the calling
        principal (NOT the TCM SP). Run Initialize-KritTcmTenant first.
        During preview only snapshot + drift detection are supported; push/remediate
        comes later (per microsoft365dsc.com transition blog).
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='Low')]
    param(
        [string[]]$Resources,
        [ValidateSet('Defender','Entra','Exchange','Intune','Purview','Teams')]
        [string[]]$Workloads = @('Defender','Entra','Exchange','Intune','Purview','Teams'),
        [string]$DisplayName = "KritTcm-Snapshot-$(Get-Date -F yyyyMMddHHmmss)",
        [string]$Description = 'Kritical TCM snapshot'
    )
    if (-not $Resources -or $Resources.Count -eq 0) {
        throw 'The current TCM createSnapshot API requires explicit -Resources names, for example microsoft.exchange.sharedmailbox,microsoft.exchange.transportrule. Use generated coverage to choose the intended workload resources.'
    }

    $body = @{
        displayName = $DisplayName
        description = $Description
        resources   = @($Resources)
    } | ConvertTo-Json -Depth 4

    if ($PSCmdlet.ShouldProcess('Microsoft Graph', "POST /admin/configurationManagement/configurationSnapshots/createSnapshot (resources=$($Resources -join ','))")) {
        $r = Invoke-MgGraphRequest -Method POST -Uri 'https://graph.microsoft.com/v1.0/admin/configurationManagement/configurationSnapshots/createSnapshot' -Body $body -ContentType 'application/json'
        [PSCustomObject]@{
            Action='New-KritTcmSnapshot'; JobId=$r.id; Status=$r.status
            DisplayName=$DisplayName; Workloads=$Workloads; Resources=$Resources
            CreatedDateTime=$r.createdDateTime
            RawResponse=$r
        }
    }
}