Public/New-RBACGrantScript.ps1

function New-RBACGrantScript {
    <#
    .SYNOPSIS
        Generates idempotent grant / revoke snippets for a role on a platform.
 
    .DESCRIPTION
        Dispatches to the platform provider to emit ready-to-run, idempotent
        PowerShell that grants (AddScript) or revokes (RemoveScript) a single role
        for a caller at a scope. The snippets are platform-native:
 
          * Azure - New-/Remove-AzRoleAssignment at an ARM scope.
          * Graph - Entra directory-role assignment via Microsoft.Graph.
          * Fabric - workspace role assignment via the Fabric REST API.
          * Purview - metadata-policy edit guidance (Purview has no one-call grant).
 
        This function only produces text; it makes no change. Run the snippet from
        an identity that holds the corresponding management permission.
 
    .PARAMETER Platform
        Platform name or alias.
 
    .PARAMETER CallerId
        The identity to grant or revoke.
 
    .PARAMETER Role
        The role to assign.
 
    .PARAMETER Scope
        The scope the assignment applies to.
 
    .PARAMETER Options
        Optional provider hashtable (e.g. @{ WorkspaceId = '...'; Collection = '...'; Endpoint = '...' }).
 
    .EXAMPLE
        New-RBACGrantScript -Platform Azure -CallerId a@b.com -Role Reader `
            -Scope /subscriptions/SUB1
 
    .OUTPUTS
        PSCustomObject (PSAutoRBAC.GrantScript) with AddScript and RemoveScript.
    #>

    [CmdletBinding()]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '',
        Justification = 'Generates script text only; makes no state change.')]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Platform,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$CallerId,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Role,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Scope,

        [Parameter()]
        [hashtable]$Options
    )

    Write-PSFMessage -Level Verbose -Message "New-RBACGrantScript: '$Role' for '$CallerId' on '$Platform' at '$Scope'." -Tag 'PSAutoRBAC', 'Public'
    $provider = Get-RBACProviderInternal -Platform $Platform
    $opts = if ($Options) { $Options } else { @{} }
    $scripts = & $provider.NewGrantScript $CallerId $Role $Scope $opts
    Write-PSFMessage -Level Debug -Message "New-RBACGrantScript: generated grant/revoke snippets for '$($provider.Name)'." -Tag 'PSAutoRBAC', 'Public'

    [pscustomobject]@{
        PSTypeName   = 'PSAutoRBAC.GrantScript'
        Platform     = $provider.Name
        CallerId     = $CallerId
        Role         = $Role
        Scope        = $Scope.TrimEnd('/')
        AddScript    = $scripts.AddScript
        RemoveScript = $scripts.RemoveScript
    }
}