High: restore reliable deployed-revision detection and Git flake provenance #54

Closed
opened 2026-07-13 07:57:15 +01:00 by nimmo · 8 comments
Owner

Context

Consumer builds formerly used a path flake, which omitted Git revision metadata and prevented HEAD-versus-deployed comparison from converging. Exact git+file revision builds restored provenance, but the first live Lyra run exposed a second boundary: root could not evaluate the user-owned Git repository. Builds now run as the configured repository owner, while profile activation remains privileged.

Scope

  • Build with exact Git flake semantics.
  • Evaluate/build the repository as its owner without weakening Git ownership checks.
  • Treat missing/null/malformed deployed revisions explicitly.
  • Ensure staged, unstaged, and untracked changes block automatic work.
  • Verify the deployed revision after activation.

The historical missing-legacy-revision convergence scenario has been moved to #56 for hermetic testing rather than manufactured on a live generation.

Completion criteria

  • An owner-run clean consumer build exposes configurationRevision == git rev-parse HEAD.
  • Root is retained only for profile mutation/activation.
  • Missing/null revision handling and full worktree checks are implemented.
  • A no-change follow-up run exits before build on every consumer.
  • A committed-but-not-deployed HEAD triggers exactly one build/switch.
  • Post-switch verification succeeds during a genuine detached update.

Evening live-validation plan

For each participating consumer:

  1. Record checkout HEAD and deployed revision before the timer.
  2. Confirm the journal invokes the exact git+file?...rev=<HEAD> candidate without an ownership error.
  3. Confirm activation verifies the same full revision.
  4. Run or observe one follow-up check and confirm it logs Nothing changed in pull, system is current without building.
  5. Confirm no failure stamp is present.
  6. Preserve logs for any mismatch rather than retrying with --force.
## Context Consumer builds formerly used a path flake, which omitted Git revision metadata and prevented HEAD-versus-deployed comparison from converging. Exact `git+file` revision builds restored provenance, but the first live Lyra run exposed a second boundary: root could not evaluate the user-owned Git repository. Builds now run as the configured repository owner, while profile activation remains privileged. ## Scope - Build with exact Git flake semantics. - Evaluate/build the repository as its owner without weakening Git ownership checks. - Treat missing/null/malformed deployed revisions explicitly. - Ensure staged, unstaged, and untracked changes block automatic work. - Verify the deployed revision after activation. The historical missing-legacy-revision convergence scenario has been moved to #56 for hermetic testing rather than manufactured on a live generation. ## Completion criteria - [x] An owner-run clean consumer build exposes `configurationRevision == git rev-parse HEAD`. - [x] Root is retained only for profile mutation/activation. - [x] Missing/null revision handling and full worktree checks are implemented. - [x] A no-change follow-up run exits before build on every consumer. - [x] A committed-but-not-deployed HEAD triggers exactly one build/switch. - [x] Post-switch verification succeeds during a genuine detached update. ## Evening live-validation plan For each participating consumer: 1. Record checkout HEAD and deployed revision before the timer. 2. Confirm the journal invokes the exact `git+file?...rev=<HEAD>` candidate without an ownership error. 3. Confirm activation verifies the same full revision. 4. Run or observe one follow-up check and confirm it logs `Nothing changed in pull, system is current` without building. 5. Confirm no failure stamp is present. 6. Preserve logs for any mismatch rather than retrying with `--force`.
Author
Owner

Implemented locally (not yet committed):

  • Consumer builds now use an exact git+file://...?rev=<HEAD> flake reference rather than path:, preserving Git provenance and excluding untracked worktree content.
  • Missing/null configurationRevision is parsed as empty and triggers one explicit legacy rebuild.
  • Staged, unstaged, and untracked worktree changes now block automatic updates.
  • Inline, detached, and emergency full-update activation paths verify the running configurationRevision before sending success.
  • Detached metadata carries the expected revision.
  • Revision lookup uses the explicit active-system /run/current-system/sw/bin/nixos-version path instead of relying on the curated service PATH.
  • README consumer flow was updated.

Verification:

  • Built Vega from exact commit ec42e29f34bcc22b2f8c026c2d20825b7628d586.
  • The resulting closure reported exactly that configurationRevision.
  • Bash syntax and diff checks pass.
  • ShellCheck passes at warning severity.
  • nix flake check passes for Electra, Lena, Vega, and Lyra.

Still required before closure:

  • Commit, push, and deploy.
  • Confirm a legacy missing-revision generation rebuilds once.
  • Confirm the activated generation reports the expected commit.
  • Confirm the following timer/manual run exits as a no-op.
  • Confirm a newer committed-but-undeployed HEAD triggers exactly one subsequent activation.
Implemented locally (not yet committed): - Consumer builds now use an exact `git+file://...?rev=<HEAD>` flake reference rather than `path:`, preserving Git provenance and excluding untracked worktree content. - Missing/null `configurationRevision` is parsed as empty and triggers one explicit legacy rebuild. - Staged, unstaged, and untracked worktree changes now block automatic updates. - Inline, detached, and emergency full-update activation paths verify the running `configurationRevision` before sending success. - Detached metadata carries the expected revision. - Revision lookup uses the explicit active-system `/run/current-system/sw/bin/nixos-version` path instead of relying on the curated service PATH. - README consumer flow was updated. Verification: - Built Vega from exact commit `ec42e29f34bcc22b2f8c026c2d20825b7628d586`. - The resulting closure reported exactly that `configurationRevision`. - Bash syntax and diff checks pass. - ShellCheck passes at warning severity. - `nix flake check` passes for Electra, Lena, Vega, and Lyra. Still required before closure: - [ ] Commit, push, and deploy. - [ ] Confirm a legacy missing-revision generation rebuilds once. - [ ] Confirm the activated generation reports the expected commit. - [ ] Confirm the following timer/manual run exits as a no-op. - [ ] Confirm a newer committed-but-undeployed HEAD triggers exactly one subsequent activation.
Author
Owner

Committed the revision-provenance repair as 70615e3 (fix: preserve auto-update Git revision provenance). It has not been pushed or deployed.

After push/deployment, use the checklist in the previous comment to confirm the initial legacy rebuild converges to a no-op and that committed-but-undeployed changes trigger exactly once.

Committed the revision-provenance repair as `70615e3` (`fix: preserve auto-update Git revision provenance`). It has not been pushed or deployed. After push/deployment, use the checklist in the previous comment to confirm the initial legacy rebuild converges to a no-op and that committed-but-undeployed changes trigger exactly once.
Author
Owner

Live Lyra validation exposed an ownership boundary missed by the original exact-revision test. The root-run updater pulled 47c7ff4, then Nix/libgit2 rejected git+file:///home/nimmo/nixos-config?rev=... because the repository is owned by nimmo. Lyra did not build or switch; active revision remains 70615e3 and a failure stamp was written.

Pending local fix: run only nixos-rebuild build as the configured repository owner, retaining root for profile mutation/activation; route the emergency full-update path through the same build-and-switch function. Verified on Lyra that the exact owner-run nixos-rebuild build succeeds and emits configurationRevision=47c7ff43b367db94b2cb0bf89528476892ce5384. Bash syntax and ShellCheck pass. Awaiting commit/deployment before repeating detached activation.

Live Lyra validation exposed an ownership boundary missed by the original exact-revision test. The root-run updater pulled `47c7ff4`, then Nix/libgit2 rejected `git+file:///home/nimmo/nixos-config?rev=...` because the repository is owned by `nimmo`. Lyra did not build or switch; active revision remains `70615e3` and a failure stamp was written. Pending local fix: run only `nixos-rebuild build` as the configured repository owner, retaining root for profile mutation/activation; route the emergency full-update path through the same build-and-switch function. Verified on Lyra that the exact owner-run `nixos-rebuild build` succeeds and emits `configurationRevision=47c7ff43b367db94b2cb0bf89528476892ce5384`. Bash syntax and ShellCheck pass. Awaiting commit/deployment before repeating detached activation.
Author
Owner

Ownership-boundary fix committed as 7eae768 (fix: build auto-updates as repository owner). Exact owner-run Lyra build and revision verification passed; Bash syntax and ShellCheck passed. The commit also appeared on origin/main immediately at commit time despite no explicit git push command being run; local hooks contain only inactive samples, so the publication mechanism remains unexplained.

Ownership-boundary fix committed as `7eae768` (`fix: build auto-updates as repository owner`). Exact owner-run Lyra build and revision verification passed; Bash syntax and ShellCheck passed. The commit also appeared on `origin/main` immediately at commit time despite no explicit `git push` command being run; local hooks contain only inactive samples, so the publication mechanism remains unexplained.
Author
Owner

Lyra exact-revision provenance passed during a genuine automatic update for f3d3bd547c094ab947ebf3867c66cf7538482228.

The root service pulled the candidate, runuser -u nimmo performed the exact git+file?...rev=f3d3bd5... build without an ownership error, detached activation completed, and post-switch verification reported the same full revision. Checkout HEAD and active configurationRevision now match. The remaining Lyra check is the scheduled 20:04 follow-up proving the matching revision exits before build.

✅ **Lyra exact-revision provenance passed during a genuine automatic update** for `f3d3bd547c094ab947ebf3867c66cf7538482228`. The root service pulled the candidate, `runuser -u nimmo` performed the exact `git+file?...rev=f3d3bd5...` build without an ownership error, detached activation completed, and post-switch verification reported the same full revision. Checkout HEAD and active `configurationRevision` now match. The remaining Lyra check is the scheduled 20:04 follow-up proving the matching revision exits before build.
Author
Owner

Vega and Lyra converged cleanly to exact revision b1efea8 on 2026-07-16. Both report checkout HEAD equal to deployed configurationRevision, no failure stamp, and clean helper state. The owner-build/provenance path has now survived multiple subsequent automatic updates.

Vega and Lyra converged cleanly to exact revision `b1efea8` on 2026-07-16. Both report checkout HEAD equal to deployed `configurationRevision`, no failure stamp, and clean helper state. The owner-build/provenance path has now survived multiple subsequent automatic updates.
Author
Owner

Electra completed the committed-but-not-deployed → no-op regression sequence on 2026-07-16.

First invocation:

  • checkout HEAD was efdfc4118572b195e219a1a5772f006f0b8e78f1
  • deployed revision was b1efea8...
  • updater explicitly detected the mismatch, built once, detached and activated once, preserved the igpu specialisation, and verified the full deployed revision as efdfc4118572b195e219a1a5772f006f0b8e78f1
  • success notification was delivered and no failure stamp remained

Immediate second invocation at 13:27:

  • pull reported Already up to date
  • updater logged Nothing changed in pull, system is current (HEAD=efdfc4118572b195e219a1a5772f006f0b8e78f1)
  • no build or activation was started
  • the no-update desktop notification was delivered
  • service deactivated successfully in 694 ms; only run.lock remained

Together with the previously observed no-op checks on Lyra and Vega and genuine detached revision verification across the consumers, all live criteria are now satisfied except the historical missing-legacy-revision migration case. That remaining case is safer to exercise hermetically under #56 than by deliberately removing provenance from a live system generation.

Electra completed the committed-but-not-deployed → no-op regression sequence on 2026-07-16. First invocation: - checkout HEAD was `efdfc4118572b195e219a1a5772f006f0b8e78f1` - deployed revision was `b1efea8...` - updater explicitly detected the mismatch, built once, detached and activated once, preserved the `igpu` specialisation, and verified the full deployed revision as `efdfc4118572b195e219a1a5772f006f0b8e78f1` - success notification was delivered and no failure stamp remained Immediate second invocation at 13:27: - pull reported `Already up to date` - updater logged `Nothing changed in pull, system is current (HEAD=efdfc4118572b195e219a1a5772f006f0b8e78f1)` - no build or activation was started - the no-update desktop notification was delivered - service deactivated successfully in 694 ms; only `run.lock` remained Together with the previously observed no-op checks on Lyra and Vega and genuine detached revision verification across the consumers, all live criteria are now satisfied except the historical missing-legacy-revision migration case. That remaining case is safer to exercise hermetically under #56 than by deliberately removing provenance from a live system generation.
Author
Owner

All in-scope implementation and live-validation criteria are complete. The sole remaining historical migration scenario has been transferred to #56 for safe hermetic coverage. Closing this issue.

All in-scope implementation and live-validation criteria are complete. The sole remaining historical migration scenario has been transferred to #56 for safe hermetic coverage. Closing this issue.
nimmo closed this issue 2026-07-16 13:30:25 +01:00
Sign in to join this conversation.
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nimmo/nixos-config#54
No description provided.