Items: the comparison of Get-Privileges with whoami compares the State only
where whoami prints the English words, because the column is localized. The
rows 'as an array with an empty element' of Copy-Item2 and Move-Item2 now pass
an array: a switch unrolls @(''), so they had passed the plain empty string. The
empty-path rows of both cmdlets run in a folder of their own, so that a guard
that regressed would copy or move an empty folder and not the sandbox into
itself.
Audit: a piped AppliesTo property does not select PathSimple, the default set
PathComplex binds and the property is dropped (a descriptor object does select
SDSimple), so the rows named PathSimple bound PathComplex. The PathSimple rows
of Add-NTFSAudit and Remove-NTFSAudit now name -AppliesTo and pipe the rest,
and the Add rows use a folder and assert the scope of the new entry (None, not
the default ContainerInherit and ObjectInherit). The descriptor rows assert the
entry in the descriptor and, after Set-NTFSSecurityDescriptor, on disk.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Get-Acl -Audit reads the SACL together with the other sections. On a domain
member (Windows Server 2019, 2022, and 2025 of the operating-system matrix)
that read reports the SACL of an item without audit entries as protected from
inheritance, where the read of the SACL alone and Get-NTFSInheritance report
it as not protected (FileSystemSecurity2 documents the same difference).
The test 'Disable-NTFSAuditInheritance -SecurityDescriptor should take two
piped descriptors ...' asserted the on-disk flag of a fresh file with
Get-Acl -Audit, and failed in all six elevated configurations of the three
file servers. Diagnostic runs on 2019 and 2025 show both reads side by side.
Four more assertions read the flag of an item that ends without audit entries
and expect "protected"; there they could not tell a written flag from none.
The five assertions now read the SACL alone through .NET, as the module does.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
Add Tests\ParameterSets.Audit.Tests.ps1, closing the TestNeeded gaps that
judged-audit.csv/judged-audit-notes.md recorded for Add-NTFSAudit,
Remove-NTFSAudit, Clear-NTFSAudit, Get-NTFSAudit, and Get-NTFSOrphanedAudit:
- Pipeline binding by value and by property name for every parameter set of
all five cmdlets, including the four sets the matrix flagged as bound only
by splat or pipe calls (Add-NTFSAudit SDSimple, Remove-NTFSAudit PathSimple
and SDSimple, Get-NTFSOrphanedAudit SD), each of which also gets a direct,
named call.
- Continuation past a failing path or a descriptor without an audit section,
asserting the ErrorId, category, and target of the error and the state or
output of the item that follows.
- State assertions beyond -PassThru: SACL/DACL SDDL before and after, the
in-memory descriptor versus the item on disk until Set-NTFSSecurityDescriptor
writes it, and the protected/unprotected SACL after Clear-NTFSAudit
-DisableInheritance.
- Narrowing of an audit entry's rights when Remove-NTFSAudit runs without
-RemoveSpecific, and the AmbiguousParameterSet error when -AppliesTo and
-InheritanceFlags are combined.
No production code, existing test file, or helper module changed. Fixture
DACLs use .NET SetAccessControl through the existing TestHelpers.psm1
helpers; no test pins the open item of the -SecurityDescriptor sets of Add
and Remove having no per-item handler around the change itself.
Verified in all four configurations (elevated/basic user x Windows
PowerShell 5.1/PowerShell 7): 0 failures. Mutation-tested with 9 one-statement
changes to the production C# in a separate, detached worktree; 8 were caught
by the new tests and one (the -AppliesTo-to-flags conversion for the Simple
sets, masked on a file target) was not, which the pre-existing
PermissionScopes.Tests.ps1 already catches on a folder target.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>