Enable and validate leaf-package remediation proposals #210
No reviewers
Labels
No labels
area:authentication
area:flake-utilities
area:performance
area:tbd
host:chaos
host:electra
host:fleet
host:lyra
host:nova
host:vega
investigation
phase:cutover
phase:deploy
phase:mcp
phase:module
phase:packaging
phase:prep
phase:validation
priority:high
priority:medium
project:attic-postgres-lyra-rollout
project:auto-update-reliability
project:auto-update-remediation
project:declarative-purity-cleanup
project:external-review
project:fleet-boundary-cleanup
project:host-facts-refactor
project:lyra-nixos-deploy
project:lyra-service-stack-migration
project:nebula-mesh-network
project:nixos-build-deployment-pipeline
project:security-hardening
project:service-stack-migration
project:vega-sillytavern-cutover
project:wiki-rebuild
repo:numtide/flake-utils
repo:numtide/nix-auth
repo:numtide/nixos-passthru-cache
repo:numtide/nix-relay
service:auto-update
service:mem0
service:nix
service:sillytavern
service:slskd
service:synthseek
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
nimmo/nixos-config!210
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/remediation-leaf-proposals"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Historical Moonlight failures could not reach an accepted temporary-pin proposal: the incident misidentified failed builders, the worker lacked package/dependency context and an allowed leaf target, and real Nix behavior exposed validation gaps hidden by fixtures. The controller now supplies bounded baseline/candidate recipes and dependency alternatives, identifies existing editable leaf files, computes proposal checksums, canonicalizes diff hunks, separates JSON stdout from diagnostics, and avoids Nix outPath coercion in package proofs. Moonlight has a dedicated leaf expression that preserves its current upstream derivation and override behavior.
Refs #208; milestone: Automated Update Remediation. #207 is merged; this MR now targets main and uses merged updater MR #2. The lock pins updater main at merge a32a0ba5a1563e10dcc41debfd31424a2020f89c.
Validation:
Remaining evidence: the reduced flake exposes one real package as a synthetic target; it does not establish fleet/production-host validation. Required live deployment and no-op follow-up remain before issue closure. Model explanatory prose still needs human review. No merge, deployment, or production package pin was applied.
Integration update: merged config main into head
c75d17d1and resolved flake.lock using current main plus updater main at MR #2's merge commit. Full flake check, remediation regressions, and pin-lifecycle regressions pass on this exact tree. The automated review claim that model.py lacks import time is a false positive: import time is present and package_evidence/time.monotonic is exercised by the passing integration test.Automated-review follow-up:
a71b8beaddresses the retained inherited-stderr-pipe finding. Reader cleanup now terminates children that retain the isolated command process group's descriptors, then explicitly closes stdout/stderr as a bounded final fallback. The regression launches a child that holds both pipes for 30 seconds and proves the parent result returns in under five seconds. The earlier missing-time-import finding was false (import timeis present and exercised). The inline Nix projection and fake-command organization remain advisory maintenance suggestions; package evidence fails closed when projection evaluation is unavailable, and real-Nix replay evidence is recorded in #208.Final exact-head review (
ee73c54): CI and automated review jobs pass. The reviewer retained one “important” item but explicitly concluded “The current implementation is robust. No change needed.” The described fallback occurs only after the command leader has exited, then TERM and KILL of its isolated process group have failed to close inherited pipes; closing the controller's read descriptors cannot signal the already-exited leader. A regression covers a live descendant retaining both descriptors. Remaining findings are advisory and either already policy-backed or explicitly handled.Automated code review
Reviewed commit:
ee73c545ad2d039dffd3c76619b2644b10415959Verdict: Requires further work
Resolve the blocking or important findings and investigate failed deterministic checks before merging.
Overall assessment
The PR introduces a dedicated wrapper for
moonlight-qtto allow dependency pinning without global overrides, enhances the remediation controller with bounded advisory context collection (package versions, dependencies, alternatives), and improves command execution robustness by separating stderr from stdout and implementing bounded cleanup of inherited output pipes. The changes include validation logic to ensure patches target allowed leaf files and avoid modifying copied evidence, and update the worker prompt to reflect these constraints.Blocking findings
None.
Important findings
The
finish_readersfunction closesprocess.stdoutandprocess.stderras a final fallback if threads remain alive. If the child process has already exited but inherited descriptors are still open in a way that prevents EOF, closing them is correct. However, if the child is still running (though unlikely given the context of 'command leader exits'), closing stdout/stderr might cause SIGPIPE or unexpected behavior in the child. The code assumes the command leader has exited (The command leader has exited, so Popen.terminate() cannot help.), which mitigates this risk.Impact: Low probability of unexpected child termination if assumptions about process state are violated, but generally safe given the context.
Suggested fix: The current implementation is robust. No change needed.
Suggestions
Hardcoded policy limits in validation.py (scripts/nixos_update_remediation/validation.py:129; medium confidence)
The
validate_applied_patchfunction usespolicy['eligibility']['allowedPatchDeletionTokens']. While this is loaded from policy, the specific tokens are not visible in the diff. Ensure these tokens are well-documented and reviewed for security implications.Impact: If tokens are too broad, they might allow unintended edits.
Suggested fix: Review
allowedPatchDeletionTokensin the policy file to ensure they are restrictive enough.Nix evaluation timeout handling (scripts/nixos_update_remediation/model.py:475; high confidence)
The
package_evidencefunction usesrun_commandwith a timeout derived fromdeadline - monotonic(). If the deadline is very close, the timeout could be negative or zero, leading to immediate failure. The code checksif remaining <= 0: raise ControllerError(...), which handles this.Impact: Prevents invalid timeouts.
Suggested fix: No change needed.
Tests and validation
Questions
moonlight-qtwrapper been tested with actual dependency overrides in a real NixOS environment?Review limitations
nix flake checkor execute the integration tests to verify the changes.Diff coverage
README.md: reviewed — included in a context-limited batchflake.lock: reviewed — included in a context-limited batchmodules/common/nix-settings.nix: reviewed — included in a context-limited batchpackages/moonlight-qt/default.nix: reviewed — included in a context-limited batchremediation/worker-prompt.md: reviewed — included in a context-limited batchscripts/nixos_update_remediation/cli.py: reviewed — included in a context-limited batchscripts/nixos_update_remediation/core.py: reviewed — included in a context-limited batchscripts/nixos_update_remediation/model.py: reviewed — included in a context-limited batchscripts/nixos_update_remediation/validation.py: reviewed — included in a context-limited batchtests/nixos-update-remediation-integration.py: reviewed — included in a context-limited batchReview metadata