PowerShell Setup: Control 2.13 - Documentation and Record Keeping
Last Updated: January 2026 Modules Required: PnP.PowerShell, ExchangeOnlineManagement
Prerequisites
Install-Module -Name PnP.PowerShell -Force -Scope CurrentUser
Install-Module -Name ExchangeOnlineManagement -Force -Scope CurrentUser
Automated Scripts
Create Site Structure
<#
.SYNOPSIS
Creates SharePoint site structure for AI governance documentation
.EXAMPLE
.\New-AIGovernanceSite.ps1 -AdminUrl "https://tenant-admin.sharepoint.com"
#>
param(
[Parameter(Mandatory=$true)]
[string]$AdminUrl,
[string]$SiteUrl = "/sites/AI-Governance"
)
Write-Host "=== Create AI Governance Site ===" -ForegroundColor Cyan
Connect-PnPOnline -Url $AdminUrl -Interactive
# Create site
$site = New-PnPSite -Type TeamSite -Title "AI Governance" -Alias "AI-Governance"
Connect-PnPOnline -Url "$AdminUrl$SiteUrl" -Interactive
# Create libraries
$libraries = @(
"AgentConfigurations",
"InteractionLogs",
"ApprovalRecords",
"IncidentReports",
"GovernanceDecisions"
)
foreach ($lib in $libraries) {
New-PnPList -Title $lib -Template DocumentLibrary
Write-Host "Created library: $lib" -ForegroundColor Green
}
# Create site columns
New-PnPField -DisplayName "Agent ID" -InternalName "AgentID" -Type Text -Group "AI Governance"
New-PnPField -DisplayName "Document Category" -InternalName "DocCategory" -Type Choice -Choices "Configuration","Log","Approval","Incident","Decision" -Group "AI Governance"
New-PnPField -DisplayName "Regulatory Reference" -InternalName "RegReference" -Type Choice -Choices "FINRA 4511","SEC 17a-4","SOX 404","GLBA" -Group "AI Governance"
Write-Host "Site setup complete" -ForegroundColor Green
Disconnect-PnPOnline
Export Retention Label Status
<#
.SYNOPSIS
Exports retention label application status
.EXAMPLE
.\Export-RetentionStatus.ps1
#>
Write-Host "=== Retention Label Status ===" -ForegroundColor Cyan
Connect-IPPSSession
# Get retention labels
$labels = Get-RetentionCompliancePolicy | Where-Object { $_.Name -like "*FSI*" -or $_.Name -like "*Agent*" }
Write-Host "Retention policies found: $($labels.Count)"
foreach ($label in $labels) {
Write-Host "`nPolicy: $($label.Name)" -ForegroundColor Yellow
Write-Host " Mode: $($label.Mode)"
Write-Host " Enabled: $($label.Enabled)"
Write-Host " Locations: $($label.SharePointLocation -join ', ')"
}
Disconnect-ExchangeOnline -Confirm:$false
Audit Document Completeness
<#
.SYNOPSIS
Audits AI governance documentation completeness
.EXAMPLE
.\Audit-DocumentationCompleteness.ps1 -SiteUrl "https://tenant.sharepoint.com/sites/AI-Governance"
#>
param(
[Parameter(Mandatory=$true)]
[string]$SiteUrl
)
Write-Host "=== Documentation Completeness Audit ===" -ForegroundColor Cyan
Connect-PnPOnline -Url $SiteUrl -Interactive
$requiredDocs = @(
@{Library="GovernanceDecisions"; Doc="AI-Governance-Policy"},
@{Library="GovernanceDecisions"; Doc="WSP-Addendum"},
@{Library="GovernanceDecisions"; Doc="Examination-Response-Procedure"}
)
foreach ($req in $requiredDocs) {
$items = Get-PnPListItem -List $req.Library -Query "<View><Query><Where><Contains><FieldRef Name='FileLeafRef'/><Value Type='Text'>$($req.Doc)</Value></Contains></Where></Query></View>"
if ($items) {
Write-Host "[PASS] Found: $($req.Doc) in $($req.Library)" -ForegroundColor Green
} else {
Write-Host "[FAIL] Missing: $($req.Doc) in $($req.Library)" -ForegroundColor Red
}
}
Disconnect-PnPOnline
Validation Script
<#
.SYNOPSIS
Validates Control 2.13 - Documentation and record keeping
.EXAMPLE
.\Validate-Control-2.13.ps1
#>
Write-Host "=== Control 2.13 Validation ===" -ForegroundColor Cyan
# Check 1: Site structure
Write-Host "`n[Check 1] SharePoint Site Structure" -ForegroundColor Cyan
Write-Host "[INFO] Verify AI Governance site and libraries exist"
# Check 2: Retention labels
Write-Host "`n[Check 2] Retention Labels" -ForegroundColor Cyan
Connect-IPPSSession
$labels = Get-RetentionCompliancePolicy | Where-Object { $_.Name -like "*Agent*" }
if ($labels) {
Write-Host "[PASS] Retention policies found: $($labels.Count)" -ForegroundColor Green
} else {
Write-Host "[WARN] No agent retention policies found" -ForegroundColor Yellow
}
Disconnect-ExchangeOnline -Confirm:$false
# Check 3: SEC 17a-4 compliant storage (manual)
Write-Host "`n[Check 3] SEC 17a-4 Compliant Storage" -ForegroundColor Cyan
Write-Host "[INFO] Verify immutable storage for Zone 3 (SEC 17a-4): WORM or audit-trail alternative per October 2022 amendments"
# Check 4: Examination procedures
Write-Host "`n[Check 4] Examination Procedures" -ForegroundColor Cyan
Write-Host "[INFO] Verify examination response procedure is documented"
Write-Host "`n=== Validation Complete ===" -ForegroundColor Cyan
Complete Configuration Script
<#
.SYNOPSIS
Complete documentation and record keeping configuration for Control 2.13
.DESCRIPTION
Executes end-to-end documentation setup including:
- SharePoint site structure verification/creation
- Retention policy validation
- Documentation completeness audit
.PARAMETER AdminUrl
SharePoint admin URL
.PARAMETER SiteAlias
Site alias for AI Governance site
.PARAMETER OutputPath
Path for output reports
.EXAMPLE
.\Configure-Control-2.13.ps1 -AdminUrl "https://tenant-admin.sharepoint.com" -OutputPath ".\Documentation"
.NOTES
Last Updated: January 2026
Related Control: Control 2.13 - Documentation and Record Keeping
#>
param(
[Parameter(Mandatory=$true)]
[string]$AdminUrl,
[string]$SiteAlias = "AI-Governance",
[string]$OutputPath = ".\Documentation-Report"
)
try {
Write-Host "=== Control 2.13: Documentation and Record Keeping Configuration ===" -ForegroundColor Cyan
# Connect to SharePoint Admin
Connect-PnPOnline -Url $AdminUrl -Interactive
# Ensure output directory exists
New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
# Check if site exists
$siteUrl = $AdminUrl -replace "-admin", "" -replace "sharepoint.com", "sharepoint.com/sites/$SiteAlias"
$site = Get-PnPTenantSite -Url $siteUrl -ErrorAction SilentlyContinue
if (-not $site) {
Write-Host "[INFO] Creating AI Governance site..." -ForegroundColor Cyan
New-PnPSite -Type TeamSite -Title "AI Governance" -Alias $SiteAlias
Write-Host "[PASS] Site created: $siteUrl" -ForegroundColor Green
} else {
Write-Host "[INFO] AI Governance site exists: $siteUrl" -ForegroundColor Cyan
}
# Connect to the site
Connect-PnPOnline -Url $siteUrl -Interactive
# Define required libraries
$requiredLibraries = @(
"AgentConfigurations",
"InteractionLogs",
"ApprovalRecords",
"IncidentReports",
"GovernanceDecisions"
)
# Create or verify libraries
Write-Host "`n[Step 1] Verifying document libraries..." -ForegroundColor Cyan
$libraryReport = @()
foreach ($lib in $requiredLibraries) {
$existing = Get-PnPList -Identity $lib -ErrorAction SilentlyContinue
if (-not $existing) {
New-PnPList -Title $lib -Template DocumentLibrary
Write-Host " [CREATED] $lib" -ForegroundColor Green
$libraryReport += [PSCustomObject]@{Library=$lib; Status="Created"; ItemCount=0}
} else {
Write-Host " [EXISTS] $lib - $($existing.ItemCount) items" -ForegroundColor Yellow
$libraryReport += [PSCustomObject]@{Library=$lib; Status="Existing"; ItemCount=$existing.ItemCount}
}
}
# Export library report
$libraryReport | Export-Csv -Path "$OutputPath\LibraryInventory.csv" -NoTypeInformation
# Check retention policies
Write-Host "`n[Step 2] Checking retention policies..." -ForegroundColor Cyan
try {
Connect-IPPSSession -ErrorAction SilentlyContinue
$retentionPolicies = Get-RetentionCompliancePolicy | Where-Object { $_.Name -like "*Agent*" -or $_.Name -like "*AI*" }
if ($retentionPolicies) {
Write-Host " [PASS] Found $($retentionPolicies.Count) retention policies" -ForegroundColor Green
$retentionPolicies | Select-Object Name, Mode, Enabled | Export-Csv -Path "$OutputPath\RetentionPolicies.csv" -NoTypeInformation
} else {
Write-Host " [WARN] No AI-specific retention policies found" -ForegroundColor Yellow
}
Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue
} catch {
Write-Host " [INFO] Could not check retention policies - verify manually in Purview" -ForegroundColor Yellow
}
# Summary
Write-Host "`n=== Summary ===" -ForegroundColor Cyan
Write-Host "Site URL: $siteUrl"
Write-Host "Libraries Configured: $($libraryReport.Count)"
Write-Host "Report Path: $OutputPath"
Write-Host "`n[PASS] Control 2.13 configuration completed successfully" -ForegroundColor Green
}
catch {
Write-Host "[FAIL] Error: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "[INFO] Stack trace: $($_.ScriptStackTrace)" -ForegroundColor Yellow
exit 1
}
finally {
# Cleanup connections
Disconnect-PnPOnline -ErrorAction SilentlyContinue
Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue
}
Back to Control 2.13 | Portal Walkthrough | Verification Testing | Troubleshooting