diff --git a/.memory-bank/activeContext.md b/.memory-bank/activeContext.md index 11abddf..e7da3ec 100644 --- a/.memory-bank/activeContext.md +++ b/.memory-bank/activeContext.md @@ -9,37 +9,30 @@ source: current task evidence ## Current focus -5.0.0-rc3, before 5.0.0 (maintainer decision of 2026-10-06): the access and -audit cmdlets read and write only the sections of the security descriptor -that they change, which fixes #34 and the copied inherited entries, and #67 -is reproduced and fixed or explained. NTFSSecurity will be archived soon; -the README and the docs point users to WindowsAccessControl (Decision 18). -The maintainer has a handoff for rc3, outside the repository. +5.0.0-rc3 is released and recorded. Next is 5.0.0, when the maintainer +decides; then the repository is archived in favor of WindowsAccessControl +(Decision 18). Issue #34 is open with Bug and Help Wanted and waits for a +tester with a file server that refuses the owner; #67 is closed as not +planned. ## Evidence -- #34 reproduces locally with 5.0.0-rc2 (2026-10-06): on a file owned by - `NT SERVICE\TrustedInstaller`, with `EnablePrivileges = $false`, - `Add-NTFSAccess` fails with "(1307) This security ID may not be assigned - as the owner of this object" (`AddAceError`), because it writes the - unchanged owner back; `icacls /grant` and `Remove-NTFSAccess`, which - write only the DACL, succeed, and with the Restore privilege enabled - `Add-NTFSAccess` succeeds. A test can therefore run in CI without a file - server. -- Elevated, `Add-NTFSAccess` and `Add-NTFSAudit` read the DACL together - with the SACL. For a DACL without the auto-inherit flag, Windows then - returns the inherited entries without their inherited flag, and the - write stores them as explicit copies (found 2026-10-05). -- `new FileSystemSecurity2(item)` reads all sections it can, and `Write()` - writes what the descriptor holds. Callers that write: adding access or - audit entries, removing all entries of an account, and - `Set-NTFSSecurityDescriptor` for a descriptor from - `Get-NTFSSecurityDescriptor`. Removing a single entry and the inheritance - cmdlets already read and write one section. -- 5.0.0-rc2 is published (2026-10-05); CI on `master` passed; the issues - are answered, labeled (Decision 17), and tracked as #107 to #111. +- 2026-10-06: the tag `5.0.0-rc3` on `914e8da`, the merge commit of #112, + published the prerelease to the PowerShell Gallery and to GitHub. The + Gallery package and `NTFSSecurity.zip` hold identical module files and + import as 5.0.0-rc3 in both editions; CI passed for #112 and on `master`. +- The replies to #34 and #67 are posted. The merge of #112 closed #34, + because the PR description said "fixes #34"; the maintainer reopened it. +- The cmdlets write only the sections that they change (Decision 19); the + manifest `Description` announces the archive (Decision 18). +- Hand commands to the maintainer as fenced code blocks at the end of the + reply, and end the turn there; never put them in the question dialog, + which also covers a reply before it. A pull request names an issue + without a closing keyword unless the merge should close it (techContext). + A handoff outside the repository fixes the hand-over in the user-level + Customizations. ## Next step -Implement 5.0.0-rc3 test-first on a topic branch, starting with a failing -test for #34 that uses the reproduction above. +Before 5.0.0, read #34 for feedback from a tester. Then release 5.0.0 as +`progress.md` describes. diff --git a/.memory-bank/decisions/0018-archive-for-windowsaccesscontrol.md b/.memory-bank/decisions/0018-archive-for-windowsaccesscontrol.md index 77eaabf..2efcc8c 100644 --- a/.memory-bank/decisions/0018-archive-for-windowsaccesscontrol.md +++ b/.memory-bank/decisions/0018-archive-for-windowsaccesscontrol.md @@ -11,8 +11,11 @@ source: maintainer decision of 2026-10-06 - Choice: The repository will be archived soon, and its users move to [WindowsAccessControl](https://github.com/raandree/WindowsAccessControl), which is on the PowerShell Gallery. The README, the documentation home - (also the wiki home), and the `Deprecated` section of the changelog say - so; keep these notes until the repository is archived. + (also the wiki home), the `Deprecated` section of the changelog, and, + since 5.0.0-rc3, the manifest `Description`, which the PowerShell Gallery + shows, say so; keep these notes until the repository is archived. The + module writes no warning on import, which would reach every script and + scheduled task (maintainer, 2026-10-06). - Before the archive: 5.0.0-rc3 for #34, #67, and the copied inherited - entries, then 5.0.0. The maintainer decided on 2026-10-06 to publish rc3 - before 5.0.0. + entries, published on 2026-10-06, then 5.0.0. The maintainer decided on + 2026-10-06 to publish rc3 before 5.0.0. diff --git a/.memory-bank/decisions/0019-write-only-changed-sections.md b/.memory-bank/decisions/0019-write-only-changed-sections.md new file mode 100644 index 0000000..d6a826a --- /dev/null +++ b/.memory-bank/decisions/0019-write-only-changed-sections.md @@ -0,0 +1,30 @@ +--- +status: accepted +date: 2026-10-06 +last-verified: 2026-10-06 +owner: shared +source: maintainer decisions of 2026-10-06 for 5.0.0-rc3 (#112) +--- + +# Decision 19: Cmdlets write only the sections that they change + +- Choice: A cmdlet that changes a file or folder reads and writes only the + section of the security descriptor that it changes, and names that + section in the write: the access and access inheritance cmdlets the + DACL, the audit cmdlets the SACL. `Set-NTFSSecurityDescriptor` writes + only the sections that changed since the descriptor was read or last + written; a descriptor without changes writes nothing, and `-Verbose` + names the sections. When the descriptor of `Get-NTFSSecurityDescriptor` + includes the SACL, it reads the DACL in a separate call. `Clear-NTFSAudit` + reports an error without the Security privilege, like the other audit + cmdlets. +- Rationale: For a DACL without the auto-inherit flag, Windows returns the + owner and the group even when only the DACL is read, and writing every + section of the descriptor writes the owner back. Where the account may not + assign that owner, that fails with error 1307 (#34). Read together with + the SACL, such a DACL loses the inherited flag of its entries when the + parent folder has no SACL, and writing it back stored them as explicit + copies. +- Rejected: writing every section in turn and ignoring the errors, the + approach of the branch `fix/#34` (2023). +- Applied: 5.0.0-rc3, #112. diff --git a/.memory-bank/progress.md b/.memory-bank/progress.md index 0f97a2f..3556766 100644 --- a/.memory-bank/progress.md +++ b/.memory-bank/progress.md @@ -9,12 +9,13 @@ source: repository evidence ## Current status -5.0.0-rc2 is on the PowerShell Gallery and in the GitHub releases, -published by CI from the tag `5.0.0-rc2` on `master` (`7ddda8d`) on -2026-10-05 (Decision 12). It contains the 24 code defects of work package -5, the issue fixes of the overnight run of 2026-10-04/05, and the CI fix -`629f4e7`. The stable Gallery version is still 4.2.6. NTFSSecurity will be -archived soon; its users move to WindowsAccessControl (Decision 18). +5.0.0-rc3 is on the PowerShell Gallery and in the GitHub releases, +published by CI from the tag `5.0.0-rc3` on `master` (`914e8da`, the merge +of #112) on 2026-10-06 (Decision 12). It adds to 5.0.0-rc2 the fix of #34 +and of the copied inherited entries: the cmdlets write only the sections +that they change (Decision 19). The stable Gallery version is still 4.2.6. +NTFSSecurity will be archived soon; its users move to WindowsAccessControl +(Decision 18). ## Recent milestones @@ -42,6 +43,13 @@ archived soon; its users move to WindowsAccessControl (Decision 18). decided to publish 5.0.0-rc3 before 5.0.0 and to archive the project in favor of WindowsAccessControl (Decision 18); the README, the docs home, and the changelog announce it. +- 2026-10-06: 5.0.0-rc3 (#112): the access and audit cmdlets write only + the section that they change, which fixes #34 and the inherited entries + that elevated sessions copied as explicit ones (Decision 19). #67 has its + cause outside the module (a share root over UNC can't re-inherit), is + explained in `Docs/FAQ.md`, and was closed as not planned. One + `security-reviewer` pass approved the branch. The PR description said + "fixes #34", so the merge closed #34; it was reopened for a tester. ## Stable capabilities @@ -56,30 +64,32 @@ archived soon; its users move to WindowsAccessControl (Decision 18). ## Open work -1. 5.0.0-rc3 first (maintainer decision of 2026-10-06): #34 and #67. Every - section of the security descriptor is read and written, so the owner - and group are written with each change, and in an elevated session - inherited entries are copied as explicit ones. #34 reproduces locally - (owner `TrustedInstaller`, no Restore privilege), so CI can test the - fix; #67 needs an SMB share. `fix/#34` swallows every error and needs a - redo. For the release: set the label `rc3` and add `5.0.0-rc2` to - `$publishedVersions` in `Tests/Repository.Tests.ps1`. -2. Then release 5.0.0 through CI (Decision 12): remove the label, date - `[Unreleased]` as `[5.0.0]`, add `5.0.0-rc3` to `$publishedVersions`, - and tag `5.0.0` (steps in `Docs/Contributing/05-Releasing.md`). -3. Issues: the open issues got their replies on 2026-10-05. Follow-up +1. Release 5.0.0 through CI (Decision 12) when the maintainer decides: + remove the label, date `[Unreleased]` as `[5.0.0]`, add `5.0.0-rc3` to + `$publishedVersions`, and tag `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 the owner + confirms the fix, or until 5.0.0 ships. +2. Issues: the open issues got their replies on 2026-10-05. Follow-up issues for the open Minor review findings: #107 (relative path forms), #108 (`Copy-Item2` and `Move-Item2`), #109 (error messages), #110 (tests), and #111 (small items); #68 tracks `-WhatIf` and `-Confirm` for - every cmdlet that changes security, and #34 the copied inherited - entries. The labels follow Decision 17; #16, #21, #45, #67, and #89 - wait for their reporters (Needs Info). Not planned for 5.0.0: #41 (a - drive root reads the device object), #90 (a trailing space in a folder - name), and the enhancements #22, #49, #68, #77, #87. + every cmdlet that changes security. The labels follow Decision 17; #16, + #21, #45, and #89 wait for their reporters (Needs Info). Not planned for + 5.0.0: #41 (a drive root reads the device object), #90 (a trailing space + in a folder name), and the enhancements #22, #49, #68, #77, #87. +3. Review findings of rc3, not filed: an extra DACL read and four SDDL + snapshots on read paths, and a duplicate SACL check. Older: + `Remove-NTFSAudit` fails for an item without a SACL; + `FileSystemSecurity2.Write(FileSystemInfo)` and `Write(string)` write + every section; the owner retry of `Set-NTFSSecurityDescriptor` lacks a + `finally`; `RemoveFileSystemAccessRuleAll` and + `RemoveFileSystemAuditRuleAll` ignore their accounts filter, which no + cmdlet passes. 4. `pwsh` 7.6.1 crashed three times during test runs on the ARM64 workstation (x64 emulation), without module frames; none of the CI runs on native x64 on 2026-10-05 crashed. 5. Optional for the maintainer: delete the AppVeyor project and revoke its GitHub authorization, restrict wiki editing to collaborators, ask `Sup3rlativ3` to delete the Read the Docs project, and delete the branch - `test/transfer`. + `test/transfer`. The branch `fix/#34` is superseded by #112. diff --git a/.memory-bank/systemPatterns.md b/.memory-bank/systemPatterns.md index 881b0e0..c2dbc99 100644 --- a/.memory-bank/systemPatterns.md +++ b/.memory-bank/systemPatterns.md @@ -1,6 +1,6 @@ --- status: current -last-verified: 2026-10-05 +last-verified: 2026-10-06 owner: active-agent source: repository evidence --- @@ -65,6 +65,7 @@ Each Decision record is a file in `decisions/`; read only the relevant ones. | 16 | [Fix only reproducible bugs](decisions/0016-fix-reproducible-bugs-only.md) | | 17 | [Issue labels](decisions/0017-issue-labels.md) | | 18 | [NTFSSecurity will be archived](decisions/0018-archive-for-windowsaccesscontrol.md) | +| 19 | [Cmdlets write only the sections that they change](decisions/0019-write-only-changed-sections.md) | ## Patterns @@ -88,9 +89,9 @@ Each Decision record is a file in `decisions/`; read only the relevant ones. - 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-TestReadPermission` and `Block-TestWritePermission` make a read or - a write fail without elevation. + 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 diff --git a/.memory-bank/techContext.md b/.memory-bank/techContext.md index f2e0a5f..be589db 100644 --- a/.memory-bank/techContext.md +++ b/.memory-bank/techContext.md @@ -55,8 +55,6 @@ source: repository evidence `https://www.powershellgallery.com/api/v2/package/MarkdownLinkCheck/0.2.0` into `$env:TEMP`, extract it, and import it by path. - The first workstation is ARM64; PowerShell 7 runs as x64 under emulation. - Python 3.12.10 (ARM64) is installed per user with winget, the - maintainer's choice for an MkDocs check that Decision 9 made unnecessary. - 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 @@ -74,7 +72,7 @@ source: repository evidence ## Constraints -- `ModuleVersion` on `master` is `5.0.0` with the prerelease label `rc2`. +- `ModuleVersion` on `master` is `5.0.0` with the prerelease label `rc3`. 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 lists exactly 36 cmdlets; `Test-ModuleManifest` passes in Windows @@ -84,24 +82,19 @@ source: repository evidence 5.0.0 prerelease. - PowerShell Gallery versions (publish dates): 4.0.0 (2015-08-19), 4.2.2 (2016-05-18), 4.2.3 (2016-05-19), 4.2.4 (2018-08-13), 4.2.5 (2019-07-11), - 4.2.6 (2019-07-12), none with release notes; 5.0.0-rc1 (2026-10-04) and - 5.0.0-rc2 (2026-10-05), published by CI. Older versions were released - on CodePlex only, and their dates are lost. The git history starts on - 2016-10-10, when the project moved from CodePlex. -- Releases up to 4.2.6 had no script and no CI deployment: the Gallery - DLLs are Debug builds (`DebuggableAttribute` 263), the nuspec comes from - `Publish-Module`, the package holds the whole output folder (`.pdb`, - `AlphaFS.xml`, 7 MB `System.Management.Automation.dll`), and tags carry - the previous version. From 5.0.0 on, CI publishes on a version tag - (Decision 12). GitHub releases attach `NTFSSecurity.zip`. + 4.2.6 (2019-07-12), none with release notes; 5.0.0-rc1 (2026-10-04), + 5.0.0-rc2 (2026-10-05), and 5.0.0-rc3 (2026-10-06), published by CI. + Older versions were released on CodePlex only, and their dates are 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 and pushes to `master` (Decision 11). - AppVeyor no longer reports on `master` (checked on `4f9f7cc`). The Read - the Docs project `ntfssecurity` (maintainer `Sup3rlativ3`) and a second - AppVeyor project are attached to the fork `Sup3rlativ3/NTFSSecurity`, - which no longer exists (GitHub 404, 2026-10-04). That site still serves - pages from 2020 and isn't used (Decision 9). -- `Get-FileHash2` fails in PowerShell 7; all other cmdlets passed a smoke - test in PowerShell 7.6. + AppVeyor no longer reports on `master`. The Read the Docs project + `ntfssecurity` and a second AppVeyor project belong to the deleted fork + `Sup3rlativ3/NTFSSecurity` and 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)). @@ -113,9 +106,13 @@ source: repository evidence 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. Give each command as one line, or as a script with - `-WhatIf`: the agent's question dialog renders Markdown, which joins the - lines of a block, and PowerShell then rejects all of it. Simulated `gh` + 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 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. @@ -161,6 +158,10 @@ source: repository evidence PowerShell 5.1: the launcher starts `pwsh`, and its payload runs `powershell.exe -NoProfile -EncodedCommand` with Pester imported by full path. A run without `bin\Release\en-US` must fail. +- Tests that run only without a privilege skip in CI and in an elevated + session. Run them as a basic user with `runas /trustlevel:0x20000`, and + give Windows PowerShell its own `PSModulePath`; that token holds one + privilege, so the `Enable-Privileges -PassThru` count test fails there. - 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