mirror of https://github.com/raandree/NTFSSecurity
Browse Source
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: AI Assistant <ai@example.com>pull/117/head
4 changed files with 341 additions and 573 deletions
@ -1,203 +1,121 @@ |
|||||
--- |
--- |
||||
status: current |
status: current |
||||
last-verified: 2026-10-08 |
last-verified: 2026-10-09 |
||||
owner: active-agent |
owner: active-agent |
||||
source: repository evidence |
source: repository and validation evidence |
||||
--- |
--- |
||||
|
|
||||
# Progress |
# Progress |
||||
|
|
||||
## Current status |
## Current status |
||||
|
|
||||
5.0.0-rc6 is on the PowerShell Gallery, published by CI on 2026-10-08 at |
5.0.0-rc6 is published on the Gallery and GitHub; its failed Release job |
||||
20:40 UTC from the tag `5.0.0-rc6` on `master` (`b51d970`, the merge of |
recovered in attempt 2 on 2026-10-09. #116 (rc7, `d25647d`, base `master`) |
||||
pull request #115; Decision 12). The Release job failed after the upload, |
is open and green, not merged or published. Further quality-gate work is |
||||
so the GitHub release waits for a rerun of the failed job. The published |
local on `ai/quality-gate-coverage`; Phase 2 is not complete while the |
||||
package passed the live tests. Phase 2 of the quality gate (Decision 21) |
remaining-path inventory is open. Stable Gallery version: 4.2.6. |
||||
is complete. The pull request #116 (`ai/release-5.0.0-rc7`) holds the |
After 5.0.0, archive in favor of WindowsAccessControl (Decision 18). |
||||
behavior changes that Phase 2 found, decided as assumptions for the |
|
||||
maintainer's review (Decision 22), and waits for that review. Phase 3 |
|
||||
follows. The stable Gallery version is still 4.2.6. NTFSSecurity will be |
|
||||
archived soon; its users move to WindowsAccessControl (Decision 18). |
|
||||
|
|
||||
## Recent milestones |
## Recent milestones |
||||
|
|
||||
- 2026-10-02 to 2026-10-04: #91 to #97 aligned the docs with the code, |
- 2026-10-02 to 2026-10-06: documentation/help aligned with source, CI and |
||||
shipped the help file, kept the docs on GitHub, set version 5.0.0, moved |
wiki moved to GitHub Actions, versioning/release automation established, |
||||
CI and a wiki generated from `Docs` to GitHub Actions, and completed the |
and prereleases rc1 to rc4 published. Earlier detail is in git, |
||||
version history (Decisions 6 to 11). |
`CHANGELOG.md`, `Docs/Version-History.md`, and Decisions 1 to 19. |
||||
- 2026-10-04: #98 (`e0f5366`) added releases on a version tag through CI |
- 2026-10-07: lab comparison of rc2/rc4 reproduced #34 over SMB and proved |
||||
(Decision 12). The tag `5.0.0-rc1` published to the Gallery and created |
changed-section writes preserve the owner. Remote effective-access |
||||
the GitHub prerelease; the installed module passed the full suite. |
fallback returned no result; fixed test-first for rc5 (Decision 20). |
||||
- 2026-10-05, overnight run: the 24 code defects of work package 5 and the |
- 2026-10-08: #114 merged (`fcb370e`), rc5 published and live-tested. |
||||
issues #3, #4, #5, #17, #74, #82, #86, and #88 fixed with regression |
Decision 21 established the quality gate. Corrected four-run coverage: |
||||
tests, plus what one security review per PR found; the 37 open issues |
rc5 58.1% sequence points/38.0% branches, not the initial one-run result. |
||||
triaged; `Docs/FAQ.md`, Dependabot for the actions, and the label `rc2`. |
- 2026-10-08: rc6 Phase 2 added basic-user CI, parameter-set/error tests, |
||||
#5 and #82 are breaking changes, like the change of Decision 13. |
expanded domain/SMB cases, and fixes for privilege cleanup, path |
||||
- 2026-10-05: the first CI runs of the eight PRs found a defect that the |
resolution, ownership retries, item conflicts, output equality, and |
||||
workstation had skipped, fixed in `629f4e7` (audit inheritance of an item |
inherited flags. Suite: 677; coverage 68.14% sequence/44.32% branches. |
||||
without a SACL). The PRs #99 to #106 were merged in order with merge |
Lab acceptance of `7b0781f` passed; two independent review passes. |
||||
commits, CI on `master` passed, and the tag `5.0.0-rc2` published the |
- 2026-10-08: rc7 implemented proposed Decision 22, including breaking |
||||
prerelease; GitHub's Actions outage that day cancelled the first two |
link binding/error changes, SimpleAccess traversal, cross-volume folder |
||||
attempts of the release run before they started. Repository hardening is |
preservation, and named effective-access warnings. Suite: 712, no |
||||
optional (Decision 14); the merge rule and the maintainer's rule for |
failures or test skipped everywhere. One review: no Blocker/Major. |
||||
fixes are Decisions 15 and 16. |
Lab candidate `dc6e9f5`: 326 passed, 2 skipped, cleanup verified. |
||||
- 2026-10-06: the issues got their labels (Decision 17). The maintainer |
- 2026-10-08: #115 merged (`b51d970`) and tagged rc6. Release run |
||||
decided to publish 5.0.0-rc3 before 5.0.0 and to archive the project in |
`37839669028` failed with HTTP 409 after Gallery publication. The log |
||||
favor of WindowsAccessControl (Decision 18); the README, the docs home, |
does not establish the previously assumed initial timeout/retry cause. |
||||
and the changelog announce it. |
Published rc6 live tests differed only in rc7's warning expectation. |
||||
- 2026-10-06: 5.0.0-rc3 (#112): the access and audit cmdlets write only |
- 2026-10-09: release attempt 2 succeeded; rc6 GitHub prerelease and zip |
||||
the section that they change, which fixes #34 and the inherited entries |
appeared at 07:01:34 UTC. #116 passed CI on `d25647d`. |
||||
that elevated sessions copied as explicit ones (Decision 19). #67 has its |
- 2026-10-09: autonomous follow-up on `ai/quality-gate-coverage`, through |
||||
cause outside the module (a share root over UNC can't re-inherit), is |
`3442194`, adds 202 cases above rc7: deletion/owner failures, all 13 |
||||
explained in `Docs/FAQ.md`, and was closed as not planned. One |
scopes, inheritance transitions, enumeration, forced replacement, |
||||
`security-reviewer` pass approved the branch. The PR description said |
descriptor failures, and offline CI recovery. Reproduced/fixed rooted |
||||
"fixes #34", so the merge closed #34; it was reopened for a tester. |
result-path handling and first-hidden-item omission. Publication recovery |
||||
- 2026-10-06: 5.0.0-rc4 (#113), test-first: drive and volume roots read |
verifies exact SHA-512 identity, not merely version existence. |
||||
and change their root folder, not the device (#41); the audit cmdlets |
- 2026-10-09: final uninstrumented suite: 914 per configuration, zero |
||||
reject a descriptor without the audit entries (#109); `-WhatIf` previews |
failures; coverage: 2,641/3,559 sequence points (74.21%) and 974/1,933 |
||||
`Copy-Item2` and `Move-Item2` despite an existing destination (#108); |
branches (50.39%), aggregate of four runs without AltCover `--save`. |
||||
small items (#111). One `security-reviewer` pass approved it; its Minor |
All skipped templates have executed counterparts. Mutation guards were |
||||
findings R1, R2, R6, and R8 were fixed before the merge. #41, #108, |
proved and production source restored; Release build/checks pass. |
||||
#109, and #111 closed as completed, #90 and #107 as not planned. |
- 2026-10-09: live comparison, 09:20 to 09:51 UTC: candidate 330 passed, |
||||
- 2026-10-07: live tests in the lab of WindowsAccessControl (Decision 20) |
zero failed, two expected skips; published rc6 four expected Hidden/ |
||||
against 5.0.0-rc2 and 5.0.0-rc4 in both editions: rc2 fails #34 over SMB |
warning-text failures only. Independent cleanup probes verified fixture |
||||
with error 1307 for `Add-NTFSAccess`, `Clear-NTFSAccess`, and |
absence; raw host-verifier failures retained with corrected verification. |
||||
`Set-NTFSSecurityDescriptor`; rc4 passes the four cases, except |
Lab guards/acceptance committed in `7594e0c`. One independent code review |
||||
`Get-NTFSEffectiveAccess -ServerName` with a computer that can't be |
approved with no significant finding (custom model unavailable; built-in |
||||
reached, which returned no access since before rc1. The maintainer chose |
fallback). All 11 tested files match the ZIP. OS/path gates stay open. |
||||
to fix it test-first in 5.0.0-rc5; the branch build passes all live tests |
|
||||
and the suite. One `security-reviewer` pass approved it with minor |
|
||||
findings (`activeContext.md`). |
|
||||
- 2026-10-08: #114 merged (`fcb370e`); the tag `5.0.0-rc5` published it to |
|
||||
the Gallery and the GitHub releases, whose `NTFSSecurity.zip` holds the |
|
||||
same 11 files. Phase 1 of the quality gate (Decision 21) measured rc5: |
|
||||
the published package passes the live tests in both editions; the 11 |
|
||||
tests that need a session without the Security privilege pass as a basic |
|
||||
user, so every test runs in at least one configuration, but CI runs only |
|
||||
elevated; the suite runs 55.9% of the C# lines and 37.4% of the branches. |
|
||||
The maintainer approved Phase 2. |
|
||||
- 2026-10-08: Phase 2, step 1 on `ai/release-5.0.0-rc6` (local): tests for |
|
||||
`Set-NTFSOwner`, `Test-Path2`, `Get-DiskSpace`, and the link cmdlets |
|
||||
(suite: 555 tests). Fixed test-first: the privileges stayed enabled after |
|
||||
an early stop; `Test-Path2` stopped for invalid characters in Windows |
|
||||
PowerShell; and, from one `security-reviewer` pass, the privilege cleanup |
|
||||
decided on stale states, a defect since 4.2.6. The page of |
|
||||
`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`). |
|
||||
- 2026-10-08: #115 (rc6, head `be04cb7`) passed CI in all four |
|
||||
configurations. On `ai/release-5.0.0-rc7` (local), the behavior changes |
|
||||
of Phase 2 were decided as assumptions for review (Decision 22) and |
|
||||
implemented test-first, two of them breaking (the link cmdlets); new |
|
||||
defects found on the way: `Move-Item2` deleted an empty folder that it |
|
||||
moved to another volume, the link cmdlets failed for every piped object, |
|
||||
and `Get-NTFSEffectiveAccess` warned for names of this computer. One |
|
||||
`security-reviewer` pass (no Blocker or Major; its findings fixed but |
|
||||
one, declined). Suite and lab acceptance in `activeContext.md`. |
|
||||
- 2026-10-08: #115 merged (`b51d970`) and tagged `5.0.0-rc6`. The Release |
|
||||
job published the package at 20:40 UTC, then failed: `Publish-PSResource` |
|
||||
gave up waiting after 100 seconds while the Gallery accepted the upload, |
|
||||
and its retry got 409, so the job didn't create the GitHub release. The |
|
||||
published package passed the live tests of rc7 in both editions except |
|
||||
the one test whose expected warning text rc7 changed |
|
||||
(`Tests/Lab/Acceptance-2026-10-08-5.0.0-rc6.md`, After the release). |
|
||||
#116 (5.0.0-rc7) was opened on the rc6 branch and moved to `master`. |
|
||||
|
|
||||
## Stable capabilities |
## Stable capabilities |
||||
|
|
||||
- 36 cmdlets: access (7), audit (5), inheritance (6), owner and security |
- 36 cmdlets: access, audit, inheritance, owners/descriptors, privileges, |
||||
descriptor (4), privileges (3), long-path items (6), links, hash, and |
long-path items, links, hash, and disk space. |
||||
disk space (5). |
- Windows PowerShell 5.1 and PowerShell 7; RIPEMD160 and MACTripleDES are |
||||
- Works in Windows PowerShell 5.1 and PowerShell 7. In PowerShell 7, |
available only in Desktop. Both editions run elevated/basic-user in CI. |
||||
`Get-FileHash2` lacks `RIPEMD160` and `MACTripleDES`, which .NET lacks. |
- Pester fixtures use `Tests/TestHelpers.psm1` TEMP sandboxes. Live tests |
||||
- Pester tests in `Tests\` run in `$env:TEMP` sandboxes through |
are excluded from CI and run only on approved lab client/server targets. |
||||
`Tests\TestHelpers.psm1`; tests that need privileges skip without them |
|
||||
and run in CI, whose runners are elevated. |
|
||||
|
|
||||
## Open work |
## Open work |
||||
|
|
||||
1. Quality gate before 5.0.0 (Decision 21): the maintainer reruns the |
1. Decision 21 gate: review Decision 22, integrate reviewed quality-gate |
||||
failed Release job of 5.0.0-rc6, which creates the GitHub release; |
follow-up, publish the next candidate, and test the published package. |
||||
reviews the choices of Decision 22 in #116; merges #116 and tags |
Do not release 5.0.0 until the remaining-path and OS-matrix gates close. |
||||
5.0.0-rc7, whose published package then runs the live tests. Phase 3 |
Release steps: `Docs/Contributing/05-Releasing.md`; remove prerelease |
||||
runs the live tests on more operating systems. Then release 5.0.0 |
label, date `[5.0.0]`, update `$publishedVersions`, tag through CI. |
||||
through CI (Decision 12): remove the label, date |
2. Issues: #110's seven items were addressed by rc6, but #115 deliberately |
||||
`[Unreleased]` as `[5.0.0]`, add the last prerelease to |
used no closing keyword. #34 stays open for non-Windows owner feedback |
||||
`$publishedVersions`, and tag `5.0.0` (steps in |
or maintainer acceptance. #16, #21, #45, #89 await reporters. #68 tracks |
||||
`Docs/Contributing/05-Releasing.md`). #34 stays open with Bug and Help |
ShouldProcess for security cmdlets; enhancements #22/#49/#68/#77/#87 |
||||
Wanted until a tester with a file server that refuses the owner |
are not planned for 5.0.0. Labels follow Decision 17. |
||||
confirms the fix, or until 5.0.0 ships. |
3. Deferred reviews (not silently accepted): rc3 extra DACL read/SDDL |
||||
2. Issues: 5.0.0-rc6 addresses the seven items of #110 (tests); #115 |
snapshots/duplicate SACL check; rc4 findings listed in #113, including |
||||
named it without a closing keyword, so the maintainer closes it now. |
library-only RemoveAll account filters; rc5 unchecked Authz errors and |
||||
#21 (a misleading error of `Move-Item2`) got |
lab-controller hardening; rc6 failed privilege-disable retry (not |
||||
a fix in rc6 that names the missing destination folder; the folder |
reproduced); rc7 audit missing-path error IDs declined in Decision 22. |
||||
moves to another volume that rc7 fixes are a different defect. #68 |
4. Architecture/cmdlet design: Decision 22 remains proposed; two link |
||||
tracks `-WhatIf` and `-Confirm` for every cmdlet that changes security. |
changes are breaking. Keep unused classes/helper overloads until a |
||||
The labels follow Decision 17; #16, #21, #45, and #89 wait for their |
maintainer decision; do not remove them to improve coverage percentages. |
||||
reporters (Needs Info). Not planned for 5.0.0: the enhancements #22, |
5. ARM64 workstation: PowerShell 7.6.1 crashed under x64 emulation without |
||||
#49, #68, #77, #87. |
module frames; native-x64 CI did not reproduce it. |
||||
3. Review findings, not filed: of rc3, an extra DACL read and four SDDL |
6. Optional maintainer cleanup: obsolete AppVeyor/Read the Docs access, |
||||
snapshots on read paths, and a duplicate SACL check; of rc4, R3 to R5, |
wiki editing restrictions, `test/transfer`, and old lab checkpoints |
||||
R7, and five older defects, listed in the description of #113, among |
when no longer needed. No remote changes or snapshot restores here. |
||||
them the accounts filter that `RemoveFileSystemAccessRuleAll` and |
7. Fresh coverage inventory at `3442194`: 918 unvisited sequence points. |
||||
`RemoveFileSystemAuditRuleAll` ignore, which no cmdlet passes; of rc5, |
Of these, 244 are in classes unused by cmdlets and 112 in parameter |
||||
the bare `catch` in `Win32.GetEffectiveAccess`, the unchecked |
getters; 562 remain for finer review/testing, including unused overloads, |
||||
`AUTHZ_ACCESS_REPLY.Error`, and hardening of the lab controller (guards |
defensive/native failures, and environment-specific branches. High-value |
||||
in the setup blocks, interpolated `-EncodedCommand` paths, CredSSP by |
local gaps closed: folders/Force/DeleteError, RestoreOwnerError, all |
||||
IP address, the password string in memory, disabling the role accounts |
scopes, file/folder inheritance, enumeration/depth/link skipping, |
||||
after a run); of rc6, a privilege that fails to be disabled isn't tried |
descriptor write failures, and forced file replacement. Remaining |
||||
again by `Dispose` (finding 2, not reproducible); of rc7, one error ID |
candidates: audit ownership-retry failures, SD inheritance edge cases, |
||||
for a missing path in the audit cmdlets (declined, Decision 22). |
effective-access unresolved identity, recursive denial/error surfaces, |
||||
4. Behavior changes found in Phase 2 (Decision 16): decided in Decision 22 |
output-object comparisons/formatting. A conditional ACE display remains |
||||
as assumptions for the maintainer's review, on `ai/release-5.0.0-rc7`; |
a .NET representation limit, not evidence of unconditional permissions. |
||||
two of them are breaking changes of the link cmdlets. Left for Phase 3: |
8. Publication recovery is implemented locally in `95b827e`, with 14 offline |
||||
400 points of code that nothing calls besides the 244 lines of unused |
tests and exact artifact SHA-512 verification. Original upload errors |
||||
classes. |
remain errors for missing/different/unverifiable outcomes. Not deployed |
||||
5. `pwsh` 7.6.1 crashed three times during test runs on the ARM64 |
until the maintainer merges/pushes; no publication was performed here. |
||||
workstation (x64 emulation), without module frames; none of the CI runs |
9. Phase 3: choose OS scope (proposed Windows 11 client/2019/2022 servers), |
||||
on native x64 on 2026-10-05 crashed. |
detect ISO editions, provision without repurposing shared VMs, then run |
||||
6. Optional for the maintainer: delete the AppVeyor project and revoke its |
published-package acceptance. #34 has no new reply since 2026-10-06. |
||||
GitHub authorization, restrict wiki editing to collaborators, ask |
10. Lab rollback evidence: new checkpoints exist but report Standard even |
||||
`Sup3rlativ3` to delete the Read the Docs project, and delete the branch |
after a successful temporary ProductionOnly probe. Classification is |
||||
`test/transfer`. In the lab, delete the checkpoints |
unresolved; original VM policy restored, no checkpoint restored. Do |
||||
`ntfs-rc6-*-before-acceptance` and `ntfs-rc7-*-before-acceptance` of the |
not represent these as verified Production snapshots. |
||||
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. |
|
||||
8. The publish step of the Release job fails when `Publish-PSResource` |
|
||||
gives up waiting after 100 seconds while the Gallery accepts the |
|
||||
package, because its retry gets 409 (5.0.0-rc6). Proposed for the |
|
||||
maintainer (Decision 16, not reproducible on demand; he was asked on |
|
||||
2026-10-08 and didn't answer, so it stays open): treat the error as |
|
||||
success when `Find-PSResource` then lists the version, in a script with |
|
||||
Pester tests. Until then, rerun the failed job. |
|
||||
|
|||||
@ -1,251 +1,156 @@ |
|||||
--- |
--- |
||||
status: current |
status: current |
||||
last-verified: 2026-10-08 |
last-verified: 2026-10-09 |
||||
owner: active-agent |
owner: active-agent |
||||
source: repository evidence |
source: repository and executable evidence |
||||
--- |
--- |
||||
|
|
||||
# Tech context |
# Tech context |
||||
|
|
||||
## Stack |
## Stack |
||||
|
|
||||
- C# class libraries, old-style `.csproj`, .NET Framework 4.5.2, |
- Legacy C# projects, .NET Framework 4.5.2, `NTFSSecurity.sln`. |
||||
solution `NTFSSecurity.sln` (Visual Studio 2017 format). |
Cmdlets depend on Security2, PrivilegeControl/ProcessPrivileges, and |
||||
- Projects: `NTFSSecurity` (cmdlets), `Security2` (ACL object model, Win32 |
AlphaFS 2.2.x. System.Management.Automation reference: 10.0.10586.0. |
||||
interop), `PrivilegeControl` and `ProcessPrivileges` (token privileges), |
- Module supports Windows PowerShell 5.1 and PowerShell 7; 36 cmdlets. |
||||
`Log`, `TestClient`, `NTFSSecurityTest` (MSTest, minimal coverage). |
Manifest initializes helper assemblies, aliases, type data, formatting, |
||||
- NuGet (`packages.config`): AlphaFS 2.2.x for long paths; |
and committed help generated from `Docs/Cmdlets` (platyPS 0.14/schema 2). |
||||
`System.Management.Automation.dll` 10.0.10586.0. For a drive or volume |
- CI: `.github/workflows/ci.yml`, scripts in `.github/scripts`; GitHub |
||||
root, AlphaFS `DirectoryInfo` reaches the device object, while |
renders Docs and publishes a generated wiki. No separate docs site. |
||||
`Directory.Get/SetAccessControl('C:\')` reaches the root folder (#41). |
|
||||
- Module: `NTFSSecurity.psd1` loads `NTFSSecurity.psm1` (aliases `dir2`, |
|
||||
`gi2`, `rm2`, `del2`), `NTFSSecurity.Init.ps1` (Add-Type of the helper |
|
||||
assemblies, prepends `NTFSSecurity.format.ps1xml`), and `NTFSSecurity.dll`. |
|
||||
- Documentation: Markdown in `Docs` and `README.md`, rendered by GitHub and |
|
||||
published to the wiki by CI; no documentation site (Decisions 9 and 11). |
|
||||
Cmdlet pages are platyPS 0.14 markdown (schema 2.0.0) in `Docs/Cmdlets`. |
|
||||
- Help: `NTFSSecurity\en-US\NTFSSecurity.dll-Help.xml`, generated from |
|
||||
`Docs/Cmdlets` and committed (Decision 8). |
|
||||
- Tests: Pester 5 in `Tests`, one file per area, against the Release |
|
||||
build; `Wiki.Tests.ps1` (wiki conversion) runs without a build. |
|
||||
- CI: GitHub Actions, `.github/workflows/ci.yml` with the scripts in |
|
||||
`.github/scripts` (Decision 11). |
|
||||
|
|
||||
## Environment |
## Current environment |
||||
|
|
||||
- Windows only (NTFS, Win32 security APIs). |
- Host `ExHost`: Windows Server 2025 VM, native x64, elevated agent; |
||||
- The Debug build writes straight into |
repository `V:\Git\NTFSSecurity`. AutomatedLab 5.61.704, Hyper-V, |
||||
`C:\Program Files\WindowsPowerShell\Modules\NTFSSecurity\`. |
approved lab `WindowsAccessControlLab` (Decision 20). |
||||
- No Visual Studio MSBuild or .NET Framework targeting pack on the |
- Build Release only: Debug writes to Program Files. Native .NET Framework |
||||
workstation. A local build works with the .NET Framework MSBuild |
MSBuild plus Roslyn `Microsoft.Net.Compilers` 4.2.0 and .NET 4.5.2 |
||||
(`%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe`) plus |
reference assemblies work; legacy compiler fails CS0136, dotnet MSBuild |
||||
`/p:CscToolPath` to the Roslyn `csc.exe` of the `Microsoft.Net.Compilers` |
fails binary resources MSB3822/MSB3823. Build packages are already cached |
||||
package; the legacy C# 5 compiler fails with CS0136. `dotnet msbuild` |
in `packages`; compiler/tools are under TEMP `ntfs-build`. |
||||
fails on the binary resources in `Resources.resx` (MSB3822, MSB3823). |
- Pester 5.7.1 is in |
||||
- platyPS 0.14.2, Pester 5.7.1, PSScriptAnalyzer, and powershell-yaml are |
`V:\Git\WindowsAccessControl\output\RequiredModules\Pester\5.7.1`. |
||||
installed only for PowerShell 7. Windows PowerShell 5.1, started from |
platyPS 0.14.2 and MarkdownLinkCheck 0.2.0 are under TEMP `ntfs-docs-tools`. |
||||
PowerShell 7, imports platyPS and Pester by full path |
PSScriptAnalyzer and PSResourceGet are available in PowerShell 7. |
||||
(`~\OneDrive\Documents\PowerShell\Modules\platyPS\0.14.2`, |
- Use Desktop's module paths in Desktop children, not inherited Core-only |
||||
`C:\Program Files\PowerShell\Modules\Pester\5.7.1`). Leave |
paths. Never import NTFSSecurity in the agent shell; every package/build |
||||
`$env:PSModulePath` alone: PowerShell 7 hands the child the Windows |
runs in a new process. Current prereleases share assembly version 5.0.0.0. |
||||
PowerShell default path, and clearing it leaves Windows PowerShell without |
- GitHub CLI: `C:\Program Files\GitHub CLI\gh.exe`, signed in as raandree. |
||||
its core modules (Pester fails: `Add-Member` not found). |
Read-only queries work; remote mutations belong to the maintainer. |
||||
- MarkdownLinkCheck is not installed, and `Save-Module` crashed (FailFast) |
- LabSources: `V:\LabSources`. All 13 deployed machines are Server 2025. |
||||
in PowerShell 7.6 on 2026-10-04. Download the 0.2.0 package from |
Windows 11 consumer/enterprise-evaluation media and Server 2019/2022 |
||||
`https://www.powershellgallery.com/api/v2/package/MarkdownLinkCheck/0.2.0` |
ISO files exist. OS cache is empty; exact detected editions are not yet |
||||
into `$env:TEMP`, extract it, and import it by path. |
verified. Do not equate present media with a deployed/tested OS matrix. |
||||
- The first workstation is ARM64; PowerShell 7 runs as x64 under emulation. |
|
||||
- The NuGet cache (`~\.nuget\packages`) holds every build dependency: copy |
|
||||
`alphafs\2.2.1`, `system.management.automation.dll\10.0.10586`, and |
|
||||
`microsoft.netframework.referenceassemblies.net452\1.0.3` into |
|
||||
`packages\<Id>.<Version>`, and point `CscToolPath` at |
|
||||
`microsoft.net.compilers\4.2.0\tools`. |
|
||||
- The second workstation (x64, used since 2026-10-05) runs the agent |
|
||||
session elevated, so the tests that need privileges run there as in CI. |
|
||||
It has no NuGet cache with these packages: download each from |
|
||||
`https://api.nuget.org/v3-flatcontainer/<id>/<version>/<id>.<version>.nupkg`, |
|
||||
extract the first three into `packages\<Id>.<Version>` and the compilers |
|
||||
into `$env:TEMP`; Pester 5.7.1 comes from the Gallery package API the |
|
||||
same way, its folder first on `$env:PSModulePath` of the test process. |
|
||||
The GitHub CLI is in `C:\Program Files\GitHub CLI`, outside the PATH of |
|
||||
sessions started before its installation. |
|
||||
- The third workstation (`ExHost`, a Windows Server 2025 VM, x64, used since |
|
||||
2026-10-07) runs the agent session elevated and hosts the AutomatedLab lab |
|
||||
`WindowsAccessControlLab` (Decision 20) with Hyper-V and AutomatedLab |
|
||||
5.61.704. It has no NuGet cache or platyPS: check each |
|
||||
nuget.org package against the SHA-512 `packageHash` of its catalog entry |
|
||||
(`https://api.nuget.org/v3/registration5-semver1/<id>/<version>.json`, |
|
||||
then `catalogEntry`), and each Gallery package against `PackageHash` of |
|
||||
`api/v2/Packages(Id='<id>',Version='<version>')`. Pester 5.7.1 is in |
|
||||
`V:\Git\WindowsAccessControl\output\RequiredModules`. The GitHub CLI |
|
||||
2.102.0 is in `C:\Program Files\GitHub CLI`, outside the PATH, and signed |
|
||||
in as `raandree` since 2026-10-08; `Block-RemoteMutation` denies its |
|
||||
mutating commands, so the agent uses it read-only. The lab domains |
|
||||
`a.forest1.net` and `b.forest1.net` had a maximum password age of 42 |
|
||||
days, so the password of `install` expired on 2026-09-15 and AutomatedLab |
|
||||
got access denied; it never expires since 2026-10-07, as in |
|
||||
`forest1.net`. |
|
||||
|
|
||||
## Constraints |
## Constraints |
||||
|
|
||||
- `ModuleVersion` is `5.0.0` with the prerelease label `rc6` on the branch |
- Source manifest: ModuleVersion 5.0.0, prerelease rc7 on #116/follow-up. |
||||
`ai/release-5.0.0-rc6` (`rc5` on `master`). |
Latest stable: 4.2.6; latest published prerelease: rc6 (2026-10-08). |
||||
The latest stable tag and Gallery release is `4.2.6`. The manifest |
GitHub rc6 release recovered 2026-10-09. rc7 publication is pending. |
||||
requires PowerShell 5.1 and .NET Framework 4.5.2, uses `RootModule`, and |
- Changed-section writes preserve unchanged owner/group/DACL/SACL (19). |
||||
lists exactly 36 cmdlets; `Test-ModuleManifest` passes in Windows |
Roots use root-folder APIs, not AlphaFS device security (#41). |
||||
PowerShell 5.1 and PowerShell 7.6. |
- CHANGELOG contains user-visible changes only (7); tests and CI-only fixes |
||||
- The module source at `master` differs from tag `4.2.6` by the changes |
get no entry. No stable release until Decision 21 gates close. |
||||
that `CHANGELOG.md` lists under `[Unreleased]`, the release notes of each |
- Honor separate topic branches, no amendment, two AI co-author trailers. |
||||
5.0.0 prerelease. |
Never work around remote-mutation blocking. Provide each maintainer |
||||
- PowerShell Gallery versions (publish dates): 4.0.0 (2015-08-19), 4.2.2 |
command separately at reply end, no question dialog after commands. |
||||
(2016-05-18), 4.2.3 (2016-05-19), 4.2.4 (2018-08-13), 4.2.5 (2019-07-11), |
Issue references use no closing keyword unless closure is intended. |
||||
4.2.6 (2019-07-12), none with release notes; 5.0.0-rc1 (2026-10-04), |
- Lab passwords stay in memory and are lab-only; no secret in repository, |
||||
5.0.0-rc2 (2026-10-05), 5.0.0-rc3 and 5.0.0-rc4 (2026-10-06), 5.0.0-rc5 |
logs, or process arguments. Live ACL mutations occur only in the lab. |
||||
(2026-10-08), published |
- Existing expired installation passwords of a.forest1/b.forest1 were |
||||
by CI. Older versions were released on CodePlex only, and their dates are |
configured not to expire on 2026-10-07, matching the root domain. |
||||
lost. The git history starts on 2016-10-10, when the project moved from |
|
||||
CodePlex. |
|
||||
- Releases up to 4.2.6 were Debug builds published by hand, with the whole |
|
||||
output folder; their tags carry the previous version. From 5.0.0 on, CI |
|
||||
publishes on a version tag (Decision 12). GitHub releases attach |
|
||||
`NTFSSecurity.zip`. |
|
||||
- CI: GitHub Actions on pull requests, pushes to `master`, and version tags |
|
||||
(Decision 11); AppVeyor and Read the Docs aren't used (Decision 9). |
|
||||
- `CHANGELOG.md` lists user-visible changes only; CI and build-only changes |
|
||||
get no entry |
|
||||
([Decision 7](decisions/0007-changelog-user-visible-only.md)). |
|
||||
- Remote mutations are the maintainer's: the user-level preToolUse hook |
|
||||
`Block-RemoteMutation.ps1` denies `git push` and mutating `gh` commands |
|
||||
(`pr create`, `pr close`, and others) from the agent session, even after |
|
||||
an explicit request. Its override, `COPILOT_ATELIER_ALLOW_REMOTE=1`, is |
|
||||
read from the environment that VS Code starts the hook with; setting it |
|
||||
inside an agent command has no effect (verified 2026-10-04). The hook |
|
||||
matches the whole command text, so a commit message that quotes such a |
|
||||
command is blocked too. Prepare the commands and descriptions; the |
|
||||
maintainer runs them. Hand over each command as its own fenced code block |
|
||||
at the end of the reply, which the chat shows with a copy button, and end |
|
||||
the turn there; the maintainer reports back in the chat. The question |
|
||||
dialog joins the lines of its text, has no copy button, and covers the |
|
||||
reply before it (maintainer, 2026-10-06). A long question also hides its |
|
||||
choices, so that it can't be answered: keep it to a few short sentences |
|
||||
(2026-10-07). A pull request description |
|
||||
names an issue without a closing keyword (fixes, closes, resolves) unless |
|
||||
the merge should close it: "fixes #34" in #112 closed #34. Simulated `gh` |
|
||||
commands in offline tests must print what the real ones print, such as |
|
||||
the URL of a new comment. |
|
||||
|
|
||||
## Validation |
## Build and focused checks |
||||
|
|
||||
- CI (`.github/workflows/ci.yml`): job `build` on `windows-2025` installs |
- Build `NTFSSecurity\NTFSSecurity.csproj` with Configuration=Release, |
||||
platyPS 0.14.2, MarkdownLinkCheck 0.2.0, and Pester 5.7.1 for all users, |
Framework MSBuild, TargetFrameworkRootPath/FrameworkPathOverride to |
||||
restores `packages.config` per project plus |
`packages\Microsoft.NETFramework.ReferenceAssemblies.net452.1.0.3\build`, |
||||
`Microsoft.NETFramework.ReferenceAssemblies.net452` 1.0.3, builds |
CscToolPath to the cached compiler. Expected legacy CS1591/CS0618 warnings |
||||
`NTFSSecurity.csproj` in Release with the MSBuild that `vswhere` finds, |
are not new failures. Never copy a mutated DLL into acceptance artifacts. |
||||
then: 01 `Update-MarkdownHelp` and fail on `git diff -- Docs/Cmdlets`; 02 |
- Pester/builds run in detached monitored child processes through |
||||
`Get-MarkdownLink -BrokenOnly`; 03 regenerate the help file and fail on |
`Start-DetachedPowerShell.ps1`; use unique TEMP logs/result paths and an |
||||
`git status --porcelain -- NTFSSecurity/en-US`; 04 `Invoke-Tests.ps1` in |
explicit-PID watcher. No foreground sleep/poll loop. Long payloads use |
||||
Windows PowerShell 5.1 and in PowerShell 7, then |
a script file: nested Base64 encoding can exceed Windows command limits. |
||||
`Invoke-TestsAsBasicUser.ps1` in both editions (since 5.0.0-rc6). Job |
- Focused helper: TEMP `ntfs-focused\Start-FocusedRuns.ps1`; detach that |
||||
`wiki` on `ubuntu-latest` |
driver too because its internal wait loop must not block the agent shell. |
||||
(read-only) clones the wiki (`gh auth setup-git` with the built-in token), |
- TEMP `ntfs-docs-tools\Invoke-ChangeChecks.ps1 -File <relative paths>` |
||||
runs `Export-WikiContent.ps1`, and lists the changed pages in the job |
performs AST/analyzer/lint/help checks. Absolute input paths misroute |
||||
summary; job `publish-wiki` (`contents: write`) repeats that and publishes, |
cmdlet pages. Check actual analyzer/lint output, not just helper exit. |
||||
for `master` only. After the tests, `build` runs |
- actionlint 1.7.12 checks the workflow. Script changes use AST parse and |
||||
`New-ModulePackage.ps1` and uploads the artifact `packages` (nupkg and |
PSScriptAnalyzer; prose Markdown uses MD013 and changelog siblings-only |
||||
`NTFSSecurity.zip`). Job `release` runs only for tags matching |
repeated-heading allowance. Native error codes must be checked explicitly. |
||||
`[0-9]+.[0-9]+.[0-9]+` or `[0-9]+.[0-9]+.[0-9]+-*`, in the environment |
- Documentation: run platyPS in Desktop, generate external help, rebuild, |
||||
`powershell-gallery` (secret `PSGALLERY_API_KEY`); see Decision 12. |
require an unchanged Markdown round trip. Links in Docs are checked |
||||
Actions are pinned by commit SHA: `actions/checkout` v7.0.1, |
relatively; Wiki tests cover generated anchors, not arbitrary web URLs. |
||||
`actions/upload-artifact` v7.0.1, `actions/download-artifact` v8.0.1; |
|
||||
Dependabot proposes updates weekly, one week after a release. |
## CI and packaging |
||||
- Packaging needs PSResourceGet (`Compress-PSResource`, PowerShell 7.4 or |
|
||||
later); its tests skip in Windows PowerShell. Dry run locally: run |
- CI `build` on windows-2025 installs tools, restores dependencies, builds |
||||
`New-ModulePackage.ps1` against `NTFSSecurity\bin\Release` into |
Release, round-trips pages/help, checks links, and runs the suite in |
||||
`$env:TEMP`, then extract the nupkg into a folder and import it there. |
Desktop/Core, elevated/basic user. Lab tests are explicitly excluded. |
||||
- Read CI runs with `gh run list --repo raandree/NTFSSecurity --workflow |
- `.github/scripts/Invoke-TestsAsBasicUser.ps1` launches a SAFER Normal User |
||||
ci.yml`, `gh pr checks <number>`, and `gh run view <id> --log-failed` |
token. Result paths may be absolute or repository-relative: Path.Combine |
||||
(read-only). |
then GetFullPath, not Join-Path with a rooted child. |
||||
- Workflow lint: actionlint (download the release zip into `$env:TEMP` and |
- Packaging needs Compress-PSResource (Core 7.4+). New-ModulePackage copies |
||||
check its SHA-256 against the checksum file; 1.7.12 on 2026-10-08); |
only FileList, validates the manifest, creates nupkg plus NTFSSecurity.zip. |
||||
PowerShell steps check |
Check package/file hashes and test the extracted artifact, not build extras. |
||||
`$LASTEXITCODE` after every native command, because GitHub checks only |
- Release runs only for validated version tags in powershell-gallery. |
||||
the last one. |
API key stays as PSGALLERY_API_KEY environment reference. Helper |
||||
- Run platyPS in Windows PowerShell 5.1 to avoid PowerShell 7.4+ |
Publish-ModulePackage treats only PackageNotFound as expected absence; |
||||
`-ProgressAction` noise. |
existing-version skip and uncertain-upload recovery require exact Gallery |
||||
- Placeholder check: no `{{` left in `Docs/Cmdlets/*.md`. |
SHA-512 equality. Base64 comparison is case-sensitive. Unverifiable, |
||||
- Help file: `New-ExternalHelp -Path .\Docs\Cmdlets -OutputPath |
missing, and different outcomes preserve errors. No test uploads. |
||||
.\NTFSSecurity\en-US -Force` must leave `git status` unchanged. |
- Read status through gh pr checks / gh run view --log-failed. A successful |
||||
- Pester: run detached (`Start-DetachedPowerShell.ps1`) in Windows |
Gallery upload followed by HTTP 409 does not prove its retry chronology. |
||||
PowerShell 5.1: the launcher starts `pwsh`, and its payload runs |
|
||||
`powershell.exe -NoProfile -EncodedCommand` with Pester imported by full |
## Coverage and test eligibility |
||||
path. A run without `bin\Release\en-US` must fail. |
|
||||
- Tests that run only without a privilege skip in an elevated session. |
- AltCover 9.0.145 net472 instruments a copied Release build with PDBs, |
||||
`.github\scripts\Invoke-TestsAsBasicUser.ps1` runs the suite from an |
OpenCover format, localSource, excluding AlphaFS/System.Management.Automation. |
||||
elevated session with a token of the SAFER level Normal User, like |
Do not use --save: collection previously retained only one process's hits. |
||||
`runas /trustlevel:0x20000`, and CI runs it in both editions. For a |
- Freeze a git worktree, instrument its NTFSSecurity\bin\Release, run all |
||||
single file, `runas /trustlevel:0x20000` works too; give Windows |
four configurations sequentially with the real CI wrappers, then |
||||
PowerShell its own `PSModulePath`, and note that `runas` returns at once, |
AltCover runner --collect recalculates the report. Compute option paths |
||||
so the script it starts writes its own log. Both tokens hold only the |
before passing native arguments, not inline Join-Path expressions. |
||||
privilege to bypass traverse checking. |
- Report sequence points, not unique source lines. Four-run baselines: |
||||
Pester reports a skipped `-ForEach` test under its template name, such as |
rc5 2,020/3,476 (58.1%), branches 711/1,873 (38.0%); |
||||
`<_> should ...`, and a test that ran under the expanded name: compare |
rc6 2,412/3,540 (68.14%), branches 850/1,918 (44.32%); |
||||
runs by template. |
follow-up `3442194` 2,641/3,559 (74.21%), 974/1,933 (50.39%). |
||||
- C# coverage (Decision 21): AltCover 9.0.145 (`tools\net472\AltCover.exe` |
NTFSSecurity assembly: 1,769/2,099 (84.28%). Different code changes |
||||
of the nuget.org package) instruments a copy of the local Release build, |
denominators; never present these as same-source incremental percentages. |
||||
which has the PDB files that the published package lacks: |
- Final suite: 914 per configuration, zero failures. Passed/skipped: |
||||
`--reportFormat=OpenCover`, AlphaFS and `System.Management.Automation` |
elevated Desktop 890/24, Core 860/54; basic Desktop 749/165, Core 719/195. |
||||
excluded with `--assemblyFilter`, and no `--save`: then every process |
- NUnit skipped ForEach names retain placeholders and parameter tuples, |
||||
writes its hits into the report when it exits. With `--save`, each |
executed names expand them. Strip trailing data tuples and match templates; |
||||
process writes a recorder file, and `runner --collect` keeps only the |
raw-name intersection or positional alignment is invalid across editions. |
||||
first one (verified 2026-10-08), so the numbers measured that way held |
139 skipped templates have eligible executed counterparts. Inspect input |
||||
only the main process of the elevated Windows PowerShell run. Put the |
eligibility when an individual data row has a condition of its own. |
||||
instrumented module in `NTFSSecurity\bin\Release` of a `git worktree`, |
- Remaining inventory: 918 points, including 244 in cmdlet-unused classes, |
||||
run `.github\scripts\Invoke-Tests.ps1` elevated and |
112 parameter-getter points, and 562 awaiting finer classification/testing. |
||||
`Invoke-TestsAsBasicUser.ps1` in both editions, then |
Preserve raw XML, eligibility CSV, logs, commit identity, and build hashes. |
||||
`AltCover.exe runner --collect --recorderDirectory=<the instrumented |
|
||||
folder>`, which recalculates the summary of the report from the hits. |
## Lab acceptance |
||||
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 |
- Defaults: F1ADC1 (domain), F1AFile2 (server), F1AFile1 (client), all in |
||||
244 lines in classes that no cmdlet calls; the rc6 candidate (`1b9edbb`) |
a.forest1.net. Foreign accounts use F1BDC1, F2DC1, F3DC1 and existing trusts. |
||||
68.1% of the lines (2,412 of 3,540) and 44.3% of the branches (850 of |
Controller accepts alternate machines; changing topology/OS scope waits |
||||
1,918), 73.2% without those classes, the `NTFSSecurity` assembly 78.1%. |
for a maintainer decision. Do not repurpose another project's shared VMs. |
||||
The earlier figures, 55.9% for rc5 and 65.6% for rc6, used `--save`. |
- Before a run: authenticated WinRM, LDAP RootDSE, Kerberos tickets, member |
||||
- Live tests (Decision 20): in an elevated Windows PowerShell 5.1 session |
secure channels, clocks; checkpoint only approved targets. Inspect actual |
||||
on the lab host, `Tests\Lab\Invoke-NTFSSecurityLabTest.ps1` with |
checkpoint kind: new checkpoints reported Standard even after a successful |
||||
`-Version` for Gallery packages or `-ModulePath` for a build; it writes |
temporary ProductionOnly request. Policy restored; no rollback performed; |
||||
the results to `$env:TEMP\NTFSSecurityLab\Results`. A run of two versions |
Production classification remains unverified, not a passed safety check. |
||||
in both editions takes about 30 minutes; `-RemoveFixture` removes its |
- Run Tests\Lab\Invoke-NTFSSecurityLabTest.ps1 in elevated Desktop with |
||||
accounts, share, and folders from the lab. For a check on the client as |
-Version for hash-checked Gallery packages or -ModulePath for the extracted |
||||
an account without administrator rights, use `NtfsLiveServerAdmin` |
build artifact, both editions. Per version/edition: Delegate, ServerAdmin, |
||||
(Remote Management Users on the client, CredSSP by IP address like the |
Admin on client, then Server independently checks persisted state. |
||||
controller): reset its password on the PDC emulator to a random value |
- Controller writes Summary.json even when tests fail: validate every role, |
||||
in memory; the next run of the controller sets a new one anyway. |
exit code, failure name, and total; DONE alone is not acceptance evidence. |
||||
- Lab acceptance of a candidate (modeled on the WindowsAccessControl |
Desktop ConvertFrom-Json can wrap arrays; explicitly enumerate the result |
||||
handoff 07): build once, package it with `New-ModulePackage.ps1`, and |
and compare full Describe-prefixed names. Never gate cleanup on the global |
||||
record the SHA-256 of the packages and module files; check WinRM, LDAP |
Error.Count, which includes handled errors; independently verify footprint. |
||||
(RootDSE), Kerberos (`klist get`), the secure channel, and the clock of |
- Remote Authz answers administrators and Access Control Assistance |
||||
the six VMs; take a Production checkpoint named |
Operators (S-1-5-32-579); other accounts get access denied. Check firewall |
||||
`ntfs-<label>-<commit>-before-acceptance` of `F1ADC1`, `F1BDC1`, |
when remote resource-manager RPC fails. Expected rights use S4U tokens. |
||||
`F2DC1`, `F3DC1`, `F1AFile1`, and `F1AFile2`; run the controller with |
- RemoveFixture after the run; verify OUs/accounts, share, folders, local |
||||
`-ModulePath` of the extracted `NTFSSecurity.zip` in both editions; then |
memberships, and test profiles removed. Credentials must never be printed. |
||||
`-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 |
|
||||
(tables, code, and headings excluded) on the conceptual pages; for |
|
||||
`CHANGELOG.md` also `MD024` with `siblings_only: true`, because every |
|
||||
version repeats the category headings. |
|
||||
- Gallery packages: download |
|
||||
`https://www.powershellgallery.com/api/v2/package/NTFSSecurity/<version>` |
|
||||
into `$env:TEMP` and extract it; dates come from the OData endpoint |
|
||||
`api/v2/FindPackagesById()?id='NTFSSecurity'`. Import each version in its |
|
||||
own process: every version's `NTFSSecurity.dll` has assembly version |
|
||||
4.2.1.0, so a second version in the same process reuses the first DLL. |
|
||||
- YAML: `ConvertFrom-Yaml` (powershell-yaml) on `.github/workflows/ci.yml`. |
|
||||
- Links: the CI step 02 (MarkdownLinkCheck 0.2.0) checks only relative |
|
||||
links in `Docs`; it strips anchors and skips absolute URLs. |
|
||||
`Wiki.Tests.ps1` checks the wiki links with their anchors; check the |
|
||||
links in `README.md` and `CHANGELOG.md` with a script. |
|
||||
|
|||||
Loading…
Reference in new issue