Skip to content

Roll back the modules' registry writes on a failed apply (Scope B) - #52

Merged
BiosSystem merged 1 commit into
masterfrom
feature/module-rollback-scope-b
Sep 17, 2026
Merged

BiosSystem merged 1 commit into
masterfrom
feature/module-rollback-scope-b

Conversation

@BiosSystem

Copy link
Copy Markdown
Owner

What

Completes full-module rollback. Scope A (merged in #45) reverted the modules' non-registry state on a failed apply but reported their imperative registry writes as "not restored". Scope B closes that gap for the three registry-writing modules: SecurityHardening, ExtendedAIPurge, GamingMode.

Design (as agreed: expose write targets as data so the snapshot can't drift)

  • Each module gets Get-<Module>RegistryTargets returning the exact (Path, Name) values it writes.
  • BackupModuleState snapshots each target's current value and type before apply (or records absence).
  • On rollback it writes the original back with its type, or removes a value the module created. Restoring all captured targets is safe even for a module that didn't run, since they were captured pre-apply.
  • One-way ops (Recall component removal) and the powercfg power-plan change stay reported as not restored. GamingMode's per-interface Nagle values are enumerated at capture time.

Validation

  • Tests\Invoke-StaticValidation.ps1 -RequirePSScriptAnalyzer clean (122 files).
  • Full unit suite: 167 passed, 0 failed, including new Scope B coverage — restore-existing-value, remove-created-value, skip-when-no-registry-module, failure recorded not faked; provider contents; and an AST drift guard asserting every Set-ItemProperty name in each module is declared by its provider.
  • Smoke-tested the live registry-read path (read-only) on a real machine: providers return 11 / 16 / 41 targets (41 = 9 static + 16 interfaces × 2), correct value/type read and missing-value detection.
  • Also wired Test-ModuleRollback.ps1 and Test-ConfigConsistency.ps1 into CI — both existed but were never run there.

Not run here (mutating, needs Sandbox): the live capture-apply-fail-restore cycle against the real registry. The snapshot/restore logic and the real read path are covered as above.

Automatic rollback already reverted the modules' non-registry state (Scope A:
services, firewall, HOSTS, tasks, SMB1) but reported their imperative registry
writes as "not restored". This closes that gap for the three registry-writing
modules: SecurityHardening, ExtendedAIPurge, GamingMode.

Each module now declares the exact (Path, Name) targets it writes as data via
Get-<Module>RegistryTargets, so the snapshot cannot drift from the apply. Before
applying, BackupModuleState captures each target's current value and type (or
records that it did not exist); on rollback it writes the original back with its
type, or removes a value the module created. Restoring all captured targets is
safe even for a module that did not run, because they were captured pre-apply.

One-way operations (Recall component removal) and the powercfg power-plan change
stay reported as not restored. GamingMode's per-interface Nagle values are
enumerated at capture time.

Tests: Scope B restore paths, provider contents, and an AST drift guard that
asserts every Set-ItemProperty name in each module is declared by its provider.
Also wired Test-ModuleRollback and Test-ConfigConsistency into CI; both existed
but were never run there.
@BiosSystem
BiosSystem merged commit 9d8bf1e into master Sep 17, 2026
1 check passed
@BiosSystem
BiosSystem deleted the feature/module-rollback-scope-b branch September 17, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant