Browse Source

chore(memory-bank): record the operating-system matrix and Decision 24

Decision 24 (proposed): the matrix lab, what its deployment and the runs showed,
and what the maintainer decides. The context, patterns, progress, and deployment
notes carry the lessons: the Authz regime of a domain member, the stale Kerberos
S4U state of a re-created account, the evaluation client, and the integration of
the stacked branches.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
pull/119/head
Raimund Andree 2 days ago
parent
commit
d5bfa37f61
  1. 64
      .memory-bank/activeContext.md
  2. 136
      .memory-bank/decisions/0024-os-matrix-lab.md
  3. 135
      .memory-bank/deployment-notes.md
  4. 29
      .memory-bank/progress.md
  5. 16
      .memory-bank/systemPatterns.md
  6. 44
      .memory-bank/techContext.md

64
.memory-bank/activeContext.md

@ -1,6 +1,6 @@
---
status: current
last-verified: 2026-10-09
last-verified: 2026-10-10
owner: active-agent
source: current task evidence
---
@ -9,11 +9,24 @@ source: current task evidence
## Current focus
Handoff 1 of the quality gate is finished on `ai/quality-gate-paths`, from the
reviewed head `f11ff41` of #117: 28 commits, which the maintainer pushed as
draft #118 (CI green on `83149ee`). Both
stacked PRs stay open and green; rc6 remains the latest published
candidate and 4.2.6 the stable Gallery version. Every C# method that no test
The maintainer asked on 2026-10-09 at 21:21 UTC to continue with the release-gate
handoffs and to decide and report later. Handoff 1 (paths) is draft #118
(`83149ee`, CI green; stacked on #117 and #116, all open; rc6 is the latest
published candidate, 4.2.6 the stable Gallery version). Handoff 2 (operating-system
matrix) is the local branch `ai/quality-gate-lab-matrix`, stacked on #118 and not
pushed: the lab `NtfsSecurityOsMatrixLab`, three fixes of the module that the
matrix found (`962887a`, `fdd7a8b`), the kit, the controller changes, and the
record `Tests/Lab/Acceptance-2026-10-10-os-matrix.md` (Decision 24, proposed).
The final local candidate `fdd7a8b` passes the module's suite on five operating
systems and the host (24 runs, no failure) and the live controller in three
cells (1,374 passed, 0 failed, 12 skipped). Handoff 3: Decision 22 was confirmed
under the delegation and stays proposed; nothing is published. Handoff 4:
Decision 23 (the #34 dossier); the risk acceptance is the maintainer's. The
agent's decisions of the night are D1 to D26 in
`decisions-night-2026-10-09.md` of the session files. Stable 5.0.0 stays gated.
The earlier state of handoff 1, from the reviewed head `f11ff41` of #117: 28
commits, which the maintainer pushed as draft #118. Every C# method that no test
visits is classified (223 explained, 8 open for the maintainer), and the
other paths have behavior tests. Eleven defects were fixed, ten of them
with a regression guard that is red before the fix and green after it (owner
@ -104,24 +117,39 @@ open.
media present, OS detection cache empty. #34 has no reply since Oct 6.
- Full evidence: session artifact `quality-gate-3442194-20261009`;
repository report `Tests/Lab/Acceptance-2026-10-09-quality-gate.md`.
- Operating-system matrix, 2026-10-10 (record `Tests/Lab/Acceptance-2026-10-10-os-matrix.md`
with CSV tables): the suite of the final candidate `fdd7a8b` on OSFile19,
OSFile22, OSFile25, OSWin11E, OSWin11, and the host, four configurations each,
zero failures, skipped tests identical to the host's; the baseline `83149ee`
fails 4 elevated and 20 basic-user tests on the domain machines. Live: run
`rc7l`, three cells, 1,374 passed, 0 failed, 12 skipped. The Admin-role
effective-access failures of the earlier cells came from re-creating the
accounts under the same names (stale Kerberos S4U state, probe in the record),
not from the module; the controller now names the account of case 3 anew for
each fixture (`1dec389`). Reviewed by the built-in code-review agent (custom
`security-reviewer` unavailable): approve with Minor, fixed.
## Next step
1. The maintainer reviews and integrates `ai/quality-gate-paths` (stacked on
#117; no remote change was made here) and decides the open items listed
in the report: `FileSecurity` conversions, `RemoveAll` account filters,
lazy path overloads, abandoned `PrivilegeEnabler`, dot patterns of
`Get-ChildItem2 -Filter`, the 17 owner-restore handlers without the
later-command check, unused classes (Decisions 21/22).
2. Gate 3: the affected live acceptance of the paths fixes is repeated (record
above). Accept the published package again before the next candidate counts
as accepted; no local upload.
3. Retain stacked-PR order (15): #116, then #117, then #118; a local merge
1. The maintainer pushes `ai/quality-gate-lab-matrix` as a draft PR with base
`ai/quality-gate-paths` and decides which of the three module fixes belong to
rc7 (each is its own commit). He reviews and integrates the stack: #116, then
#117, then #118, then the matrix branch (Decision 24).
2. He decides the open items listed in the paths report: `FileSecurity`
conversions, `RemoveAll` account filters, lazy path overloads, abandoned
`PrivilegeEnabler`, dot patterns of `Get-ChildItem2 -Filter`, the 17
owner-restore handlers without the later-command check, unused classes
(Decisions 21/22).
3. Gate 3: accept the published package in the first lab and in every cell of
the matrix (`Run-MatrixSequence.ps1 -Version`) before the candidate counts as
accepted; no local upload. The paths fixes were accepted locally (record
above).
4. Retain stacked-PR order (15): #116, then #117, then #118; a local merge
in that order gives exactly the tree of #118. Confirm or change Decision
22.
4. #34 stays open (Decision 23): the maintainer chooses between waiting for a
5. #34 stays open (Decision 23): the maintainer chooses between waiting for a
test of the published candidate on the NetApp, EMC, and IBM ESS servers of
the reporters (checklist: `Tests/Lab/Non-Windows-File-Server-Test.md`) and
accepting the untested risk with a release-note caveat. No agent can
accept it.
5. Do not release stable 5.0.0 or equate a percentage with gate closure.
6. Do not release stable 5.0.0 or equate a percentage with gate closure.

136
.memory-bank/decisions/0024-os-matrix-lab.md

@ -0,0 +1,136 @@
---
status: proposed
date: 2026-10-09
last-verified: 2026-10-10
owner: shared
source: agent decisions under the maintainer's delegation of 2026-10-09 (Handoff 2); the scope follows Decision 21, phase 3
---
# Decision 24: The operating-system matrix lab
- Context: Decision 21 requires the live tests on more operating systems,
"such as a Windows 11 client and Server 2019 and 2022 file servers", and the
published package must pass them. Every machine of `WindowsAccessControlLab`
is Server 2025. Handoff 2 asks for the maintainer's approval of scope and
topology before new VMs. On 2026-10-09 at 21:21 UTC the maintainer, going to
bed, wrote "you can do whatever is required with the lab" and told the agent
to decide and report later. The agent took that as the approval for the
minimal matrix below and for nothing broader. It is the agent's decision, so
the status stays `proposed` until the maintainer confirms it.
- Choice:
1. Cells: a Windows 11 client with each file server (Server 2019 Datacenter
10.0.17763.1217, Server 2022 Datacenter 10.0.20348.4773, Server 2025
Datacenter 10.0.26100.32690), the module in Windows PowerShell 5.1 and
PowerShell 7 in every cell. The client was planned as Windows 11 Pro
26H1 (10.0.28000.1836). It cannot keep a secure channel to the Server 2025
domain controller (see "What the deployment showed"), so the domain client
is `OSWin11E`, Windows 11 Enterprise Evaluation 22H2 (10.0.22621.525), and
the 26H1 machine `OSWin11` stays in the lab outside the domain for runs of
the module's own tests. The reference cell of Decision 20 (Server 2025
client and file server in `WindowsAccessControlLab`) stays as it is.
Server 2019 and 2022 as clients are extra cells, to run the module on the
older .NET Framework builds (Server 2019 has 4.7.2).
2. Topology: a separate AutomatedLab lab `NtfsSecurityOsMatrixLab` with its
own internal switch (`192.168.12.0/24`) and its own forest `osmatrix.net`:
`OSDC1` (Server 2025, root domain controller), `OSFile19`, `OSFile22`,
`OSFile25`, `OSWin11E`, and `OSWin11`. `Deploy-OsMatrixLab.ps1` deploys it
with the maintainer's AutomatedLab and the VM path `V:\AutomatedLab-VMs`;
`Add-OsMatrixMachine.ps1` adds a machine to the deployed lab; the
payloads of the existing lab (PowerShell 7.6.3 and Pester 5.7.1 from the
host, because the VMs have no internet) come from
`Complete-OsMatrixLab.ps1`.
3. Case 9 (accounts of other domains and forests) needs trusts to the
forests of the existing lab, so the matrix cells run with
`-ForeignDomainController @()`; the existing lab keeps that case.
4. The controller of the repository runs in every cell with `-LabName`,
`-DomainController`, `-FileServer`, and `-Client`. The matrix showed three
defects of its setup and removal, fixed in `7d47316`: a recursive delete
fails with "The directory is not empty" on Windows Server 2019 (and the
stderr line ended the script before any retry, because `2>&1` under `Stop`
is terminating in Windows PowerShell 5.1), `Get-LocalGroupMember` fails on
an orphaned SID, and a vanished profile failed the client cleanup.
5. The module's own behavior tests run on every machine as well
(`Run-MatrixLocalSuite.ps1`), elevated and as a basic user, in both
editions, as scheduled tasks so that the token matches a CI runner. This
found three defects of the module, each fixed in its own commit on
`ai/quality-gate-lab-matrix`: `Get-NTFSInheritance -SecurityDescriptor`
and `Get-NTFSEffectiveAccess -ServerName ''` (`962887a`), and
`Get-NTFSEffectiveAccess` for a user who isn't an administrator on a
computer in a domain (`fdd7a8b`, with a live test for the ServerAdmin
role). The maintainer decides which of them belong to rc7.
- Why a separate lab: AutomatedLab 5.61 refuses to add machines to an
imported lab, and defining a lab under an existing name would overwrite the
metadata of its 13 machines. A separate lab leaves every shared machine,
switch, domain, and account untouched, which Handoff 2 requires. Inside the
new lab, a machine can be added with `Import-LabDefinition`,
`Add-LabMachineDefinition`, and `Export-LabDefinition`, followed by the steps
that `Install-Lab` runs for one machine; `Add-OsMatrixMachine.ps1` does this
after it copies the lab metadata.
- Cost and rollback: six VMs (4 GB for the domain controller and both clients,
3 GB for each file server), four new base images, measured at 17.8 GB for
the differencing disks and 42.4 GB for the base images (about 60 GB on `V:`;
my first estimate of 100 GB was too high). The deployment added twelve lines
to the hosts file of the host, which `Remove-Lab` removes. To remove the
matrix, run `Remove-Lab -Name NtfsSecurityOsMatrixLab` from AutomatedLab;
nothing else depends on it. No existing machine, checkpoint, or lab was
changed. A copy of the lab metadata from before the sixth machine is in
`C:\ProgramData\AutomatedLab\Backups` (administrators only).
- What the deployment showed (the agent's decisions D11 to D23 of the night
log, each reversible):
- The base image of a Server 2019 or a Windows 11 22H2 machine had an empty
EFI system partition: the `bcdboot` of the Server 2025 host fails with
exit code 193 on their boot files, and AutomatedLab ignores the exit code,
so the generation 2 machine fails with Hyper-V event 18603. The images of
Server 2022 and Windows 11 26H1 are fine. `Repair-OsMatrixBoot.ps1` runs
the `bcdboot` of the image itself on the differencing disk of the one
machine and starts it.
- The AutomatedLab driver sat in its file-server job wait with idle remote
runspaces after all features were installed, so I stopped it and ran the
rest by script.
- Windows 11 26H1 (10.0.28000.1836) joins the domain but cannot keep the
Netlogon secure channel to the Server 2025 domain controller
(10.0.26100.32690). The client calls `NetrLogonGetCapabilities` with query
level 2, which the protocol document describes as a check of the flags the
client sent; the controller answers `STATUS_ACCESS_DENIED` (level 1 and
`NetrServerAuthenticate` succeed), and the client denies the channel
(`NlConfirmRequestedCapabilities: denying access ... 0xc0000022`).
`Test-ComputerSecureChannel -Repair` can't help. Windows 11 22H2 against the
same controller works (secure channel, Kerberos, readiness). This is an
environment finding about two Microsoft builds, not about NTFSSecurity; the
maintainer may want to know it for his own labs.
- The Windows 11 Enterprise Evaluation 22H2 image (`OSWin11E`) is in
notification mode from its first day and shuts down an hour after every
start (`wlms.exe`, 0xC004F009 "grace time expired"): its install time was
recorded on a clock about seven hours ahead, which was then corrected. One
of its two rearms didn't help. After an unplanned shutdown its machine
account password no longer matched (domain logons fail with 0xC000018D,
`nltest /sc_verify` says `ERROR_INVALID_PASSWORD`);
`Test-ComputerSecureChannel -Repair` with the lab account fixed it, and
`/sc_verify` kept showing the old status afterwards, so test a domain
session instead. A run on this machine has to stay under an hour from its
start.
- A profile of an account that a probe's scheduled task used stayed loaded on
one server until it restarted; the probe now uses a new account name for
every run.
- The fixture of the live controller deleted its accounts after a cell and
created them again with the same names for the next. Windows then returns
the SID and the groups of the deleted account for a Kerberos S4U logon on
the domain controller and the file server for more than seven minutes, so
`Get-NTFSEffectiveAccess` returned no access for the new account in some
cells (Windows Server 2022, Admin role), for the baseline and the final
candidate alike. This looked like a regression of the module until a loop
probe showed both builds failing the same way. The controller now gives a
new fixture a new name for the account of case 3 (`1dec389`); the record
has the evidence.
- Result: [the record](../../Tests/Lab/Acceptance-2026-10-10-os-matrix.md). The
final candidate (`fdd7a8b`) passes the module's suite on all five machines
and the host in all four configurations, and the live cells (see the record).
- Open: the maintainer confirms or changes the matrix and decides whether to
keep the VMs after 5.0.0. Local `-ModulePath` runs are validation; the gate
needs the published package in every cell (Handoff 3, stage D). The newest
Windows 11 build that can join a Server 2025 domain here is 22H2; a domain
cell with 26H1 needs a newer domain controller build or a fix of the
mismatch. The maintainer also decides which of the three module fixes belong
to rc7 (each is its own commit, `git revert` removes it), and whether the
evaluation client stays (it needs a start shortly before every run) or is
replaced by a client with a license that doesn't expire.

135
.memory-bank/deployment-notes.md

@ -0,0 +1,135 @@
---
status: current
last-verified: 2026-10-10
owner: software-engineer
source: release gates of 5.0.0 (lab acceptance, OS matrix, publication plan), repository evidence
---
# Deployment notes
## Publish the next prerelease (rc7)
State on 2026-10-09: #116 (rc7, head `d25647d`, base `master`), #117 (head
`f11ff41`, base `ai/release-5.0.0-rc7`), and #118 (draft, head `83149ee`,
base `ai/quality-gate-coverage`) are open and green. A local merge in that
order, each with a merge commit (Decision 15), ends in exactly the tree of
#118 (`b1dc006`), without conflicts. The manifest says `5.0.0` with
`Prerelease = 'rc7'`, and `$publishedVersions` in `Tests/Repository.Tests.ps1`
lists the versions up to rc6, as it must before rc7 is published.
The branch `ai/quality-gate-lab-matrix` (local until the maintainer pushes it)
is stacked on #118. It holds three fixes of the module (`962887a`, `fdd7a8b`;
each is its own commit and `git revert` removes it), the kit of the
operating-system matrix, the changes of the live controller, and the record
(Decision 24). rc7 contains the module fixes only if the branch is merged after
#118 and before the tag; otherwise they go to the next prerelease. The
maintainer decides; open it as a draft with base `ai/quality-gate-paths`.
1. Merge #116, then #117, then #118 into `master`, each with **Create a merge
commit**. Deleting the merged head branch makes GitHub retarget the next
pull request to `master`; otherwise change its base. Wait for green CI on
the retargeted pull request.
2. Tag the merge commit on `master` with `5.0.0-rc7` and push the tag. The
`release` job checks the tag against the manifest and builds nothing new:
it publishes the package that the `build` job tested. Approve the
deployment of the `powershell-gallery` environment if it asks.
3. After the publication, add `5.0.0-rc7` to `$publishedVersions` with the
next change that goes to `master`.
## Accept a published package
Local `-ModulePath` runs are validation; the gate needs the published bytes.
1. `Tests/Lab/Acceptance/Test-PublishedRelease.ps1 -Version <version>
-OutputPath <folder>` (read-only): tag and commit on `master`, the CI run
of the tag, the Gallery's SHA-512 against the downloaded nupkg (ordinal,
case-sensitive base64), the nupkg against the GitHub zip file by file, and
the identity of the manifest. Dry run on rc6: all checks passed.
2. `Tests/Lab/Invoke-NTFSSecurityLabTest.ps1 -Version <version>` in the
existing lab, both editions, and `Tests/Lab/Acceptance/Run-MatrixSequence.ps1
-Version <version>` for each cell of the matrix (Decision 24). Check every
role from the result files with `Validate-LabResults.ps1`, never from the
marker `DONE` of the controller.
3. Remove the fixture and check the end state independently with
`Test-MatrixCleanup.ps1`, which takes the lab name and the machine names
(`-LabName WindowsAccessControlLab -DomainController F1ADC1, F1BDC1, F2DC1,
F3DC1 -Machine F1AFile1, F1AFile2` for the existing lab).
4. If the published binary changes, repeat the cells; never combine runs of
different binaries into one matrix.
## Lab lessons
- AutomatedLab 5.61 can't add machines to an imported lab (`Add-LabMachineDefinition`
throws "Lab is already imported"), and `New-LabDefinition` under an existing
name overwrites its metadata. New machines go into a new lab with its own
switch and domain, and `-LabName` of the controller selects it.
- `Install-Lab -NetworkSwitches -BaseImages` creates the switch and the base
images first; the base images of Server 2019, Server 2022, and Windows 11 Pro
took about two to four minutes each from the ISO files. AutomatedLab
adds records to the hosts file of the host, which `Remove-Lab` removes.
- The VMs have no internet: take PowerShell 7 and Pester 5.7.1 from the host
(`Copy-LabFileItem`, `Install-LabSoftwarePackage`).
- AutomatedLab ignores the exit code of `bcdboot` when it builds a base image.
The Server 2019 image that it built on this Server 2025 host got an empty
EFI system partition: the `bcdboot` of the host fails with exit code 193,
"Failure when attempting to copy boot files", on the 2019 boot files, and the
VM failed to boot (Hyper-V event 18603, "failed to boot an operating
system"; no memory demand, no IP, heartbeat `NoContact`). Check the EFI
system partition of a new base image before the first VM: mount the image
read-only (`Mount-DiskImage -Access ReadOnly`) and look for
`EFI\Microsoft\Boot\bootmgfw.efi` (the images of Server 2022 and Windows 11
Pro had 140 and 149 files). Repair a VM, not the base: stop the VM, mount its
own differencing disk, run the `bcdboot.exe` of the image (`D:\Windows\System32\bcdboot.exe
D:\Windows /s H: /f UEFI`), copy `bootmgfw.efi` to `EFI\Boot\bootx64.efi`,
dismount, and start the VM. A changed base image would invalidate its
differencing disks.
- The tool output of the agent masks text that looks like a secret, such as
`-Password $password`, in what it shows. Test such a line by parsing the
file, and don't repair it from the displayed text.
- A script that a detached process runs needs its own log, an exit marker, and
an end-state check of its own; verify cleanup from the end state, not from
its marker.
- Extend a deployed lab with one machine like this: in a process that never ran
`Import-Lab`, call `Import-LabDefinition`, `Add-LabMachineDefinition`, and
`Export-LabDefinition`, then `New-LabBaseImages` and `New-LabVM -Name <machine>`.
`Install-Lab` has no per-machine selector, and `Add-LabMachineDefinition`
throws as soon as `Get-Lab` returns a lab. `Add-OsMatrixMachine.ps1` does it
after it copies the lab metadata to `C:\ProgramData\AutomatedLab\Backups`.
- Windows 11 22H2 (10.0.22621) has the empty EFI system partition problem too
(`bcdboot` exit code 193 on the host); `Repair-OsMatrixBoot.ps1` repairs it.
After `Mount-VHD` the host gives the NTFS partition a letter on its own; don't
assign a second one.
- Run AutomatedLab processes one after the other. Two `Import-Lab` calls at the
same time corrupt each other (XML errors, "No machines imported").
- Check the secure channel of every domain client before the first run
(`Test-MatrixReadiness.ps1`). Windows 11 26H1 (10.0.28000.1836) joins a
Server 2025 domain (10.0.26100.32690) but loses the channel: the client asks
`NetrLogonGetCapabilities` for query level 2, the domain controller answers
`0xC0000022`, and the client denies the channel. Rejoining doesn't help.
- A process that starts from a remoting session has every privilege enabled
and no credentials of its own, so tests that expect disabled privileges fail
(eight per edition). Run the suite of a VM as a scheduled task with a batch
logon at the highest run level (`Register-ScheduledTask -RunLevel Highest
-User -Password`): that token matches a CI runner. A restricted token (a basic
user) can't run Pester's NUnit export, because it asks WMI for the
environment, so write the JSON summary first.
- In Windows PowerShell 5.1, `$PSScriptRoot` is empty in a parameter default of a
script that runs with `-File`; compute it in the body. `-File` passes an array
as one string, so split on commas. With `$ErrorActionPreference = 'Stop'`, a
line that a native command writes to stderr and that `2>&1` redirects is a
terminating error; let the command write its errors to stdout.
- `Get-LocalGroupMember` fails with "Failed to compare two elements in the array"
when the group holds an orphaned SID. Add members with `Add-LocalGroupMember`
and ignore `MemberExistsException`; read and remove members with
`net localgroup <name>` and `net localgroup <name> <SID> /delete`. The SIDs
of a deleted account can't be found afterwards, so keep `fixture-sids.json`
from before the removal of the organizational unit.
- An account that is deleted and created again with the same name keeps its old
SID and groups in Kerberos S4U logons on the domain controller and member
servers for more than seven minutes, and nothing flushes it (see
`techContext.md`). The controller names the account of case 3 anew for each
new fixture; a script of your own that recreates accounts needs unique names
too.
- Restart the evaluation client (`OSWin11E`) right before a sequence or a suite,
not before several: it shuts down an hour after each start. The restart takes
about two and a half minutes and may need the repair of the secure channel.

29
.memory-bank/progress.md

@ -14,7 +14,10 @@ recovered in attempt 2 on 2026-10-09. #116 (rc7, `d25647d`, base `master`)
is open and green, not merged or published. Further quality-gate work is
`ai/quality-gate-coverage` (#117) and `ai/quality-gate-paths` (draft #118),
which classifies every remaining unvisited path; the open items are the
maintainer's decisions. Stable Gallery version: 4.2.6.
maintainer's decisions. The local branch `ai/quality-gate-lab-matrix` (stacked
on #118, not pushed) holds the operating-system matrix, three fixes of the
module found by it, and the controller changes (Decision 24, proposed).
Stable Gallery version: 4.2.6.
After 5.0.0, archive in favor of WindowsAccessControl (Decision 18).
## Recent milestones
@ -79,6 +82,21 @@ After 5.0.0, archive in favor of WindowsAccessControl (Decision 18).
486 passed, 0 failed, 2 expected skips; baseline 338 passed, 148 failed, all
148 green on the candidate; fixture removed and verified clean on six
machines. Record: `Tests/Lab/Acceptance-2026-10-09-quality-gate-paths.md`.
- 2026-10-09 to 10: handoffs 2 to 4 under the maintainer's delegation (decisions
D1 to D26 in the night log of the session files). The matrix lab
`NtfsSecurityOsMatrixLab` (Server 2019, 2022, and 2025 file servers, Windows 11
Enterprise 22H2 client, Windows 11 26H1 suite only) found three defects of the
module, fixed in `962887a` and `fdd7a8b`: audit inheritance by descriptor,
`Get-NTFSEffectiveAccess -ServerName ''`, and the same cmdlet for a user who
isn't an administrator on a domain member. The final candidate passes the
module's suite on every machine (24 runs, no failure) and the live controller
in three cells (1,374 passed, 0 failed, 12 skipped). The failures of the
effective-access tests in the Server 2022 cell were not a defect of the module:
Windows returns the SID and the groups of a deleted account for a Kerberos S4U
logon for more than seven minutes, and the controller names the account of
case 3 anew for each fixture (`1dec389`). A read-only built-in review of the
kit and the fixes approved with Minor findings, fixed in `db04ef2`. Record:
`Tests/Lab/Acceptance-2026-10-10-os-matrix.md`; nothing was pushed.
## Stable capabilities
@ -128,9 +146,12 @@ After 5.0.0, archive in favor of WindowsAccessControl (Decision 18).
tests and exact artifact SHA-512 verification. Original upload errors
remain errors for missing/different/unverifiable outcomes. Not deployed
until the maintainer merges/pushes; no publication was performed here.
9. Phase 3: choose OS scope (proposed Windows 11 client/2019/2022 servers),
detect ISO editions, provision without repurposing shared VMs, then run
published-package acceptance. #34 has no new reply since 2026-10-06.
9. Operating-system matrix (Decision 24, proposed): the lab and the cells exist
and the final local candidate passes them. Open: the acceptance of the
published rc7 in every cell, keeping or replacing the VMs (about 60 GB) and
the evaluation client (it shuts down every hour), which module fixes go to
rc7, and a domain cell for Windows 11 26H1. #34 has no new reply since
2026-10-06.
10. Lab rollback evidence: new checkpoints exist but report Standard even
after a successful temporary ProductionOnly probe. Classification is
unresolved; original VM policy restored, no checkpoint restored. Do

16
.memory-bank/systemPatterns.md

@ -113,6 +113,22 @@ Read only task-relevant records; the index controls routing.
example code blocks, and check the generated XML.
- Live tests use only approved lab targets, SMB then independent server state;
Get/SetFileSecurity preserves stored DACLs; rights oracles use S4U tokens.
- A suite that is green on the development host and on CI says little about a
feature that the environment lacks. The matrix found three defects that every
earlier run had missed because the host is outside a domain and the CI
runner's token differs: run the suite on a domain member, on other builds, and
as a basic user before a release, and classify a failure by a probe under the
real tokens (elevated, filtered, local standard, domain standard) before
calling it a defect or a design.
- A fixture that deletes an account and creates it again with the same name
gets the old SID and groups from Kerberos S4U logons (the oracle of the live
tests, and the Authz functions behind `Get-NTFSEffectiveAccess`) on the
domain controller and on member servers for more than seven minutes, and no
cache flush helped (a ticket purge renews only the session's own token). A
failure that follows the order of the cells and not the version of the
module points to such state: run a loop probe with the baseline and the
candidate side by side before blaming the code. The controller names the
account of case 3 anew for each new fixture.
### CI results and publication

44
.memory-bank/techContext.md

@ -175,6 +175,12 @@ source: repository and executable evidence
- Remote Authz answers administrators and Access Control Assistance
Operators (S-1-5-32-579); other accounts get access denied. Check firewall
when remote resource-manager RPC fails. Expected rights use S4U tokens.
A computer in a domain offers the remote interface to every caller, so the
denial also hit the default `-ServerName localhost` for a user who isn't an
administrator; a computer outside a domain doesn't offer it, which is why the
tests passed on the development host and on CI. Since `fdd7a8b`, the local
manager answers for a name of this computer when the remote one refuses; the
denial stays for another computer (live test of the Delegate role).
- A live test is evidence of a fix only when it fails on the build without
the fix: run the same tests, controller, and lab against the candidate and
the base of the branch, a new process per edition, and join both result
@ -185,3 +191,41 @@ source: repository and executable evidence
in the CSV became `System.String[]`.
- RemoveFixture after the run; verify OUs/accounts, share, folders, local
memberships, and test profiles removed. Credentials must never be printed.
### Operating-system matrix (Decision 24)
- Lab `NtfsSecurityOsMatrixLab`: OSDC1 (Server 2025), OSFile19/22/25 (Server
2019/2022/2025), OSWin11E (Windows 11 Enterprise Evaluation 22H2, the domain
client), OSWin11 (Windows 11 Pro 26H1, suite only). Kit: `Tests\Lab\Acceptance`;
record: `Tests\Lab\Acceptance-2026-10-10-os-matrix.md`.
- Run the module's own suite on every machine class before the controller
(`Run-MatrixLocalSuite.ps1`, elevated and basic, both editions, as scheduled
tasks with a batch logon at the highest run level): a child of a remoting
session has every privilege enabled and fails eight tests that expect them
disabled. Skipped lists are compared as multisets against the host.
- AutomatedLab: one `Import-Lab` at a time, and none while a controller
sequence runs (it re-imports the lab); `Wait-LabVM` waits for a heartbeat that
a client may not report, so retry `New-LabPSSession`. The host's `bcdboot`
leaves the ESP of a Server 2019 or Windows 11 22H2 base image empty.
- Windows PowerShell 5.1: `$PSScriptRoot` is empty in a parameter default under
`-File`; `2>&1` on a native command under `Stop` makes its stderr line
terminating; `Get-LocalGroupMember` fails on an orphaned SID; `net localgroup
<name> <SID> /delete` refuses the SID of a name that its cache still
resolves (use `Remove-LocalGroupMember -SID`).
- Windows 11 26H1 (28000.1836) loses the secure channel to a Server 2025 domain
controller (`NetrLogonGetCapabilities` level 2, 0xC0000022): suite only.
The 22H2 evaluation client shuts down every hour (license grace expired) and
can lose its machine password after an unplanned shutdown: keep a run under
an hour from its start, test a domain session (not `nltest /sc_verify`, which
stays stale), repair with `Test-ComputerSecureChannel -Repair`.
- Builds are not byte-reproducible (two unchanged assemblies differ per build):
hash each candidate and its package separately.
- The fixture's account for case 3 gets a new name for each new fixture
(`NtfsLiveSubject` and four digits). After an account is deleted and created
again with the same name, a Kerberos S4U logon returns the old SID and groups
for more than seven minutes on the domain controller and the file server
(`WindowsIdentity` with a UPN, the Authz functions behind
`Get-NTFSEffectiveAccess`), whichever module version asks; a `klist purge`
renews only the session's own token, and `nltest /sc_reset`, a DNS flush, and
a restart of the Kerberos service change nothing. `Probe-AccountRecreation.ps1`
shows it.

Loading…
Cancel
Save