You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

6.4 KiB

status last-verified owner source
current 2026-10-08 active-agent repository evidence

System patterns

Architecture

NTFSSecurity.psd1 ─┬─ ScriptsToProcess: NTFSSecurity.Init.ps1
                   │    Add-Type: Security2.dll, PrivilegeControl.dll,
                   │    ProcessPrivileges.dll, inline NTFS.DriveInfoExt;
                   │    Update-FormatData -PrependPath format.ps1xml
                   ├─ TypesToProcess: NTFSSecurity.types.ps1xml
                   │    (Owner, IsInheritanceBlocked, LengthOnDisk on
                   │    FileInfo/DirectoryInfo; AccountType on ACEs)
                   ├─ RootModule: NTFSSecurity.psm1 (aliases)
                   ├─ NestedModules: NTFSSecurity.dll (36 cmdlets)
                   └─ en-US\NTFSSecurity.dll-Help.xml (Get-Help; generated
                        from Docs/Cmdlets, Decision 8)
NTFSSecurity.dll ── cmdlets ──> Security2.dll (FileSystemAccessRule2,
                                FileSystemAuditRule2, IdentityReference2,
                                FileSystemInheritanceInfo, EffectiveAccess)
                 ── long paths ──> AlphaFS
                 ── privileges ──> PrivilegeControl / ProcessPrivileges
  • BaseCmdlet resolves only relative paths, against the current file system location of the session (not $PWD, #86). Path parameters carry [FileSystemPathTransformation], which binds file objects as full paths.
  • On access denied, most cmdlets retry through InvokeAsOwner, which takes ownership and restores the previous owner on every exit path.
  • BaseCmdletWithPrivControl enables Backup, Restore, TakeOwnership, and Security in BeginProcessing when PrivateData.EnablePrivileges is $true, and disables the ones it enabled in EndProcessing and, since 5.0.0-rc6, in Dispose: PowerShell skips EndProcessing when a later command, such as Select-Object -First, or a terminating error stops the pipeline, but calls Dispose. Enable-Privileges keeps them (KeepEnabledPrivileges).
  • PrivateData switches: EnablePrivileges, GetInheritedFrom, GetFileSystemModeProperty, IdentifyHardLinks, ShowAccountSid.
  • Cmdlets accept -Path (alias FullName) or -SecurityDescriptor; the SD sets change the object in memory until Set-NTFSSecurityDescriptor.

Decisions

Each Decision record is a file in decisions/; read only the relevant ones.

# Decision
1 Use the canonical Memory Bank base
2 Cmdlet reference stays platyPS markdown
3 Document the source at HEAD
4 Online help points to GitHub
5 Document defects, don't fix them in docs work
6 CI checks the docs against a build of the source
7 CHANGELOG lists user-visible changes only
8 Commit the generated help file and check it in CI
9 Keep the documentation on GitHub
10 One version for the manifest, assemblies, and changelog
11 CI and the wiki run on GitHub Actions
12 Releases are built and published by CI on a version tag
13 Set-NTFSInheritance keeps entries like the dedicated cmdlets
14 Repository hardening is optional
15 Merge stacked pull requests in order with merge commits
16 Fix only reproducible bugs
17 Issue labels
18 NTFSSecurity will be archived
19 Cmdlets write only the sections that they change
20 Live tests in a lab live in Tests\Lab
21 A quality gate before 5.0.0

Patterns

Verifying documentation

  • Run platyPS in Windows PowerShell 5.1 against a Release build; a copy of Docs/Cmdlets must round-trip through Update-MarkdownHelp unchanged. Keep cmdlet pages ASCII-only. platyPS takes Position and Required from the shipped help file: after such a change, edit the page YAML, run New-ExternalHelp, rebuild, and check the round trip.
  • MarkdownLinkCheck checks relative Docs links, Tests\Wiki.Tests.ps1 the wiki links and anchors. The wiki is generated from Docs (never edit it); Docs/README.md becomes Home, its cmdlet groups the sidebar.
  • In cmdlet pages, end a sentence with a link (platyPS drops the space after it). Verify examples in a $env:TEMP sandbox, never on real data.

Testing the module

  • Pester 5 tests in Tests/*.Tests.ps1 import the Release build; CI runs them in Windows PowerShell 5.1 and PowerShell 7 (Decision 11).
  • A test that changes files, links, or security descriptors uses Tests\TestHelpers.psm1: its own sandbox, Assert-TestSandboxPath before each change, Remove-TestSandbox. Cases that need a privilege skip with Test-PrivilegeHeld and run in CI (elevated). Block-Test* make a read or a write fail without elevation; Set-TestOwner with EnablePrivileges = $false reproduces an owner the user can't assign.
  • Get-Help -Online tests run only in Windows PowerShell, which honors the hook BypassOnlineHelpRetrieval. Manifest.Tests.ps1 and Release.Tests.ps1 check the manifest, the version (Decision 10), the release notes, and the packages.
  • The live tests in Tests\Lab (Decision 20) run as domain accounts in a lab: on the client over SMB, then on the file server, which checks what the client runs left. They read and write descriptors as Windows stores them with GetFileSecurity and SetFileSecurity, because GetNamedSecurityInfo converts a DACL without the auto-inherit flag and returns its owner. The expected effective rights come from the S4U tokens of the file server and the client, like the Effective Access tab.