Verification & Testing — Control 1.13: Sensitive Information Types and Pattern Recognition
Scope. Operational verification procedures for Control 1.13 across Microsoft 365 Copilot, Copilot Studio, Power Platform, and SharePoint-grounded agents in US financial-services tenants. Audience. Microsoft 365 administrators, Purview engineers, internal auditors, and supervisory examiners at FINRA member firms, SEC-registered investment advisers, OCC/FRB-supervised banks, and CFTC-registered swap dealers. Sovereign coverage. Commercial · GCC · GCC High · DoD — see §5 for parity caveats. Cross-links. Portal walkthrough · PowerShell setup ·
troubleshooting.md(sibling playbook — pending publication) · Shared PowerShell baseline Last UI Verified. April 2026 (Microsoft Purview portalpurview.microsoft.com, Microsoft 365 Admin Centeradmin.cloud.microsoft).
What this verification catches
Verification of SIT and pattern-recognition coverage exists to surface failure modes that produce silent NPI exposure through agent grounding. The following ten failure modes are explicit targets of this playbook:
- Silent SIT miss in Copilot grounding. A built-in or custom SIT exists in the tenant but is not referenced by an active DLP-for-Copilot policy, so an agent surfaces SSN- or account-bearing content without policy enforcement. Detected by tests
1.13-DLP-01through1.13-DLP-03and the incident reproduction test1.13-IR-01. - EDM near-match leakage. An Exact Data Match classifier is configured for exact-only equality but a downstream regex normalization (whitespace, hyphenation) allows a near-miss row to pass. Detected by
1.13-EDM-02. - Preview → GA classifier ID drift. A trainable classifier referenced by ID in a DLP policy is the preview build; Microsoft promotes it to GA with a new GUID and the policy silently stops matching. Detected by
1.13-NEG-03. - DLP-for-Copilot mistargeting. A policy is scoped to a user group rather than the agent identity / SharePoint site containing the grounding source, so the policy never evaluates the grounding query. Detected by
1.13-NEG-05. - Fabricated SLA reliance. A runbook says "wait 24 hours for SIT indexing" without a Microsoft-published basis, so testers prematurely declare a pass. Mitigated by §3 (Documented processing windows) which cites only Microsoft-published windows feature-by-feature.
- Hard-coded numeric confidence thresholds in operator UX. Operators are told "≥85 = High" without referencing the custom SIT XML
confidenceLevelattribute that defines the band; a SIT change silently breaks the assumption. Detected during1.13-CUSTOM-01..04review and §8 Anti-Pattern #6. - No negative corpus. Only positive matches are tested, so false-positive rate is unknown and Zone 3 block actions create denial-of-service to legitimate agent queries. Detected by every
*-NEG-*and the-negative-half of each pair. - EDM hash drift. The EDM Upload Agent runs against a stale schema or stale source extract, producing a hash set that no longer matches production data. Detected by
1.13-NEG-02. - Sovereign-cloud false attestation. A Commercial-tenant attestation is reused for a GCC High tenant where NER, trainable classifiers, or DSPM for AI are not yet at parity. Detected by
1.13-PRE-07and §5. - Trainable classifier without OCC 2011-12 / Fed SR 11-7 model-risk evidence. A custom trainable classifier is deployed without documented training-data lineage, validation set, or model-risk sign-off, breaching the FSI Governance Gate defined in the control spec. Detected by
1.13-TC-01..04.
§1 Verification cadence
Cadence is firm-defined under WSPs (FINRA Rule 3110) and supervisory procedures. Microsoft does not publish a verification cadence for SIT or DLP correctness. The table below is the minimum recommended cadence for FSI tenants; firms may shorten any interval based on risk.
| Cadence | Test scope | Owner (Responsible) | Owner (Accountable) | Regulatory driver |
|---|---|---|---|---|
| Daily | UAL sampling (1.13-AUDIT-01..04); DLP alert queue triage |
Purview Compliance Admin | Compliance Officer | FINRA 3110(b), SEC 17a-4(f), SOX ITGC |
| Weekly | DLP-for-Copilot match review (1.13-DLP-01..03); DSPM for AI surfacing (1.13-DSPM-01..02) |
Information Protection Admin | CISO | GLBA Safeguards 314.4(d); OCC Heightened Standards |
| Monthly | Full BUILTIN (1.13-BUILTIN-01..08) and CUSTOM (1.13-CUSTOM-01..04) regression with positive + negative corpus |
Information Protection Admin | Compliance Officer | FINRA 3110, SEC Reg S-P |
| Quarterly | EDM (1.13-EDM-01..03), Trainable Classifier (1.13-TC-01..04), NER (1.13-NER-01..04), Negative-path battery (1.13-NEG-01..05), Sovereign parity recheck (§5) |
Compliance Data Administrator + Information Protection Admin | CRO | OCC 2011-12 / Fed SR 11-7; GLBA Safeguards |
| On change | Any test affected by a tenant change (new SIT, EDM schema rotation, DLP rule edit, classifier promotion preview→GA, role-group change, sovereign-cloud feature GA) | Purview Compliance Admin | Compliance Officer | SOX ITGC change-control |
| On incident | 1.13-IR-01 reproduction with the actual unredacted incident artifact in a contained eDiscovery workspace |
Incident Response Lead + Compliance Data Administrator | CISO + Compliance Officer | SEC Reg S-P §248.30; state breach laws; NYDFS 500.17 |
RACI note. Accountable role per RACI may not match the role with admin permissions. The Compliance Officer is accountable but does not hold Purview Compliance Admin rights; that separation is required by the role-separation control (1.5) and audited at 1.13-PRE-04.
§2 Pre-flight (1.13-PRE-01..07)
Pre-flight tests must pass before any §4 test is executed. A failed pre-flight blocks the entire verification cycle and is itself a finding.
1.13-PRE-01 — License entitlement
Objective. Confirm that the tenant holds the licenses required for every detection primitive in scope.
Preconditions. Entra Global Reader or License Administrator role; access to admin.cloud.microsoft → Billing → Licenses.
Steps.
1. In Microsoft 365 admin center, navigate to Billing → Licenses.
2. Confirm presence of: Microsoft 365 E5 or E5 Compliance add-on (required for EDM, NER, trainable classifiers, DSPM for AI), Microsoft 365 Copilot (required for DLP-for-Copilot policy type), and Microsoft Purview Audit (Premium) (required for 1-year+ UAL retention referenced by 1.13-AUDIT-*).
3. Record license SKU GUIDs and seat counts in the evidence manifest.
Expected. All three SKUs present with sufficient seats to cover every test user and every agent identity referenced by §4.
Pass criteria. SKU presence verified; screenshot or Get-MgSubscribedSku JSON output captured.
Audit assertion. None — license check is not a UAL-emitting event. Evidence is the captured admin-center state.
Evidence collected. 1.13-PRE-01-licenses.json (output of Get-MgSubscribedSku | Select-Object SkuPartNumber, ConsumedUnits, PrepaidUnits), 1.13-PRE-01-screenshot.png.
1.13-PRE-02 — Unified Audit Log enabled
Objective. Confirm UAL ingestion is enabled and that the operations referenced by 1.13-AUDIT-* are emitted by the tenant.
Preconditions. Audit Reader or Audit Manager role.
Steps.
1. Open compliance.microsoft.com → Audit.
2. Confirm the banner does not state "Start recording user and admin activity".
3. Run a 7-day search filtered to operations: SitCreated, SitUpdated, SitDeleted, EdmSchemaCreated, EdmSchemaUpdated, EdmDataUploaded, DlpRuleMatch, CopilotInteraction. Verify each operation appears in the dropdown (operation name autocomplete).
4. Export results to CSV.
Expected. UAL is enabled; all eight operation names are recognized by the search UI.
Pass criteria. UAL banner absent; all eight operations present in autocomplete; CSV exported.
Audit assertion. N/A (this test verifies UAL itself).
Evidence collected. 1.13-PRE-02-ual-search.csv, 1.13-PRE-02-screenshot.png.
Verify on Microsoft Learn at execution time. Operation-name spelling for
SitCreated/SitUpdated/EdmSchemaCreated/EdmDataUploaded/DlpRuleMatch/CopilotInteractionis subject to change. Confirm againstlearn.microsoft.com/purview/audit-log-activitiesbefore signing the attestation in §7.
1.13-PRE-03 — PowerShell modules pinned
Objective. Confirm verifier workstation has the pinned module versions defined in the shared baseline.
Preconditions. Workstation with PowerShell 7.4+; access to PSGallery (or sovereign equivalent).
Steps. Follow _shared/powershell-baseline.md §2. Pinned modules: ExchangeOnlineManagement, Microsoft.Graph, Microsoft.Graph.Beta, PnP.PowerShell, Microsoft.PowerApps.Administration.PowerShell. Capture Get-Module -ListAvailable | Where-Object { $_.Name -in @(...) } | Select Name, Version output.
Expected. All five modules present at the version pinned by the shared baseline.
Pass criteria. Module table matches baseline; no module is at "latest" / unpinned.
Audit assertion. N/A.
Evidence collected. 1.13-PRE-03-modules.json.
1.13-PRE-04 — Role separation
Objective. Confirm SIT-management, DLP-management, and audit-review roles are held by separate principals (separation of duties per Control 1.5).
Preconditions. Entra Global Reader.
Steps. 1. Enumerate members of: Information Protection Admin, Purview Compliance Admin, Compliance Data Administrator, Audit Manager. 2. Confirm no single human principal holds more than one of {Information Protection Admin, Purview Compliance Admin, Audit Manager}. 3. Confirm no service principal holds Information Protection Admin without an approved exception ticket.
Expected. Each role group has ≥1 member; no overlap among the three sensitive groups.
Pass criteria. Membership matrix exported; overlap check passes.
Audit assertion. Role-group membership change events emit Add member to role in UAL; out of scope for this test but referenced by Control 1.5.
Evidence collected. 1.13-PRE-04-role-matrix.csv.
1.13-PRE-05 — EDM Upload Agent installed and IPPS connectivity
Objective. Confirm the EDM Upload Agent is installed on the designated secure workstation and can authenticate to Information Protection PowerShell (IPPS).
Preconditions. Workstation hardened per Control 1.7; Compliance Data Administrator role.
Steps.
1. On the EDM workstation, confirm EdmUploadAgent.exe is present at the documented install path.
2. Run Connect-IPPSSession (use sovereign endpoint per §5 for non-Commercial clouds).
3. Run Get-DlpEdmSchema and confirm the existing schema list returns without error.
Expected. Agent present; IPPS session established; schema list returned.
Pass criteria. Agent version recorded; Get-DlpEdmSchema returns ≥1 schema (or 0 if none yet defined — record either way).
Audit assertion. EdmSchemaCreated / EdmSchemaUpdated events emit when schemas are mutated; verified in 1.13-AUDIT-02.
Evidence collected. 1.13-PRE-05-edm-agent-version.txt, 1.13-PRE-05-schema-list.json.
1.13-PRE-06 — Test corpus staged with SHA-256 manifest
Objective. Confirm the synthetic positive + negative test corpus exists at tests/1.13/corpus/ and that every file's SHA-256 hash is recorded in 1.13-corpus-manifest.json.
Preconditions. Repository checkout; Get-FileHash available.
Steps.
1. List corpus directory: Get-ChildItem tests/1.13/corpus/ -Recurse -File.
2. Verify naming convention 1.13-{TYPE}-{positive|negative}-{NNN}.{ext} (e.g., 1.13-SSN-positive-001.txt, 1.13-CC-negative-014.docx).
3. Recompute SHA-256 for every file and compare to 1.13-corpus-manifest.json shipped with the repo.
4. Confirm the corpus contains no real customer NPI. Acceptable test values include the Luhn-valid card test PAN 4111-1111-1111-1111 and SSA-published test SSNs from the 987-65-4xxx range. The string 123-45-6789 must not be used as an SSA-invalid example for positive cases.
Expected. Every corpus file present; every SHA-256 matches manifest; no real NPI.
Pass criteria. Hash diff is empty; manual sample of 10 files confirms synthetic content.
Audit assertion. N/A.
Evidence collected. 1.13-PRE-06-corpus-hash-diff.txt.
1.13-PRE-07 — Three named test agents and sovereign parity check
Objective. Confirm the three named test agents exist and that the sovereign-cloud feature parity matrix (§5) has been refreshed in the last 30 days.
Preconditions. Power Platform Admin; Copilot Studio access; SharePoint admin for the controlled test site.
Steps.
1. Confirm three Copilot Studio agents exist: agent-fsi-test-Z1, agent-fsi-test-Z2, agent-fsi-test-Z3. Each must be grounded on the controlled SharePoint site https://{tenant}.sharepoint.com/sites/fsi-test-1.13.
2. Confirm each agent is published to a single test user (not org-wide).
3. Confirm the sovereign parity matrix (§5) has a "Last verified" timestamp within 30 days of the current run.
Expected. Three agents present, correctly scoped; sovereign matrix current.
Pass criteria. Agent inventory matches; sovereign matrix timestamp ≤30 days old.
Audit assertion. Agent-creation events emit CopilotAgentCreated (verify spelling on Learn at execution); referenced by Control 4.6.
Evidence collected. 1.13-PRE-07-agent-inventory.json, 1.13-PRE-07-sovereign-matrix-timestamp.txt.
§3 Documented processing windows
The windows below are the only windows cited by Microsoft Learn at the date of last UI verification (April 2026). No other "wait N hours" instruction in this playbook is permitted. If a feature has no published window, the playbook says "no committed SLA — verify by audit event, not by elapsed time."
| Feature | Microsoft-published window | Source anchor (verify at execution) | Test usage |
|---|---|---|---|
| DLP-for-Copilot policy enforcement after publish | Up to ~1 hour | learn.microsoft.com/purview/dlp-copilot-learn-about |
1.13-DLP-01..03 polling window |
| Trainable classifier seed-site indexing (initial) | At least 1 hour | learn.microsoft.com/purview/classifier-learn-about |
1.13-TC-01..04 |
| DSPM for AI data collection | ~24 hours | learn.microsoft.com/purview/dspm-for-ai |
1.13-DSPM-01..02 |
| Role-group membership propagation | ~30 minutes | learn.microsoft.com/purview/microsoft-365-compliance-center-permissions |
1.13-PRE-04 re-test after change |
| EDM data upload → match availability | No committed SLA — verify by EdmDataUploaded UAL event then test match |
learn.microsoft.com/purview/sit-create-edm-classifier |
1.13-EDM-01..03 |
| Custom SIT publish → match availability | No committed SLA — verify by SitCreated/SitUpdated UAL event |
learn.microsoft.com/purview/sit-get-started |
1.13-CUSTOM-01..04 |
| Built-in SIT match in Copilot grounding | No committed SLA — verify by DlpRuleMatch UAL event tied to CopilotInteraction |
learn.microsoft.com/purview/sit-defn-overview |
1.13-BUILTIN-01..08 |
Anti-pattern. Operator-mediated waits ("the analyst waited 24h then re-tested") are not evidence. Pass criteria for every §4 test require an audit-event assertion, not an elapsed-time assertion.
§4 Test catalog
Every test below uses the structure: Objective · Preconditions · Steps · Expected · Pass criteria · Audit assertion · Evidence collected. Test IDs are stable and referenced by the evidence manifest (§6) and the attestation block (§7).
Built-in SITs (1.13-BUILTIN-01..08)
1.13-BUILTIN-01 — US SSN positive
Objective. Confirm the built-in U.S. Social Security Number (SSN) SIT matches an SSA-format compliant test value when present in a SharePoint document grounded by agent-fsi-test-Z3.
Preconditions. PRE-01..07 passed; corpus file 1.13-SSN-positive-001.txt (containing SSA test value such as 987-65-4320) uploaded to the controlled test site; Zone 3 DLP-for-Copilot policy active with U.S. SSN SIT at confidence "High" and action "Block".
Steps.
1. Upload 1.13-SSN-positive-001.txt to /sites/fsi-test-1.13/Shared Documents/.
2. Wait for DlpRuleMatch event referencing the file (poll UAL every 5 minutes; do not assume a fixed window).
3. From the published test user, prompt agent-fsi-test-Z3: "Summarize any documents in the test library that mention the customer."
4. Capture the agent response and the corresponding CopilotInteraction UAL event.
Expected. Agent response is blocked or redacted; DlpRuleMatch UAL event correlates the SIT, the file, the policy, and the CopilotInteraction event ID.
Pass criteria. Agent does not surface the SSN string; DlpRuleMatch.SensitiveInformationTypeName == "U.S. Social Security Number (SSN)"; DlpRuleMatch.PolicyId matches the Zone 3 policy GUID.
Audit assertion. DlpRuleMatch and CopilotInteraction events both present, correlated by CorrelationId or shared SessionId.
Evidence collected. 1.13-BUILTIN-01-ual.json, 1.13-BUILTIN-01-agent-response.txt, 1.13-BUILTIN-01-file-hash.txt.
1.13-BUILTIN-02 — US SSN negative
Objective. Confirm the SSN SIT does not match a non-SSN nine-digit string (e.g., a phone-number-shaped value) — guards against false-positive denial-of-service.
Preconditions. Same as BUILTIN-01.
Steps. Repeat BUILTIN-01 substituting 1.13-SSN-negative-001.txt (e.g., (987) 654-3201 or random digit string failing SSA range rules).
Expected. No DlpRuleMatch event for SSN SIT against the negative file; agent surfaces the file content normally.
Pass criteria. Zero DlpRuleMatch events with SensitiveInformationTypeName == "U.S. Social Security Number (SSN)" referencing the negative file's ObjectId.
Audit assertion. CopilotInteraction event present; absence of DlpRuleMatch is itself the assertion (recorded as a negative-evidence row in the manifest).
Evidence collected. 1.13-BUILTIN-02-ual-negative.json.
1.13-BUILTIN-03 — US Bank Account positive
Objective. Confirm U.S. Bank Account Number SIT matches an ABA-routing + account-number combination at "High" confidence in Zone 2 (Educate action).
Preconditions. PRE-01..07 passed; corpus file 1.13-USBANK-positive-001.txt; Zone 2 policy active with action "Notify user" (educate).
Steps. Upload corpus file; prompt agent-fsi-test-Z2; capture educate notification surfaced to the user; capture UAL.
Expected. Agent surfaces an educate banner referencing the firm's policy URL; DlpRuleMatch event present with Action == "Notify".
Pass criteria. Educate banner displayed; DlpRuleMatch.Action is Notify or NotifyUser (verify exact spelling on Learn).
Audit assertion. DlpRuleMatch with notify action; CopilotInteraction event correlated.
Evidence collected. 1.13-BUILTIN-03-ual.json, 1.13-BUILTIN-03-banner-screenshot.png.
1.13-BUILTIN-04 — US Bank Account negative
Objective. Confirm the bank-account SIT does not match a random 9-digit + 10-digit string lacking ABA checksum.
Preconditions. Same as BUILTIN-03.
Steps. Substitute 1.13-USBANK-negative-001.txt.
Expected. No DlpRuleMatch for bank-account SIT.
Pass criteria. Zero matching DlpRuleMatch events.
Audit assertion. Absence of DlpRuleMatch; CopilotInteraction present.
Evidence collected. 1.13-BUILTIN-04-ual-negative.json.
1.13-BUILTIN-05 — Credit Card positive (Luhn-valid)
Objective. Confirm Credit Card Number SIT matches the Luhn-valid test PAN 4111-1111-1111-1111 in Zone 1 (alert-only).
Preconditions. PRE-01..07 passed; Zone 1 policy with action "Generate alert".
Steps. Upload 1.13-CC-positive-001.txt; prompt agent-fsi-test-Z1; capture alert in Defender / Purview alert queue.
Expected. Agent surfaces content (alert-only zone); alert appears within firm-defined supervisory window.
Pass criteria. Alert created; DlpRuleMatch.SensitiveInformationTypeName == "Credit Card Number".
Audit assertion. DlpRuleMatch with alert action; CopilotInteraction correlated.
Evidence collected. 1.13-BUILTIN-05-ual.json, 1.13-BUILTIN-05-alert-id.txt.
1.13-BUILTIN-06 — Credit Card negative (Luhn-invalid)
Objective. Confirm CC SIT does not match a 16-digit string failing Luhn checksum.
Preconditions. Same as BUILTIN-05.
Steps. Substitute 1.13-CC-negative-001.txt containing 4111-1111-1111-1112 (last digit changed to break Luhn).
Expected. No DlpRuleMatch for CC SIT.
Pass criteria. Zero matching events.
Audit assertion. Absence; CopilotInteraction present.
Evidence collected. 1.13-BUILTIN-06-ual-negative.json.
1.13-BUILTIN-07 — ITIN positive
Objective. Confirm U.S. Individual Taxpayer Identification Number (ITIN) SIT matches an IRS-format test value (9NN-7N-NNNN where NN is in the 70–88 range per IRS publication).
Preconditions. Zone 3 policy with ITIN SIT at High confidence.
Steps. Upload 1.13-ITIN-positive-001.txt; prompt agent-fsi-test-Z3; capture block.
Expected. Agent blocked; DlpRuleMatch for ITIN SIT.
Pass criteria. Block enforced; UAL event present.
Audit assertion. DlpRuleMatch with SensitiveInformationTypeName == "U.S. Individual Taxpayer Identification Number (ITIN)".
Evidence collected. 1.13-BUILTIN-07-ual.json.
1.13-BUILTIN-08 — EIN positive
Objective. Confirm U.S. Employer Identification Number (EIN) SIT matches a 2-7 IRS-format value.
Preconditions. Zone 2 educate policy with EIN SIT.
Steps. Upload 1.13-EIN-positive-001.txt; prompt agent-fsi-test-Z2.
Expected. Educate banner; DlpRuleMatch for EIN.
Pass criteria. Banner; UAL event.
Audit assertion. DlpRuleMatch for EIN SIT.
Evidence collected. 1.13-BUILTIN-08-ual.json.
Custom SITs (1.13-CUSTOM-01..04)
1.13-CUSTOM-01 — FINRA CRD positive
Objective. Confirm a custom SIT matching the FINRA Central Registration Depository (CRD) number format (6–7 digits with firm-specific prefix or contextual keywords like CRD#, CRD No) detects positive samples in Zone 3.
Preconditions. Custom SIT defined per playbook portal-walkthrough.md §4 with confidenceLevel="85" (High band per the custom SIT XML schema — note: the band is firm-defined in XML, not a Microsoft universal threshold). Zone 3 policy references the custom SIT.
Steps. Upload 1.13-CRD-positive-001.txt containing five distinct CRD-format values with surrounding context (CRD# 1234567); prompt agent-fsi-test-Z3; capture block + UAL.
Expected. Block enforced; DlpRuleMatch references the custom SIT GUID.
Pass criteria. UAL event references the GUID (not display name); GUID matches the value recorded in 1.13-CUSTOM-01-sit-id.txt.
Audit assertion. DlpRuleMatch with SensitiveInformationTypeId matching custom SIT GUID; SitUpdated event present in change-history audit if SIT was last modified within the test window.
Evidence collected. 1.13-CUSTOM-01-ual.json, 1.13-CUSTOM-01-sit-xml.xml (export of current SIT definition), 1.13-CUSTOM-01-sit-id.txt.
1.13-CUSTOM-02 — FINRA CRD negative
Objective. Confirm CRD SIT does not match a generic 7-digit number lacking the contextual keyword (false-positive guard).
Preconditions. Same as CUSTOM-01.
Steps. Substitute 1.13-CRD-negative-001.txt containing seven-digit numbers without CRD keyword.
Expected. No match.
Pass criteria. Zero DlpRuleMatch events for CRD SIT.
Audit assertion. Absence; CopilotInteraction present.
Evidence collected. 1.13-CUSTOM-02-ual-negative.json.
1.13-CUSTOM-03 — Internal account number positive
Objective. Confirm a firm-defined internal account number SIT (e.g., format ACCT-NNNNNNNN) matches positive samples in Zone 2.
Preconditions. Custom SIT defined; Zone 2 educate policy active.
Steps. Upload 1.13-ACCT-positive-001.txt; prompt agent-fsi-test-Z2.
Expected. Educate banner; DlpRuleMatch.
Pass criteria. UAL event references custom SIT GUID; banner displayed.
Audit assertion. DlpRuleMatch with custom SIT GUID.
Evidence collected. 1.13-CUSTOM-03-ual.json, 1.13-CUSTOM-03-sit-xml.xml.
1.13-CUSTOM-04 — Internal account number negative
Objective. Confirm internal account SIT does not match ACCT-NNNN (too short) or INVOICE-NNNNNNNN (wrong prefix).
Preconditions. Same as CUSTOM-03.
Steps. Substitute 1.13-ACCT-negative-001.txt.
Expected. No match.
Pass criteria. Zero matching events.
Audit assertion. Absence.
Evidence collected. 1.13-CUSTOM-04-ual-negative.json.
Exact Data Match (1.13-EDM-01..03)
1.13-EDM-01 — EDM exact match
Objective. Confirm an EDM classifier built from a hashed customer-account extract matches a row that exists exactly in the source extract.
Preconditions. EDM schema and data uploaded per powershell-setup.md §5; daily refresh job verified by EdmDataUploaded event in the last 24 hours; Zone 3 policy references the EDM classifier.
Steps.
1. Select a known row from the source extract (e.g., row 142 — account ACCT-12345678, customer Smith, J., branch B-014).
2. Place the row's primary value into 1.13-EDM-positive-exact-001.txt.
3. Upload to test site; prompt agent-fsi-test-Z3; capture block + UAL.
Expected. Block enforced; DlpRuleMatch references the EDM classifier ID.
Pass criteria. UAL event references EDM classifier; EdmDataUploaded event for current dataset present within the published feature window (no committed SLA — verified by event presence per §3).
Audit assertion. DlpRuleMatch with EDM classifier ID; EdmDataUploaded event correlated to the dataset version.
Evidence collected. 1.13-EDM-01-ual.json, 1.13-EDM-01-edm-dataset-version.txt, 1.13-EDM-01-source-row-hash.txt.
1.13-EDM-02 — EDM near-miss negative
Objective. Confirm EDM does not match a value that differs by a single character or whitespace from a source row (verifying exact-equality semantics and detecting any unintended fuzzy normalization in the regex layer).
Preconditions. Same as EDM-01.
Steps. Construct 1.13-EDM-negative-near-001.txt containing the row 142 account number with one digit altered (ACCT-12345679) and a separate file with the exact account number but with hyphenation removed (ACCT12345678).
Expected. No DlpRuleMatch for EDM classifier on either file (or, if normalization is intentional and documented, the normalized form matches and the digit-altered form does not — record which behavior is observed).
Pass criteria. Behavior matches the documented EDM normalization rules in the firm's EDM design document. Any unexpected match is a finding.
Audit assertion. Absence (or expected presence per documented normalization).
Evidence collected. 1.13-EDM-02-ual.json, 1.13-EDM-02-design-doc-ref.txt.
1.13-EDM-03 — EDM schema rotation
Objective. Confirm an EDM schema rotation (column add/remove or primary-key change) emits EdmSchemaUpdated and that downstream policies continue to match correctly.
Preconditions. EDM-01 passed; change-control ticket approved for schema rotation.
Steps.
1. Modify the schema XML (e.g., add a non-primary column).
2. Re-upload schema via EDM Upload Agent.
3. Confirm EdmSchemaUpdated event in UAL.
4. Re-run EDM-01 test against the rotated schema.
Expected. EdmSchemaUpdated present; EDM-01 still passes against rotated schema.
Pass criteria. Both UAL events present; rotation does not regress EDM-01.
Audit assertion. EdmSchemaUpdated event with new schema version; subsequent DlpRuleMatch events reference the updated classifier ID (if classifier ID changes on rotation — verify behavior on Learn).
Evidence collected. 1.13-EDM-03-schema-updated-ual.json, 1.13-EDM-03-rerun-of-edm-01.json.
Named Entity Recognition (1.13-NER-01..04)
1.13-NER-01 — PERSON entity positive
Objective. Confirm the built-in NER Person Name (or current Microsoft naming) classifier surfaces person-name entities in unstructured text.
Preconditions. E5 NER feature enabled in the tenant (verify on Learn — NER availability differs across sovereign clouds, see §5); Zone 2 educate policy referencing the NER classifier.
Steps. Upload 1.13-NER-PERSON-positive-001.txt containing distinct person-name examples in narrative context; prompt agent-fsi-test-Z2; capture banner + UAL.
Expected. Educate banner; DlpRuleMatch referencing NER classifier ID.
Pass criteria. UAL event references NER classifier; banner shown.
Audit assertion. DlpRuleMatch with NER classifier identifier (verify exact field name on Learn).
Evidence collected. 1.13-NER-01-ual.json.
1.13-NER-02 — ORG entity positive
Objective. Confirm Organization NER classifier matches organization names.
Preconditions. Same as NER-01.
Steps. Upload 1.13-NER-ORG-positive-001.txt; prompt agent-fsi-test-Z2.
Expected. Educate banner; UAL match.
Pass criteria. UAL references ORG NER classifier ID.
Audit assertion. DlpRuleMatch for ORG classifier.
Evidence collected. 1.13-NER-02-ual.json.
1.13-NER-03 — ADDRESS entity positive
Objective. Confirm Physical Address NER matches US street addresses.
Preconditions. Same as NER-01.
Steps. Upload 1.13-NER-ADDRESS-positive-001.txt; prompt agent-fsi-test-Z2.
Expected. Banner; UAL match.
Pass criteria. UAL event present.
Audit assertion. DlpRuleMatch for ADDRESS classifier.
Evidence collected. 1.13-NER-03-ual.json.
1.13-NER-04 — NER false-positive control
Objective. Confirm NER does not surface educate banner for narrative text containing common nouns that NER may mis-classify (e.g., "Bill" used as verb, "Apple" used as fruit). Validates that the NER confidence band configured in policy is appropriate.
Preconditions. Same as NER-01.
Steps. Upload 1.13-NER-negative-001.txt; prompt agent-fsi-test-Z2.
Expected. Either no match, or match below the policy's confidence band (no banner surfaced).
Pass criteria. Banner not displayed; if DlpRuleMatch event is present, its Confidence field is below the policy threshold.
Audit assertion. Absence of banner is the test outcome; UAL event presence is informational.
Evidence collected. 1.13-NER-04-ual.json, 1.13-NER-04-banner-absent-screenshot.png.
Trainable Classifiers (1.13-TC-01..04)
FSI Governance Gate. Trainable classifiers are model artifacts subject to OCC Bulletin 2011-12 and Federal Reserve SR 11-7 (Model Risk Management). Each classifier deployed for Zone 2/3 enforcement requires: documented training-data lineage, validation set with measured precision/recall, model-risk committee sign-off, and re-validation cadence. Tests below assume that gate has been passed; absence of evidence is itself a finding.
1.13-TC-01 — Customer Complaints classifier positive
Objective. Confirm the built-in or custom Customer Complaints trainable classifier surfaces an educate banner when a Zone 2 agent grounds on complaint-pattern text.
Preconditions. Classifier published (preview or GA — record state); model-risk evidence on file; Zone 2 policy references classifier by GA GUID if GA, or with documented preview-acceptance approval if preview.
Steps. Upload 1.13-TC-COMPLAINT-positive-001.txt containing complaint-pattern narrative; prompt agent-fsi-test-Z2.
Expected. Educate banner; DlpRuleMatch for classifier.
Pass criteria. UAL event references the current classifier GUID; if classifier was promoted preview→GA in last 90 days, NEG-03 must also have passed.
Audit assertion. DlpRuleMatch for TC classifier; classifier GUID matches the value in the model-risk inventory.
Evidence collected. 1.13-TC-01-ual.json, 1.13-TC-01-classifier-guid.txt, 1.13-TC-01-model-risk-evidence-ref.txt.
1.13-TC-02 — Customer Complaints classifier negative
Objective. Confirm classifier does not match generic customer-service narrative without complaint indicators.
Preconditions. Same as TC-01.
Steps. Substitute 1.13-TC-COMPLAINT-negative-001.txt (e.g., positive testimonial text).
Expected. No banner; either no match or match below confidence band.
Pass criteria. Banner absent.
Audit assertion. Absence.
Evidence collected. 1.13-TC-02-ual.json.
1.13-TC-03 — Mergers & Acquisitions classifier
Objective. Confirm Mergers & Acquisitions (or firm-defined deal-confidential) classifier surfaces in Zone 3 with block action.
Preconditions. Classifier published with model-risk evidence; Zone 3 policy active.
Steps. Upload 1.13-TC-MA-positive-001.txt; prompt agent-fsi-test-Z3.
Expected. Block enforced; DlpRuleMatch.
Pass criteria. UAL event references classifier GUID.
Audit assertion. DlpRuleMatch for MA classifier.
Evidence collected. 1.13-TC-03-ual.json.
1.13-TC-04 — Source code classifier
Objective. Confirm Source Code trainable classifier matches code snippets in narrative documents (Zone 2 educate).
Preconditions. Classifier published; Zone 2 policy active.
Steps. Upload 1.13-TC-CODE-positive-001.txt containing a representative code block (Python, C#, etc.); prompt agent-fsi-test-Z2.
Expected. Educate banner; UAL match.
Pass criteria. UAL event present.
Audit assertion. DlpRuleMatch for source-code classifier.
Evidence collected. 1.13-TC-04-ual.json.
DLP-for-Copilot policy enforcement (1.13-DLP-01..03)
1.13-DLP-01 — Zone 1 alert
Objective. Confirm a Zone 1 (Personal) DLP-for-Copilot policy generates an alert without blocking or notifying the user.
Preconditions. Zone 1 policy scoped to agent-fsi-test-Z1 agent identity (not user identity — see NEG-05 for the mistargeting failure mode).
Steps. Upload 1.13-SSN-positive-001.txt; prompt agent-fsi-test-Z1; verify agent surfaces content; verify alert generated in Defender / Purview alert queue.
Expected. Content surfaced; alert created.
Pass criteria. Alert ID captured; DlpRuleMatch with alert action.
Audit assertion. DlpRuleMatch with Action == "Alert" (verify spelling on Learn).
Evidence collected. 1.13-DLP-01-ual.json, 1.13-DLP-01-alert-id.txt.
1.13-DLP-02 — Zone 2 educate
Objective. Confirm Zone 2 policy surfaces educate banner with policy URL link.
Preconditions. Zone 2 policy with notify action and policy tip URL configured.
Steps. Upload 1.13-USBANK-positive-001.txt; prompt agent-fsi-test-Z2; verify banner with link.
Expected. Banner displayed; clicking link goes to firm's policy page.
Pass criteria. Banner content matches configured policy tip; UAL match present.
Audit assertion. DlpRuleMatch with notify action.
Evidence collected. 1.13-DLP-02-banner-screenshot.png, 1.13-DLP-02-ual.json.
1.13-DLP-03 — Zone 3 block
Objective. Confirm Zone 3 policy blocks agent response on High-confidence match.
Preconditions. Zone 3 policy with block action.
Steps. Upload 1.13-CRD-positive-001.txt; prompt agent-fsi-test-Z3; verify response is blocked or fully redacted.
Expected. No NPI surfaced in response.
Pass criteria. Agent response contains no SIT-matched substring; UAL event with block action.
Audit assertion. DlpRuleMatch with block action; CopilotInteraction correlated.
Evidence collected. 1.13-DLP-03-agent-response.txt, 1.13-DLP-03-ual.json.
DSPM for AI (1.13-DSPM-01..02)
1.13-DSPM-01 — DSPM surfacing
Objective. Confirm DSPM for AI surfaces the Zone 3 block events from DLP-03 in the DSPM dashboard within the documented ~24-hour collection window (§3).
Preconditions. DSPM for AI enabled; DLP-03 executed ≥24h prior (or executed and then DSPM checked at next available collection cycle — whichever comes later).
Steps. Open Purview → DSPM for AI → Reports; confirm the Zone 3 block events appear with correct agent identity and SIT name.
Expected. Events visible with correct attribution.
Pass criteria. Event count in DSPM matches UAL count for the same window.
Audit assertion. N/A (DSPM is a derived view; underlying assertion is the UAL event already captured in DLP-03).
Evidence collected. 1.13-DSPM-01-screenshot.png, 1.13-DSPM-01-export.csv.
1.13-DSPM-02 — DSPM trend
Objective. Confirm DSPM trend view shows expected weekly cadence of test events (no gaps, no duplicates).
Preconditions. ≥4 weeks of test history.
Steps. Open DSPM trend view; export 4-week trend; reconcile against expected test execution log.
Expected. No unexplained gaps; no duplicates.
Pass criteria. Reconciliation log signed by Compliance Data Administrator.
Audit assertion. N/A.
Evidence collected. 1.13-DSPM-02-trend.csv, 1.13-DSPM-02-reconciliation.md.
Audit operations (1.13-AUDIT-01..04)
1.13-AUDIT-01 — SitCreated emission
Objective. Confirm SitCreated UAL event emits when a new custom SIT is created.
Preconditions. Audit Reader; Information Protection Admin (separate principal — see PRE-04).
Steps.
1. Information Protection Admin creates a temporary throwaway custom SIT named 1.13-audit-temp-{timestamp}.
2. Audit Reader queries UAL for SitCreated filtered to the SIT name.
3. Information Protection Admin deletes the throwaway SIT (verifies SitDeleted).
Expected. Both SitCreated and SitDeleted events present.
Pass criteria. Events visible in UAL within firm-defined supervisory window; user principal name on event matches the Information Protection Admin who performed the action.
Audit assertion. SitCreated and SitDeleted events with correct UserId.
Evidence collected. 1.13-AUDIT-01-ual.json.
1.13-AUDIT-02 — EdmSchemaCreated emission
Objective. Confirm EdmSchemaCreated emits when a new EDM schema is uploaded.
Preconditions. Compliance Data Administrator; Audit Reader.
Steps. Compliance Data Administrator uploads a throwaway EDM schema (no real data) named 1.13-audit-edm-{timestamp}; Audit Reader confirms event.
Expected. EdmSchemaCreated event present.
Pass criteria. Event present with correct UserId.
Audit assertion. EdmSchemaCreated.
Evidence collected. 1.13-AUDIT-02-ual.json.
1.13-AUDIT-03 — SitUpdated emission
Objective. Confirm SitUpdated emits when a custom SIT's confidence threshold or pattern is modified.
Preconditions. Same as AUDIT-01.
Steps. Information Protection Admin modifies the confidence band on a non-production custom SIT; Audit Reader confirms event.
Expected. SitUpdated event present.
Pass criteria. Event present with correct UserId and ObjectId referencing the SIT GUID.
Audit assertion. SitUpdated.
Evidence collected. 1.13-AUDIT-03-ual.json.
1.13-AUDIT-04 — DlpRuleMatch emission with CopilotInteraction correlation
Objective. Confirm DlpRuleMatch and CopilotInteraction events can be correlated for the same agent prompt (foundational for every other §4 test's audit assertion).
Preconditions. Any §4 BUILTIN/CUSTOM/EDM/TC test executed in the last hour.
Steps. Pull the most recent CopilotInteraction event; extract correlation field (e.g., CorrelationId, SessionId, InteractionId — verify exact field on Learn); pull DlpRuleMatch events filtered by the same correlation field.
Expected. ≥1 DlpRuleMatch event correlated to the CopilotInteraction.
Pass criteria. Correlation field matches in both events; pivot table of correlation field → event count is non-zero.
Audit assertion. Self-asserting (this test verifies the correlation mechanism itself).
Evidence collected. 1.13-AUDIT-04-correlation-pivot.csv.
Negative-path battery (1.13-NEG-01..05)
1.13-NEG-01 — Schema drift
Objective. Detect a custom SIT whose XML in production no longer matches the version-controlled definition in the SIT-as-code repository.
Preconditions. SIT-as-code repository (e.g., Azure DevOps repo with exported SIT XML); read access to production SIT definitions via IPPS.
Steps.
1. Export current production SIT XML for every custom SIT: Get-DlpSensitiveInformationType | Export-Clixml.
2. Diff against the SIT-as-code repo HEAD.
Expected. Diff is empty.
Pass criteria. Empty diff (or every difference is associated with an approved change-control ticket).
Audit assertion. SitUpdated events in the diff window must each correspond to an approved ticket.
Evidence collected. 1.13-NEG-01-sit-diff.txt, 1.13-NEG-01-ticket-list.csv.
1.13-NEG-02 — EDM hash mismatch
Objective. Detect EDM dataset whose hash digest no longer matches the hash recorded at last upload (indicates either a successful unauthorized re-upload or an Upload Agent failure).
Preconditions. EDM dataset hash recorded at last upload (recorded in 1.13-EDM-dataset-hash.txt per powershell-setup.md §5).
Steps. Recompute hash of current source extract; compare to recorded hash.
Expected. Hash matches expected scheduled refresh hash; if changed, EdmDataUploaded event in UAL within last 24h corresponds to the new hash.
Pass criteria. Hash chain valid; every change correlated to an EdmDataUploaded event with a known UserId.
Audit assertion. EdmDataUploaded events in window correspond to known principals.
Evidence collected. 1.13-NEG-02-hash-chain.txt.
1.13-NEG-03 — Preview → GA classifier ID delta
Objective. Detect trainable-classifier or NER references in DLP policies that point to a preview GUID after Microsoft has promoted the classifier to GA (the GUID changes on promotion, silently breaking the policy match).
Preconditions. Inventory of all DLP policy references to trainable classifiers and NER classifiers (exported from Get-DlpCompliancePolicy / Get-DlpComplianceRule).
Steps.
1. Enumerate all classifier IDs referenced by policies.
2. For each, query the current classifier definition and confirm IsPreview / LifecycleState (verify exact field on Learn) is current.
3. Cross-check Microsoft Learn / Message Center for any classifier promoted preview→GA in the last 90 days; confirm policies were re-pointed to GA GUID.
Expected. Zero policies reference a deprecated preview GUID.
Pass criteria. Inventory clean; any deprecated reference is a finding.
Audit assertion. DlpPolicyUpdated (verify spelling) events in window for any re-pointing.
Evidence collected. 1.13-NEG-03-classifier-inventory.csv.
1.13-NEG-04 — Regex regression
Objective. Detect a custom SIT whose regex no longer matches a previously-known positive sample (indicates an unintended pattern edit or library upgrade behavior change).
Preconditions. Per-custom-SIT regression corpus stored at tests/1.13/regression/{sit-name}/.
Steps. For each custom SIT, run BUILTIN-style positive test against the regression sample.
Expected. All historical positives still match.
Pass criteria. Regression battery 100% pass.
Audit assertion. DlpRuleMatch per regression sample.
Evidence collected. 1.13-NEG-04-regression-results.csv.
1.13-NEG-05 — DLP-for-Copilot user-scope mistargeting
Objective. Detect DLP-for-Copilot policies scoped to a user group rather than the agent identity or SharePoint site hosting grounding sources (a common misconfiguration that produces silent non-enforcement).
Preconditions. Inventory of all DLP-for-Copilot policy scopes.
Steps.
1. Enumerate every DLP-for-Copilot policy: Get-DlpCompliancePolicy | Where-Object { $_.Workload -like "*Copilot*" } (verify property name on Learn).
2. For each, inspect the scope: it must reference an agent identity, agent group, or SharePoint site URL — not a user group.
3. Any policy scoped to a user group is a finding (unless explicitly approved as a user-targeted educate policy with documented justification).
Expected. Zero unjustified user-scoped policies.
Pass criteria. Inventory clean.
Audit assertion. N/A (configuration check).
Evidence collected. 1.13-NEG-05-policy-scope-inventory.csv.
Incident reproduction (1.13-IR-01)
1.13-IR-01 — SIT misses real SSN in Copilot grounding (full reproduction)
Objective. Reproduce a real or hypothetical incident where a SIT failed to match an SSN-bearing document grounded by an agent. Used to validate root-cause analysis and to drive corrective-action SIT updates.
Preconditions. Contained eDiscovery workspace per Control 1.10; incident artifact present (real document with NPI, handled per firm's incident-handling SOP); Compliance Officer authorization on file.
Steps. 1. In the contained workspace, replay the original prompt against a copy of the agent configuration at the time of incident. 2. Capture the agent response and UAL events. 3. Identify which SIT, classifier, or policy should have matched and did not. 4. Document root cause: missing SIT? wrong confidence band? wrong policy scope (NEG-05)? preview classifier GUID drift (NEG-03)? EDM hash mismatch (NEG-02)? 5. Propose corrective action and create a change-control ticket.
Expected. Root cause identified and documented; corrective action proposed.
Pass criteria. Root-cause document signed by Compliance Officer; corrective-action ticket linked.
Audit assertion. CopilotInteraction from incident replay present in workspace audit log.
Evidence collected. 1.13-IR-01-rca.md, 1.13-IR-01-corrective-action-ticket.txt, 1.13-IR-01-replay-ual.json.
§5 Sovereign cloud variant matrix
Update cadence. This matrix must be re-verified within 30 days of every test cycle (asserted by
1.13-PRE-07). Sovereign feature parity is fluid; cells marked "Verify per release" indicate features that historically lag commercial GA. Last verified: April 2026 (refresh on every test cycle).
| Test class | Commercial | GCC | GCC High | DoD | Notes |
|---|---|---|---|---|---|
| BUILTIN-01..08 (built-in SITs) | GA | GA | Verify per release | Verify per release | Built-in SIT availability is generally at parity; new built-in SITs lag in GCC High / DoD |
| CUSTOM-01..04 (custom SITs) | GA | GA | GA | GA | Customer-defined SITs portable across clouds |
| EDM-01..03 | GA | GA | Verify per release | Verify per release | Confirm EDM Upload Agent build supports the sovereign endpoint |
| NER-01..04 | GA | Verify per release | Verify per release | Not available (verify) | NER lags commercial; do not assume parity |
| TC-01..04 (trainable classifiers) | GA | Verify per release | Verify per release | Verify per release | Pre-trained classifier inventory differs by cloud |
| DLP-01..03 (DLP-for-Copilot) | GA | Verify per release | Verify per release | Verify per release | Copilot itself has differential availability |
| DSPM-01..02 | GA | Verify per release | Verify per release | Not available (verify) | DSPM for AI typically lags Copilot GA in sovereign clouds |
| AUDIT-01..04 | GA | GA | GA | GA | UAL operations available in all clouds; specific operation names may differ — verify on Learn |
| NEG-01..05 | N/A | N/A | N/A | N/A | Negative-path tests are tenant-internal and apply uniformly |
| IR-01 | GA | GA | GA | GA | Incident reproduction uses contained workspace per Control 1.10 |
Sovereign endpoints. PowerShell connections must use the sovereign-specific endpoint per _shared/powershell-baseline.md §3 (e.g., Connect-IPPSSession -ConnectionUri https://ps.compliance.protection.office365.us/powershell-liveid/ for GCC High).
§6 Evidence pack
6.1 Evidence manifest schema
Every test cycle produces a single 1.13-evidence-manifest.json conforming to the schema below. The manifest is the canonical index into the evidence artifacts and is the file submitted to the supervisory examiner.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "FSI Control 1.13 Evidence Manifest",
"type": "object",
"required": [
"controlId",
"controlVersion",
"tenantId",
"sovereignCloud",
"cycleId",
"cycleStart",
"cycleEnd",
"executor",
"approver",
"tests",
"manifestSha256"
],
"properties": {
"controlId": { "type": "string", "const": "1.13" },
"controlVersion": { "type": "string", "pattern": "^v\\d+\\.\\d+(\\.\\d+)?$" },
"tenantId": { "type": "string", "format": "uuid" },
"sovereignCloud": {
"type": "string",
"enum": ["Commercial", "GCC", "GCCHigh", "DoD"]
},
"cycleId": { "type": "string" },
"cycleStart": { "type": "string", "format": "date-time" },
"cycleEnd": { "type": "string", "format": "date-time" },
"executor": {
"type": "object",
"required": ["upn", "role"],
"properties": {
"upn": { "type": "string", "format": "email" },
"role": {
"type": "string",
"enum": [
"Information Protection Admin",
"Purview Compliance Admin",
"Compliance Data Administrator"
]
}
}
},
"approver": {
"type": "object",
"required": ["upn", "role"],
"properties": {
"upn": { "type": "string", "format": "email" },
"role": {
"type": "string",
"enum": ["Compliance Officer", "CISO", "CRO"]
}
}
},
"tests": {
"type": "array",
"minItems": 38,
"items": {
"type": "object",
"required": [
"testId",
"outcome",
"executedAt",
"evidenceArtifacts",
"auditAssertion"
],
"properties": {
"testId": {
"type": "string",
"pattern": "^1\\.13-(PRE|BUILTIN|CUSTOM|EDM|NER|TC|DLP|DSPM|AUDIT|NEG|IR)-\\d{2}$"
},
"outcome": {
"type": "string",
"enum": ["pass", "fail", "blocked", "n/a"]
},
"executedAt": { "type": "string", "format": "date-time" },
"evidenceArtifacts": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": ["path", "sha256", "sizeBytes"],
"properties": {
"path": { "type": "string" },
"sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$"
},
"sizeBytes": { "type": "integer", "minimum": 0 }
}
}
},
"auditAssertion": {
"type": "object",
"required": ["operation", "verified"],
"properties": {
"operation": { "type": "string" },
"verified": { "type": "boolean" },
"correlationId": { "type": "string" }
}
},
"notes": { "type": "string" }
}
}
},
"manifestSha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA-256 of the manifest file with this field set to all zeros, computed at finalization."
}
}
}
6.2 Manifest validator (Invoke-EvidenceManifestValidation.ps1)
# Invoke-EvidenceManifestValidation.ps1
# Validates a 1.13 evidence manifest against schema, recomputes artifact hashes,
# and verifies the manifest's own SHA-256 self-hash.
[CmdletBinding()]
param(
[Parameter(Mandatory)] [string] $ManifestPath,
[Parameter(Mandatory)] [string] $SchemaPath,
[Parameter(Mandatory)] [string] $EvidenceRoot
)
$ErrorActionPreference = 'Stop'
# 1. Load
$manifest = Get-Content $ManifestPath -Raw | ConvertFrom-Json
$schema = Get-Content $SchemaPath -Raw
# 2. Schema validation (requires Test-Json with -SchemaFile, PS 7.4+)
if (-not (Test-Json -Json (Get-Content $ManifestPath -Raw) -SchemaFile $SchemaPath)) {
throw "Schema validation failed for $ManifestPath"
}
# 3. Verify every artifact hash
$failures = @()
foreach ($test in $manifest.tests) {
foreach ($artifact in $test.evidenceArtifacts) {
$full = Join-Path $EvidenceRoot $artifact.path
if (-not (Test-Path $full)) {
$failures += "MISSING: $($test.testId) -> $($artifact.path)"
continue
}
$actual = (Get-FileHash $full -Algorithm SHA256).Hash.ToLower()
if ($actual -ne $artifact.sha256.ToLower()) {
$failures += "HASH MISMATCH: $($test.testId) -> $($artifact.path) (expected $($artifact.sha256), got $actual)"
}
}
}
# 4. Verify the manifest self-hash
$tempCopy = [System.IO.Path]::GetTempFileName()
try {
$copy = $manifest | ConvertTo-Json -Depth 50 | ConvertFrom-Json
$recordedHash = $copy.manifestSha256
$copy.manifestSha256 = '0' * 64
($copy | ConvertTo-Json -Depth 50) | Set-Content -Path $tempCopy -NoNewline
$recomputed = (Get-FileHash $tempCopy -Algorithm SHA256).Hash.ToLower()
if ($recomputed -ne $recordedHash.ToLower()) {
$failures += "MANIFEST SELF-HASH MISMATCH: expected $recordedHash, got $recomputed"
}
} finally {
Remove-Item $tempCopy -ErrorAction SilentlyContinue
}
# 5. Coverage assertion
$expectedIds = @(
('PRE', 1..7),
('BUILTIN', 1..8),
('CUSTOM', 1..4),
('EDM', 1..3),
('NER', 1..4),
('TC', 1..4),
('DLP', 1..3),
('DSPM', 1..2),
('AUDIT', 1..4),
('NEG', 1..5),
('IR', 1..1)
) | ForEach-Object {
$prefix = $_[0]
$_[1] | ForEach-Object { '1.13-{0}-{1:00}' -f $prefix, $_ }
}
$presentIds = $manifest.tests.testId
$missing = $expectedIds | Where-Object { $_ -notin $presentIds }
if ($missing.Count -gt 0) {
$failures += "MISSING TEST IDS: $($missing -join ', ')"
}
if ($failures.Count -gt 0) {
Write-Error ($failures -join "`n")
exit 1
}
Write-Host "OK: manifest valid; $($manifest.tests.Count) tests; all hashes verified."
exit 0
6.3 Manifest builder
Builder pattern (sketch — full implementation in powershell-setup.md §8):
# Build-EvidenceManifest.ps1 (sketch)
$manifest = [ordered]@{
controlId = '1.13'
controlVersion = 'v1.4'
tenantId = (Get-MgContext).TenantId
sovereignCloud = $env:FSI_SOVEREIGN_CLOUD # 'Commercial' | 'GCC' | 'GCCHigh' | 'DoD'
cycleId = "1.13-cycle-$(Get-Date -Format 'yyyyMMdd-HHmm')"
cycleStart = (Get-Date).ToUniversalTime().ToString('o')
cycleEnd = $null
executor = @{ upn = $env:FSI_EXECUTOR_UPN; role = $env:FSI_EXECUTOR_ROLE }
approver = @{ upn = $env:FSI_APPROVER_UPN; role = $env:FSI_APPROVER_ROLE }
tests = @()
manifestSha256 = '0' * 64
}
# ... append per-test entries with hashes ...
# At end: $manifest.cycleEnd = ...; compute self-hash; write file.
6.4 Evidence artifacts (per cycle)
| Artifact | Origin | Format | Retention |
|---|---|---|---|
1.13-evidence-manifest.json |
Build-EvidenceManifest.ps1 |
JSON | 6 years (FINRA 4511) — WORM |
1.13-{testId}-ual.json |
Search-UnifiedAuditLog exports |
JSON | 6 years — WORM |
1.13-{testId}-screenshot.png |
Portal capture | PNG | 6 years — WORM |
1.13-{testId}-agent-response.txt |
Test transcript | UTF-8 | 6 years — WORM |
1.13-corpus-manifest.json |
Repo-controlled | JSON | Source control retention |
1.13-PRE-04-role-matrix.csv |
Get-MgDirectoryRole export |
CSV | 6 years — WORM |
1.13-NEG-01-sit-diff.txt |
git diff of SIT-as-code |
Text | Source control retention |
6.5 Retention and WORM placement
Evidence is retained per FINRA Rule 4511 (general books and records, 6 years) and SEC Rule 17a-4(f) (WORM media or electronic equivalent with required attestations). The evidence root must be either: (a) an immutable Azure Storage container with time-based retention policy locked, (b) an Azure Data Lake with Immutable policy applied, or (c) a third-party WORM-attested archive. The path and storage account ID are recorded once per tenant in docs/reference/evidence-retention.md (firm-specific) and referenced by every cycle's manifest via evidenceRoot metadata in the executor's run log.
Do not treat Content Explorer screenshots as primary evidence; they are supplementary. Primary evidence is the UAL JSON export and the manifest entry hashing it.
§7 Attestation block
The attestation below is signed at the end of every test cycle. RACI alignment: Compliance Officer is Accountable, Information Protection Admin (or Purview Compliance Admin executing the cycle) is Responsible, CISO is Consulted, Internal Audit is Informed.
=============================================================
FSI Control 1.13 — Verification Cycle Attestation
=============================================================
Control ID: 1.13
Control Version: v1.4.0
Tenant ID: ____________________________________
Sovereign Cloud: [ ] Commercial [ ] GCC [ ] GCC High [ ] DoD
Cycle ID: ____________________________________
Cycle Start (UTC): ____________________________________
Cycle End (UTC): ____________________________________
Manifest SHA-256: ____________________________________
Validator Run Log: ____________________________________ (path)
Evidence Root (WORM): ____________________________________
Test Counts:
Pre-flight (PRE-01..07) passed: ___ / 7
Built-in SITs (BUILTIN-01..08) passed: ___ / 8
Custom SITs (CUSTOM-01..04) passed: ___ / 4
EDM (EDM-01..03) passed: ___ / 3
NER (NER-01..04) passed: ___ / 4
Trainable Classifiers (TC-01..04) passed: ___ / 4
DLP-for-Copilot (DLP-01..03) passed: ___ / 3
DSPM for AI (DSPM-01..02) passed: ___ / 2
Audit operations (AUDIT-01..04) passed: ___ / 4
Negative path (NEG-01..05) passed: ___ / 5
Incident reproduction (IR-01) passed: ___ / 1
TOTAL : ___ / 45
Findings opened this cycle: ____
Findings closed this cycle: ____
Open findings carried: ____
-------------------------------------------------------------
Responsible (Executor)
Name: ____________________________________________
Role: [ ] Information Protection Admin
[ ] Purview Compliance Admin
[ ] Compliance Data Administrator
UPN: ____________________________________________
Signature: ____________________________________________
Date (UTC): ____________________________________________
Accountable (Approver)
Name: ____________________________________________
Role: Compliance Officer
UPN: ____________________________________________
Signature: ____________________________________________
Date (UTC): ____________________________________________
Consulted (Security)
Name: ____________________________________________
Role: CISO (or designated Security Officer)
UPN: ____________________________________________
Signature: ____________________________________________
Date (UTC): ____________________________________________
Informed (Audit)
Name: ____________________________________________
Role: Internal Audit / Audit Manager
UPN: ____________________________________________
Acknowledged (Date UTC): ___________________________________
-------------------------------------------------------------
I attest that the verification cycle described above was
executed in accordance with the firm's WSPs (FINRA Rule 3110)
and that the evidence artifacts referenced by the manifest
hash above are complete, unaltered, and stored on WORM media
per FINRA Rule 4511 / SEC Rule 17a-4(f). I further attest
that no operator-mediated waits were substituted for audit-
event verification, that no real customer NPI was used in
synthetic testing, and that the sovereign-cloud parity matrix
(§5) was re-verified within 30 days of cycle start.
=============================================================
Single-role attestation is a finding. A cycle signed only by the Executor (without Compliance Officer counter-signature) does not satisfy the control. See §8 Anti-Pattern #14.
§8 Anti-patterns
The following 15 patterns are non-conformance to Control 1.13 and must be remediated before the cycle can be signed.
- Synthetic-only testing without real-incident replay. No
1.13-IR-01execution against an actual past incident or hypothetical incident artifact within the last 12 months. - Ignoring confidence bands. Treating any positive
DlpRuleMatchas a pass without recording theConfidencefield and reconciling against the policy's configured band. - No false-positive corpus. Every
*-positive-*test executed without the matching*-negative-*test. - Inline test data in playbook prose. Test SSNs, PANs, or account numbers pasted into Markdown rather than referenced from
tests/1.13/corpus/with hash manifest. - Fabricated SLAs. Phrases such as "wait 24 hours for indexing" outside the §3 table of Microsoft-published windows.
- Numeric thresholds in policy UX prose. Documenting "≥85 = High" as if it were a Microsoft universal rule rather than a per-SIT XML
confidenceLevelattribute. - EDM with no near-miss test. EDM classifiers deployed to Zone 3 without
1.13-EDM-02having ever been run. - DLP-for-Copilot user-scope mistargeting. Policies scoped to user groups instead of agent identities or grounding-source SharePoint sites (detected by
1.13-NEG-05). - Training trainable classifiers with production documents. Seed sites containing real customer NPI (violates Control 1.7 secure-handling and OCC 2011-12 model-risk standards).
- Skipping the preview → GA classifier ID re-pointing check. Policies left referencing preview GUIDs after Microsoft has GA'd the classifier (detected by
1.13-NEG-03). - Screenshots without manifest hash entry. Evidence files present in the evidence root but absent from the manifest's
evidenceArtifactslist (validator will fail). - No sovereign-cloud parity check. Reusing a Commercial-tenant attestation in GCC / GCC High / DoD without §5 re-verification (detected by
1.13-PRE-07). - Operator-mediated waits substituted for audit-event verification. "We waited 2 hours and re-tested" with no UAL event capture.
- Single-role attestation. Cycle signed only by Executor, without Compliance Officer counter-signature.
- Treating Content Explorer screenshots as primary audit evidence. Content Explorer is a derived view; primary evidence is the UAL JSON export of
DlpRuleMatch/CopilotInteractionevents with correlation IDs.
§9 Cross-links
- Sibling 1.13 playbooks
portal-walkthrough.md— portal configuration steps for SITs, EDM, classifiers, DLP-for-Copilotpowershell-setup.md— module pinning, IPPS connect, EDM Upload Agent, manifest buildertroubleshooting.md— common failure modes for the tests in this catalog (sibling playbook — pending publication)- Shared baseline
_shared/powershell-baseline.md— pinned module versions and sovereign endpoints- Related controls
- Control 1.5 — Role separation (audited by
1.13-PRE-04) - Control 1.6 — Information Protection labels (downstream consumer of SITs)
- Control 1.7 — Secure handling of training data (gates trainable classifier deployment)
- Control 1.10 — eDiscovery and incident workspace containment (used by
1.13-IR-01) - Control 4.6 — Agent identity inventory (referenced by DLP-for-Copilot scoping in
1.13-DLP-*and1.13-NEG-05) - Framework
- AI Incident Response Playbook — invoked by
1.13-IR-01 - FSI Governance Gate (control spec §3) — gates trainable-classifier deployment per OCC 2011-12 / Fed SR 11-7
Updated: April 2026 | Version: v1.4.0 | UI Verification Status: Current