mirror of https://github.com/raandree/NTFSSecurity
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.
7.8 KiB
7.8 KiB
| status | last-verified | owner | source |
|---|---|---|---|
| current | 2026-10-09 | active-agent | repository and regression evidence |
System patterns
Architecture
| Component | Responsibility |
|---|---|
NTFSSecurity.psd1 |
Root script, nested binary, initialization, types, help |
NTFSSecurity.Init.ps1 |
Loads Security2/privilege assemblies and prepends formatting |
NTFSSecurity.dll |
36 PowerShell cmdlets; BaseCmdlet path/privilege behavior |
Security2.dll |
DACL/SACL objects, owners, inheritance, effective access, Win32 |
| AlphaFS | Long-path files/directories/links |
| PrivilegeControl / ProcessPrivileges | Token privilege operations |
en-US/NTFSSecurity.dll-Help.xml |
Committed help generated from cmdlet Markdown |
Decisions
Read only task-relevant records; the index controls routing.
Patterns
Cmdlets and security sections
- BaseCmdlet resolves relative paths against the current filesystem location; file-object input binds FullName through path transformation.
- Write only changed/read sections (Decision 19); a descriptor parameter
changes memory until
Set-NTFSSecurityDescriptorpersists it. - Access denial can retry through InvokeAsOwner; restore the previous owner on every exit, except a successful descriptor write that intentionally sets the owner. Restoration failures must report RestoreOwnerError.
- Privilege cleanup runs in EndProcessing and Dispose, reads current states, attempts all cleanup, and preserves explicit enables. Dispose has no stream.
- Pipeline getters never throw; per-item errors name input and allow continuation.
- Folder moves never use CopyAllowed; preserve cross-volume source folders.
- Apply implied Hidden/Force before deciding to emit, including the first item.
- A catch-all for the failures of one item must pass on what a later command
raises through a Write call. A downstream throw is an ordinary exception,
so a type check finds only the end of the pipeline, break, and continue.
BaseCmdlet notes the exception that its WriteObject, WriteError,
WriteVerbose, and WriteDebug raised (WriteWarning is not noted: no catch-all
encloses it);
IsFromLaterCommandrecognizes it, and the type checkPipelineControl.IsEndbacks it up for other calls into PowerShell. A write inside a helper, such as the owner restore ofInvokeAsOwner, is an accepted gap: its handler reports the item's own error, which raises too. Prefer writing outside the try.Tests/PipelineControl.Tests.ps1has rows for every cmdlet: add a row for a new one, and keep the typed-throw rows (they fail if PowerShell stops wrapping a thrown exception). - Record an enabled privilege before the next write, which a later command can answer with an exception: Dispose disables only what is recorded.
Get-ChildItem2 -Filterhas two matchers: the AlphaFS enumeration, whose dot rules also differ from those ofGet-ChildItem(probe:Report.*andRep*.in both editions), and a PowerShell wildcard on the name, where only*and?are special.*.*is treated as*; the other dot patterns are pinned byItemCmdlets.Testsand are an open maintainer decision.
Tests and documentation
- Tests import Release in isolated processes, both editions and privilege modes. File/ACL/link fixtures use shared sandbox guards and cleanup. Privilege-dependent skips must have eligible counterparts in the matrix.
- Assert persisted state, errors/targets, continuation, and no failed PassThru output. Prove new characterization guards with bounded mutations; restore source exactly and rebuild before green validation or packaging. Apply the mutations of one round together only when no guard can fail because of another mutation; otherwise split the rounds.
- A test that arranges a retry asserts its precondition (the plain write is denied), or it can pass without reaching the retry.
- A test variable must not take the name of an automatic variable such as
$foreach: Pester runs the block inside a foreach, and the value is lost. - The CI scripts set
$ErrorActionPreference = 'Stop'; focused runs do the same, and a test that needs a non-terminating error (for example to take it through2>&1) names-ErrorAction Continue. - Fixture DACLs use .NET SetAccessControl, not Set-Acl's unintended SACL writes.
- Scope/descendant expectations are independent of the production converter.
- Drive-root tests map a sandbox folder with
substthroughNew-TestDriveMapping(elevated only; the basic token cannot). Tests that need a letter without a volume take the lowest free one. - Desktop platyPS: generate help, rebuild, round-trip unchanged, check links. platyPS 0.14.2 turns a pair of asterisks in a paragraph into emphasis, also inside backticks, and the help drops them: write the words, put patterns in example code blocks, and check the generated XML.
- Live tests use only approved lab targets, SMB then independent server state; Get/SetFileSecurity preserves stored DACLs; rights oracles use S4U tokens.
CI results and publication
- Use Path.Combine then GetFullPath for a rooted-or-repository-relative result path; Join-Path appends even a rooted child and corrupts it.
- Discovery handles only expected PackageNotFound as absence; repository, authentication, and network errors remain failures.
- Rerun/uncertain-upload success requires Gallery SHA-512 equality with the exact build artifact. Base64 is case-sensitive: use ordinal comparison. Missing/different/unverifiable metadata preserves the upload error.
- Secrets stay by environment reference, never in process arguments/logs. Test all external publication commands with mocks; no test may upload.
- AltCover aggregates all four sequential runs without --save. Report sequence points, not unique source lines; keep unmatched paths visible.