Browse Source

chore(memory-bank): record Phase 2 of the quality gate and 5.0.0-rc6

Phase 2 is complete on the branch: the fixes, the basic-user CI, the
live tests of all cmdlet groups, three passing lab acceptances, two
reviews, and the coverage across the four configurations, measured again
without --save, which kept only one run. The behavior changes for the
maintainer and the reachable code that no test runs are open work. The
Set-Acl pitfall of the test fixtures is a pattern.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
pull/115/head
Raimund Andree 3 weeks ago
parent
commit
be04cb7132
  1. 147
      .memory-bank/activeContext.md
  2. 4
      .memory-bank/decisions/0021-quality-gate-before-5.0.0.md
  3. 92
      .memory-bank/progress.md
  4. 15
      .memory-bank/systemPatterns.md
  5. 62
      .memory-bank/techContext.md

147
.memory-bank/activeContext.md

@ -9,95 +9,70 @@ source: current task evidence
## Current focus ## Current focus
Phase 2 of the quality gate before 5.0.0 (Decision 21), on the branch Phase 2 of the quality gate before 5.0.0 (Decision 21) is complete on the
`ai/release-5.0.0-rc6`, released as 5.0.0-rc6: tests until every code local branch `ai/release-5.0.0-rc6`, candidate `7b0781f`. The maintainer
path is tested or explained, live tests for the remaining cmdlets, and pushes the branch, merges the pull request after CI, and tags 5.0.0-rc6.
test-first fixes of the known defects. The maintainer approved it on Then Phase 3 (live tests on more operating systems) and 5.0.0; after
2026-10-08. Then Phase 3 and 5.0.0; after 5.0.0 the repository is archived 5.0.0 the repository is archived in favor of WindowsAccessControl
in favor of WindowsAccessControl (Decision 18). (Decision 18).
## Evidence ## Evidence
- 2026-10-08, Phase 1, measured on 5.0.0-rc5 (`fcb370e`): - 2026-10-08, Phase 2 on `ai/release-5.0.0-rc6`, 31 commits on `fcb370e`
- The published package passes the live tests in both editions: 8 role (5.0.0-rc5); the candidate is `7b0781f`:
runs, no failure. - The suite has 684 tests. Elevated: 662 passed and 22 skipped in
- As a basic user, the 11 tests that CI skips pass in both editions. The Windows PowerShell 5.1, 632 and 52 in PowerShell 7. As a basic user
one failure, `Enable-Privileges should write one object per through `Invoke-TestsAsBasicUser.ps1`: 590 and 94, 560 and 124. No
privilege`, assumes more than one privilege. Every test runs in at failure, and no test is skipped in all four configurations; CI runs
least one of four configurations (elevated or basic user, two all four since this branch.
editions), but CI runs only elevated. - C# coverage of all four configurations (AltCover without `--save`,
- The suite runs 55.9% of the C# lines and 37.4% of the branches `techContext.md`): 68.1% of the lines and 44.3% of the branches on
(`techContext.md`, Validation). No line of `Test-Path2` and `1b9edbb`; rc5 58.1% and 38.0%. The earlier figures counted one of
`Get-DiskSpace` runs; `Set-NTFSOwner` (46%) runs only as a setup step the four runs. Of the 972 points that no test ran at `e2b6b24`
of another test; `Clear-NTFSAccess` and the access inheritance cmdlets (without the classes that no cmdlet calls), 400 are code that nothing
run about 43%, `FileSystemSecurity2` 42%. No cmdlet calls the registry calls, 107 defensive guards, 74 need a failure of Windows, 4 need the
classes, `SimpleFileSystemAuditRule`, `PrivilegeEnabler`, or lab, and 387 are reachable; 51 of those ran in runs that the first
`FileSystemEffectivePermissionEntry` (244 lines). measurement missed, and the top items of the rest are in
- 19 of the 36 cmdlets never ran over SMB, among them `Get-NTFSOwner`, `progress.md`, open work 7.
`Set-NTFSOwner`, the audit inheritance cmdlets, and `Clear-NTFSAudit`; - Fixed test-first: `Get-NTFSSimpleAccess` (`ReadData`, the parent of a
no account of another domain or forest ran; both ends of the lab run relative path); `Copy-Item2` and `Move-Item2` (a folder at the
Windows Server 2025. destination, the missing destination folder of #21, also with
- Known defects from the reviews of #113 and #114 (`progress.md`, open `-WhatIf`); the hard-link cmdlets on shares and at folders;
work 3): `Move-Item2 -PassThru` returns the source item; the conflict `Set-NTFSSecurityDescriptor -PassThru` (R5); the error ID of
checks of `Copy-Item2` and `Move-Item2` use `File.Exists` also for `Get-NTFSOrphanedAccess`; relative paths that start with a dot, which
folders, maybe the cause of #21; an error while restoring the owner can every cmdlet shortened by two characters (`Remove-Item2 .x` removed
hide the original one (R4); `Set-NTFSSecurityDescriptor -PassThru` reads another item); comparing entries and descriptors
the item again inside the retry (R5); the access check doesn't read (`InvalidCastException`, also `Compare-Object` in PowerShell 7) and
`AUTHZ_ACCESS_REPLY.Error`, and its buffers aren't initialized. #110 their conversions; `InheritedFrom` with `-ExcludeExplicit` and for a
lists seven test follow-ups. descriptor with audit entries (`ArgumentOutOfRangeException`).
- #34: no reply from the tester by 06:44 UTC on 2026-10-08. `Copy-Item2` no longer creates the missing folders of a destination
- Phase 2, step 1, first part (2026-10-08, commits `82969ba` to for a folder (assumption, flagged for the maintainer).
`ff74100`): 34 new tests for `Set-NTFSOwner`, `Test-Path2`, and - Live tests: cases 4b to 9 and accounts of `b.forest1.net`,
`Get-DiskSpace`, and two defects found and fixed test-first. Every `forest2.net`, and `forest3.net`. The lab acceptance passed for
cmdlet that enables privileges left the Backup, Restore, Take Ownership, `acfe3af`, `1b9edbb`, and `7b0781f` (326 tests each, none failed;
and Security privileges enabled in the session when a later command or a `Tests/Lab/Acceptance-2026-10-08-5.0.0-rc6.md`). Baseline: the
terminating error stopped the pipeline; `Test-Path2` stopped with published 5.0.0-rc5 fails only the two hard-link tests of case 8. The
"Illegal characters in path" in Windows PowerShell for a path such as fixture was removed and the removal checked after each run; three
`C:\a|b`. checkpoints `ntfs-rc6-*-before-acceptance` stay on six machines.
- Phase 2, step 1, link cmdlets (2026-10-08, `4d5c8c4`, `09eb337`): 18 new - `Get-NTFSEffectiveAccess -ServerName` needs administrators or
tests for `New-NTFSHardLink`, `Get-NTFSHardLink`, and Access Control Assistance Operators on the named computer (lab probe,
`New-NTFSSymbolicLink` pass elevated and as a basic user in both documented).
editions; no code defect. The page of `New-NTFSSymbolicLink` was wrong - Two `security-reviewer` passes approved the branch with no Blocker or
twice: `-PassThru` returns a folder object for a link to a folder since Major finding: `fcb370e..e2b6b24` (findings 1, 4, 5, 10 fixed in
5.0.0, and Windows Developer Mode doesn't help, because AlphaFS 2.2.1 `acfe3af`) and `e2b6b24..1b9edbb` (findings 1, 2, 6, 7 fixed in
passes only the File or Directory flag to `CreateSymbolicLinkW`. Lab `7b0781f`). Not fixed: a failed privilege disable isn't tried again,
check on `F1AFile1` as `NtfsLiveServerAdmin` (no administrator): and a non-qualified ACE could shift `InheritedFrom` (neither
with Developer Mode on, `mklink` created a link and the cmdlet of reproducible); `New-NTFSHardLink` stays terminating for a folder (a
5.0.0-rc5 failed with error 1314; the setting was restored. behavior change for the maintainer).
- Security review of `fcb370e..00c3646` (`security-reviewer`, 2026-10-08): - #34: no reply from the tester since 2026-10-06.
the `Dispose` approach is sound; two Major findings, both one root cause
that 4.2.6 already had: the privilege cleanup decided on the states read
in `BeginProcessing` and stopped at the first failure. Reproduced: a
privilege that another command in the pipeline disabled left the others
enabled (silently after an early stop), and
`Get-NTFSOwner ... | ForEach-Object { Disable-Privileges; $_ }` stopped
with "Priviledge already disabled". Two Minor findings: the early-stop
tests could pass vacuously, and `Test-Path2` gave no reason for `$false`.
The maintainer chose to fix all four; fixed test-first in `578042f` and
`b241441`. The suite (555 tests) passes elevated in both editions
(534/0/21 and 504/0/51), and the changed test files pass as a basic user.
## Next step ## Next step
Phase 2, one step at a time, each with evidence before the next: 1. The maintainer pushes the branch, opens the pull request, merges it
after CI, and tags `5.0.0-rc6`; then the live tests run against the
1. Tests for the cmdlets without tests of their own: done for published package (`-Version 5.0.0-rc6`). The first CI run is the first
`Set-NTFSOwner`, `Test-Path2`, `Get-DiskSpace`, and the link cmdlets; run of `Invoke-TestsAsBasicUser.ps1` on a GitHub runner.
open for `Get-NTFSOrphanedAudit` and `Get-NTFSSimpleAccess`. 2. The maintainer decides the behavior changes in `progress.md`, open
2. The other parameter sets and error paths, such as the work 4 (Decision 16), and the scope of Phase 3: the operating systems,
`-SecurityDescriptor` sets of the inheritance cmdlets and of the code that nothing calls, and file servers that aren't Windows
`Clear-NTFSAccess`. (#34).
3. The paths of `Security2` that no test runs, and #110.
4. Test-first fixes of the known defects; behavior changes go to the
maintainer (Decision 16).
5. A CI job as a basic user, live tests for the other cmdlets over SMB and
for accounts of other forests, and a lab run.
6. Measure the coverage again, explain what remains, review, and prepare
5.0.0-rc6. The final review covers the whole branch, including the fix
round of `578042f` and `b241441`.
Open question for the maintainer, not planned: `New-NTFSSymbolicLink`
could request unprivileged creation with
`SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE`, so that Developer Mode
works. That is a behavior change (Decision 16) and needs a fallback for
Windows versions before 10 1703, which don't know the flag.

4
.memory-bank/decisions/0021-quality-gate-before-5.0.0.md

@ -28,7 +28,9 @@ source: maintainer decision of 2026-10-08
of the matrix. of the matrix.
- Rationale: rc5 passed every test that ran, but the tests ran 55.9% of - Rationale: rc5 passed every test that ran, but the tests ran 55.9% of
the code lines and 37.4% of the branches; five cmdlets had no tests of the code lines and 37.4% of the branches; five cmdlets had no tests of
their own, and 19 cmdlets never ran over SMB. their own, and 19 cmdlets never ran over SMB. (That measurement counted
only one of the four test runs; with all four, rc5 runs 58.1% of the
lines and 38.0% of the branches, see `techContext.md`.)
- Open: behavior changes found on the way stay the maintainer's decision - Open: behavior changes found on the way stay the maintainer's decision
(Decision 16); so do the 244 lines of classes that no cmdlet calls, the (Decision 16); so do the 244 lines of classes that no cmdlet calls, the
operating systems of Phase 3, and how to cover file servers that aren't operating systems of Phase 3, and how to cover file servers that aren't

92
.memory-bank/progress.md

@ -11,13 +11,13 @@ source: repository evidence
5.0.0-rc5 is on the PowerShell Gallery and in the GitHub releases, 5.0.0-rc5 is on the PowerShell Gallery and in the GitHub releases,
published by CI on 2026-10-08 from the tag `5.0.0-rc5` on `master` published by CI on 2026-10-08 from the tag `5.0.0-rc5` on `master`
(`fcb370e`, the merge of #114; Decision 12). It adds to 5.0.0-rc4 the live (`fcb370e`, the merge of #114; Decision 12). Phase 2 of the quality gate
tests in a lab (Decision 20) and the fix of (Decision 21) is complete on the local branch `ai/release-5.0.0-rc6`: the
`Get-NTFSEffectiveAccess -ServerName` that they found. Before 5.0.0, the candidate 5.0.0-rc6 (`acfe3af`) passed the suite in four configurations,
maintainer wants the highest quality with everything tested: the quality one `security-reviewer` pass, and the lab acceptance. It waits for the
gate of Decision 21, now in Phase 2, which ends with 5.0.0-rc6. The stable maintainer to push, merge, and tag it; Phase 3 follows. The stable Gallery
Gallery version is still 4.2.6. NTFSSecurity will be archived soon; its version is still 4.2.6. NTFSSecurity will be archived soon; its users move
users move to WindowsAccessControl (Decision 18). to WindowsAccessControl (Decision 18).
## Recent milestones ## Recent milestones
@ -83,6 +83,23 @@ users move to WindowsAccessControl (Decision 18).
PowerShell; and, from one `security-reviewer` pass, the privilege cleanup PowerShell; and, from one `security-reviewer` pass, the privilege cleanup
decided on stale states, a defect since 4.2.6. The page of decided on stale states, a defect since 4.2.6. The page of
`New-NTFSSymbolicLink` was corrected after a lab check of Developer Mode. `New-NTFSSymbolicLink` was corrected after a lab check of Developer Mode.
- 2026-10-08: Phase 2 finished on `ai/release-5.0.0-rc6` (local). Tests for
`Get-NTFSOrphanedAudit`, `Get-NTFSSimpleAccess`, the
`-SecurityDescriptor` parameter sets, the error contracts of all path
cmdlets, and #110. Fixed test-first: `Get-NTFSSimpleAccess` (`ReadData`,
relative paths), `Copy-Item2` and `Move-Item2` (folder conflicts, the
missing destination folder of #21), the hard-link cmdlets on shares,
`Set-NTFSSecurityDescriptor -PassThru` (R5), and the error ID of
`Get-NTFSOrphanedAccess`; from the coverage report, relative paths that
start with a dot (every cmdlet acted on the item without the first two
characters), comparing output objects (`InvalidCastException`), and
`InheritedFrom`. CI runs the suite as a basic user too; the live tests
cover all cmdlet groups and accounts of three more domains. Suite: 677
tests, none failed, none skipped in every configuration; C# coverage
68.1% of the lines and 44.3% of the branches (rc5: 58.1% and 38.0%,
measured again; the first measurements counted one of four runs). Two
`security-reviewer` passes; the lab acceptance of `7b0781f` passed
(`Tests/Lab/Acceptance-2026-10-08-5.0.0-rc6.md`).
## Stable capabilities ## Stable capabilities
@ -97,15 +114,20 @@ users move to WindowsAccessControl (Decision 18).
## Open work ## Open work
1. Quality gate before 5.0.0 (Decision 21): Phase 2 on the branch 1. Quality gate before 5.0.0 (Decision 21): Phase 2 is done on the branch
`ai/release-5.0.0-rc6` (`activeContext.md`), released as 5.0.0-rc6; `ai/release-5.0.0-rc6` (`activeContext.md`); the maintainer pushes it,
Phase 3 runs the live tests on more operating systems. Then release merges the pull request, and tags 5.0.0-rc6, and the live tests run
against the published package. Phase 3 runs the live tests on more
operating systems. Then release
5.0.0 through CI (Decision 12): remove the label, date `[Unreleased]` as 5.0.0 through CI (Decision 12): remove the label, date `[Unreleased]` as
`[5.0.0]`, add the last prerelease to `$publishedVersions`, and tag `[5.0.0]`, add the last prerelease to `$publishedVersions`, and tag
`5.0.0` (steps in `Docs/Contributing/05-Releasing.md`). #34 stays open `5.0.0` (steps in `Docs/Contributing/05-Releasing.md`). #34 stays open
with Bug and Help Wanted until a tester with a file server that refuses with Bug and Help Wanted until a tester with a file server that refuses
the owner confirms the fix, or until 5.0.0 ships. the owner confirms the fix, or until 5.0.0 ships.
2. Issues: #110 (tests) is the open follow-up of the review findings; #68 2. Issues: the rc6 branch addresses the seven items of #110 (tests); the
pull request names it without a closing keyword, so the maintainer
closes it after the merge. #21 (a misleading error of `Move-Item2`) got
a fix in rc6 that names the missing destination folder. #68
tracks `-WhatIf` and `-Confirm` for every cmdlet that changes security. tracks `-WhatIf` and `-Confirm` for every cmdlet that changes security.
The labels follow Decision 17; #16, #21, #45, and #89 wait for their The labels follow Decision 17; #16, #21, #45, and #89 wait for their
reporters (Needs Info). Not planned for 5.0.0: the enhancements #22, reporters (Needs Info). Not planned for 5.0.0: the enhancements #22,
@ -119,11 +141,51 @@ users move to WindowsAccessControl (Decision 18).
`AUTHZ_ACCESS_REPLY.Error`, a fallback warning without the server name, `AUTHZ_ACCESS_REPLY.Error`, a fallback warning without the server name,
and hardening of the lab controller (guards in the setup blocks, and hardening of the lab controller (guards in the setup blocks,
interpolated `-EncodedCommand` paths, CredSSP by IP address, the interpolated `-EncodedCommand` paths, CredSSP by IP address, the
password string in memory, disabling the role accounts after a run). password string in memory, disabling the role accounts after a run); of
4. `pwsh` 7.6.1 crashed three times during test runs on the ARM64 rc6, a privilege that fails to be disabled isn't tried again by
`Dispose` (finding 2, not reproducible).
4. Behavior changes found in Phase 2, for the maintainer (Decision 16):
`Get-NTFSOrphanedAudit` returns nothing without the Security privilege,
while `Get-NTFSAudit` writes `ReadSecurityError`;
`Get-NTFSSimpleAccess` skips a folder whose parent it didn't process;
`New-NTFSSymbolicLink` could create links without the privilege in
Developer Mode (flag `SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE`, with
a fallback before Windows 10 1703); `-WhatIf` names a conflict in a
verbose message instead of a warning (R7); the fallback warning of
`Get-NTFSEffectiveAccess` doesn't name the server; `Move-Item2` can't
move a folder to another volume; `New-NTFSHardLink` stops with a
terminating error for a folder, unlike `Get-NTFSHardLink` (rc6 review,
finding 11). Taken as an assumption in rc6, for review: `Copy-Item2`
no longer creates the missing folders of a destination for a folder.
Found by the coverage report of rc6: `-Target` of the link cmdlets is
optional and means the current location when it's omitted; equality of
entries and descriptors is the identity of the wrapped .NET object, so
two reads of the same entry differ for `Compare-Object` and
`Select-Object -Unique` (value equality would be a behavior change); 400
points of code that nothing calls besides the 244 lines of unused
classes (Phase 3).
5. `pwsh` 7.6.1 crashed three times during test runs on the ARM64
workstation (x64 emulation), without module frames; none of the CI runs workstation (x64 emulation), without module frames; none of the CI runs
on native x64 on 2026-10-05 crashed. on native x64 on 2026-10-05 crashed.
5. Optional for the maintainer: delete the AppVeyor project and revoke its 6. Optional for the maintainer: delete the AppVeyor project and revoke its
GitHub authorization, restrict wiki editing to collaborators, ask GitHub authorization, restrict wiki editing to collaborators, ask
`Sup3rlativ3` to delete the Read the Docs project, and delete the branch `Sup3rlativ3` to delete the Read the Docs project, and delete the branch
`test/transfer`. `test/transfer`. In the lab, delete the checkpoints
`ntfs-rc6-*-before-acceptance` of the six machines when they are no
longer needed.
7. Reachable code that no test runs (coverage report of rc6, ranked by
impact; about 300 points): `Remove-Item2` on folders (`-Recurse`,
`-Force`, `DeleteError`); the owner restore after taking ownership
(`RestoreOwnerError`); the inheritance cmdlets on folders and
`Set-NTFSInheritance -AccessInheritanceEnabled $true`; the mapping of
all 13 `-AppliesTo` values and the flag parameters of
`Remove-NTFSAccess`, `Add-NTFSAudit`, and `Remove-NTFSAudit`; the
switches and errors of `Get-ChildItem2`; the table views and
`InheritedFrom` in them; `Move-Item2 -Force`; account input errors;
`-PassThru` after success of the audit and inheritance cmdlets;
`Set-NTFSSecurityDescriptor` failures; the audit cmdlets without the
Security privilege on a local item; `Get-NTFSEffectiveAccess` for an
unresolvable SID; failed ownership retries of `Clear-NTFSAccess` and
`Set-NTFSInheritance`. A display limit, not a defect: a conditional ACE
shows as an unconditional entry, because the .NET rules have no
condition.

15
.memory-bank/systemPatterns.md

@ -99,9 +99,20 @@ Each Decision record is a file in `decisions/`; read only the relevant ones.
- A test that changes files, links, or security descriptors uses - A test that changes files, links, or security descriptors uses
`Tests\TestHelpers.psm1`: its own sandbox, `Assert-TestSandboxPath` `Tests\TestHelpers.psm1`: its own sandbox, `Assert-TestSandboxPath`
before each change, `Remove-TestSandbox`. Cases that need a privilege before each change, `Remove-TestSandbox`. Cases that need a privilege
skip with `Test-PrivilegeHeld` and run in CI (elevated). `Block-Test*` skip with `Test-PrivilegeHeld`, cases that need its absence skip when
make a read or a write fail without elevation; `Set-TestOwner` with elevated; CI runs the suite elevated and as a basic user in both
editions, so each case runs somewhere. `Block-Test*` make a read or a
write fail without elevation; `Set-TestOwner` with
`EnablePrivileges = $false` reproduces an owner the user can't assign. `EnablePrivileges = $false` reproduces an owner the user can't assign.
- Fixtures write a DACL with `SetAccessControl`, never with `Set-Acl`:
`Set-Acl` compares `AreAuditRulesProtected` of the new descriptor with
`AreAccessRulesProtected` of the item (`FileSystemSecurity.cs` of
PowerShell), so for an item with a protected DACL it writes the audit
section too. Without the Security privilege that fails with
`PrivilegeNotHeldException`; with it, `Set-Acl` writes every section and
drops the audit entries. Windows PowerShell has
`FileInfo`/`DirectoryInfo.SetAccessControl`; PowerShell 7 has
`[System.IO.FileSystemAclExtensions]::SetAccessControl`.
- `Get-Help -Online` tests run only in Windows PowerShell, which honors the - `Get-Help -Online` tests run only in Windows PowerShell, which honors the
hook `BypassOnlineHelpRetrieval`. `Manifest.Tests.ps1` and hook `BypassOnlineHelpRetrieval`. `Manifest.Tests.ps1` and
`Release.Tests.ps1` check the manifest, the version (Decision 10), the `Release.Tests.ps1` check the manifest, the version (Decision 10), the

62
.memory-bank/techContext.md

@ -88,7 +88,8 @@ source: repository evidence
## Constraints ## Constraints
- `ModuleVersion` is `5.0.0` with the prerelease label `rc5`. - `ModuleVersion` is `5.0.0` with the prerelease label `rc6` on the branch
`ai/release-5.0.0-rc6` (`rc5` on `master`).
The latest stable tag and Gallery release is `4.2.6`. The manifest The latest stable tag and Gallery release is `4.2.6`. The manifest
requires PowerShell 5.1 and .NET Framework 4.5.2, uses `RootModule`, and requires PowerShell 5.1 and .NET Framework 4.5.2, uses `RootModule`, and
lists exactly 36 cmdlets; `Test-ModuleManifest` passes in Windows lists exactly 36 cmdlets; `Test-ModuleManifest` passes in Windows
@ -143,7 +144,9 @@ source: repository evidence
then: 01 `Update-MarkdownHelp` and fail on `git diff -- Docs/Cmdlets`; 02 then: 01 `Update-MarkdownHelp` and fail on `git diff -- Docs/Cmdlets`; 02
`Get-MarkdownLink -BrokenOnly`; 03 regenerate the help file and fail on `Get-MarkdownLink -BrokenOnly`; 03 regenerate the help file and fail on
`git status --porcelain -- NTFSSecurity/en-US`; 04 `Invoke-Tests.ps1` in `git status --porcelain -- NTFSSecurity/en-US`; 04 `Invoke-Tests.ps1` in
Windows PowerShell 5.1 and in PowerShell 7. Job `wiki` on `ubuntu-latest` Windows PowerShell 5.1 and in PowerShell 7, then
`Invoke-TestsAsBasicUser.ps1` in both editions (since 5.0.0-rc6). Job
`wiki` on `ubuntu-latest`
(read-only) clones the wiki (`gh auth setup-git` with the built-in token), (read-only) clones the wiki (`gh auth setup-git` with the built-in token),
runs `Export-WikiContent.ps1`, and lists the changed pages in the job runs `Export-WikiContent.ps1`, and lists the changed pages in the job
summary; job `publish-wiki` (`contents: write`) repeats that and publishes, summary; job `publish-wiki` (`contents: write`) repeats that and publishes,
@ -163,7 +166,8 @@ source: repository evidence
ci.yml`, `gh pr checks <number>`, and `gh run view <id> --log-failed` ci.yml`, `gh pr checks <number>`, and `gh run view <id> --log-failed`
(read-only). (read-only).
- Workflow lint: actionlint (download the release zip into `$env:TEMP` and - Workflow lint: actionlint (download the release zip into `$env:TEMP` and
check its SHA-256 against the checksum file); PowerShell steps check check its SHA-256 against the checksum file; 1.7.12 on 2026-10-08);
PowerShell steps check
`$LASTEXITCODE` after every native command, because GitHub checks only `$LASTEXITCODE` after every native command, because GitHub checks only
the last one. the last one.
- Run platyPS in Windows PowerShell 5.1 to avoid PowerShell 7.4+ - Run platyPS in Windows PowerShell 5.1 to avoid PowerShell 7.4+
@ -175,25 +179,37 @@ source: repository evidence
PowerShell 5.1: the launcher starts `pwsh`, and its payload runs PowerShell 5.1: the launcher starts `pwsh`, and its payload runs
`powershell.exe -NoProfile -EncodedCommand` with Pester imported by full `powershell.exe -NoProfile -EncodedCommand` with Pester imported by full
path. A run without `bin\Release\en-US` must fail. path. A run without `bin\Release\en-US` must fail.
- Tests that run only without a privilege skip in CI and in an elevated - Tests that run only without a privilege skip in an elevated session.
session. Run them as a basic user with `runas /trustlevel:0x20000`, and `.github\scripts\Invoke-TestsAsBasicUser.ps1` runs the suite from an
give Windows PowerShell its own `PSModulePath`; that token holds one elevated session with a token of the SAFER level Normal User, like
privilege, so the `Enable-Privileges -PassThru` count test fails there. `runas /trustlevel:0x20000`, and CI runs it in both editions. For a
`runas` returns at once, so the script it starts writes its own log. single file, `runas /trustlevel:0x20000` works too; give Windows
PowerShell its own `PSModulePath`, and note that `runas` returns at once,
so the script it starts writes its own log. Both tokens hold only the
privilege to bypass traverse checking.
Pester reports a skipped `-ForEach` test under its template name, such as Pester reports a skipped `-ForEach` test under its template name, such as
`<_> should ...`, and a test that ran under the expanded name: compare `<_> should ...`, and a test that ran under the expanded name: compare
runs by template. runs by template.
- C# coverage (Decision 21): AltCover 9.0.145 (`tools\net472\AltCover.exe` - C# coverage (Decision 21): AltCover 9.0.145 (`tools\net472\AltCover.exe`
of the nuget.org package) instruments a copy of the local Release build, of the nuget.org package) instruments a copy of the local Release build,
which has the PDB files that the published package lacks: `--save`, which has the PDB files that the published package lacks:
`--reportFormat=OpenCover`, AlphaFS and `System.Management.Automation` `--reportFormat=OpenCover`, AlphaFS and `System.Management.Automation`
excluded with `--assemblyFilter`. Put the instrumented module in excluded with `--assemblyFilter`, and no `--save`: then every process
`NTFSSecurity\bin\Release` of a `git worktree`, run writes its hits into the report when it exits. With `--save`, each
`.github\scripts\Invoke-Tests.ps1` elevated and as a basic user in both process writes a recorder file, and `runner --collect` keeps only the
editions, then `AltCover.exe runner --collect --recorderDirectory=<the first one (verified 2026-10-08), so the numbers measured that way held
instrumented folder>`. Baseline of the rc5 tree on 2026-10-08: 55.9% of only the main process of the elevated Windows PowerShell run. Put the
the lines (1,943 of 3,476), 37.4% of the branches (700 of 1,873); 60.1% instrumented module in `NTFSSecurity\bin\Release` of a `git worktree`,
of the lines without 244 lines in classes that no cmdlet calls. run `.github\scripts\Invoke-Tests.ps1` elevated and
`Invoke-TestsAsBasicUser.ps1` in both editions, then
`AltCover.exe runner --collect --recorderDirectory=<the instrumented
folder>`, which recalculates the summary of the report from the hits.
All four configurations, 2026-10-08: the rc5 tree 58.1% of the lines
(2,020 of 3,476) and 38.0% of the branches (711 of 1,873), 62.5% without
244 lines in classes that no cmdlet calls; the rc6 candidate (`1b9edbb`)
68.1% of the lines (2,412 of 3,540) and 44.3% of the branches (850 of
1,918), 73.2% without those classes, the `NTFSSecurity` assembly 78.1%.
The earlier figures, 55.9% for rc5 and 65.6% for rc6, used `--save`.
- Live tests (Decision 20): in an elevated Windows PowerShell 5.1 session - Live tests (Decision 20): in an elevated Windows PowerShell 5.1 session
on the lab host, `Tests\Lab\Invoke-NTFSSecurityLabTest.ps1` with on the lab host, `Tests\Lab\Invoke-NTFSSecurityLabTest.ps1` with
`-Version` for Gallery packages or `-ModulePath` for a build; it writes `-Version` for Gallery packages or `-ModulePath` for a build; it writes
@ -204,6 +220,20 @@ source: repository evidence
(Remote Management Users on the client, CredSSP by IP address like the (Remote Management Users on the client, CredSSP by IP address like the
controller): reset its password on the PDC emulator to a random value controller): reset its password on the PDC emulator to a random value
in memory; the next run of the controller sets a new one anyway. in memory; the next run of the controller sets a new one anyway.
- Lab acceptance of a candidate (modeled on the WindowsAccessControl
handoff 07): build once, package it with `New-ModulePackage.ps1`, and
record the SHA-256 of the packages and module files; check WinRM, LDAP
(RootDSE), Kerberos (`klist get`), the secure channel, and the clock of
the six VMs; take a Production checkpoint named
`ntfs-<label>-<commit>-before-acceptance` of `F1ADC1`, `F1BDC1`,
`F2DC1`, `F3DC1`, `F1AFile1`, and `F1AFile2`; run the controller with
`-ModulePath` of the extracted `NTFSSecurity.zip` in both editions; then
`-RemoveFixture` and check that the accounts, share, folders, group
memberships, and profiles are gone.
- `Get-NTFSEffectiveAccess -ServerName`: the authorization manager of the
named computer answers only its administrators and the members of its
group Access Control Assistance Operators (S-1-5-32-579); others get
"Access is denied" (5). Lab probe of 2026-10-08 on `F1AFile2`.
- Markdown lint: `npx markdownlint-cli2` with `MD013` limited to prose - Markdown lint: `npx markdownlint-cli2` with `MD013` limited to prose
(tables, code, and headings excluded) on the conceptual pages; for (tables, code, and headings excluded) on the conceptual pages; for
`CHANGELOG.md` also `MD024` with `siblings_only: true`, because every `CHANGELOG.md` also `MD024` with `siblings_only: true`, because every

Loading…
Cancel
Save