fix(installer): generate state.json from lib/state-schema.nix

Closes the last source-of-truth split after the state-defaults
centralization batches. The installer's heredoc was the only remaining
place that hardcoded the state.json literal — adding a default to the
schema previously required a parallel edit here, and silent drift was
exactly the bug class we kept fixing.

Before:

  cat > /mnt/etc/nixos/state.json <<JSON_EOF
  {
    "theme": "nord",
    "timezone": "${_state_tz}",
    "dns": "DHCP",
    ...
  }
  JSON_EOF

After:

  nix eval --impure --raw --expr "
    let
      flake = builtins.getFlake \"$NOMARCHY_REPO\";
      lib = flake.inputs.nixpkgs.lib;
      schema = import \"$NOMARCHY_REPO/lib/state-schema.nix\"
                 { inherit lib; };
      state = schema.system // { timezone = \"$_state_tz\"; };
    in builtins.toJSON state
  " | nrun jq '.' > /mnt/etc/nixos/state.json

Uses the flake's own pinned `inputs.nixpkgs` (matching what the rest of
Nomarchy resolves against), so the schema evaluates with the same `lib`
the consumer modules see. `nrun jq` pretty-prints for human inspection.

Behavioural notes:
- Output is identical to the old heredoc modulo alphabetical key
  ordering — `builtins.toJSON` sorts keys, the heredoc was in
  declaration order. Toggle scripts read/write via `jq` so it's
  invisible to them.
- Dry-run path unchanged. `execute_dry_run` already bind-mounts a fake
  /mnt for the generator; the generator's absolute paths still resolve.
- New schema fields show up automatically on the next install; no
  parallel edit needed.
- `bash -n` + `shellcheck --severity=error` clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-05-18 18:18:25 +01:00
parent d264371b46
commit 03968e5d0d
2 changed files with 22 additions and 22 deletions

View File

@@ -1799,30 +1799,29 @@ EOF
}
EOF
# state.json — consumed by core/system/state.nix at every nixos-rebuild and
# mutated by toggle scripts (nomarchy-tz-select, nomarchy-setup-fido2,
# state.json — consumed by core/system/state.nix at every nixos-rebuild
# and mutated by toggle scripts (nomarchy-tz-select, nomarchy-setup-fido2,
# nomarchy-toggle-hybrid-gpu, nomarchy-wifi-powersave, ...). Those scripts
# `jq` the file in place and fail hard if it doesn't exist or isn't valid
# JSON, so a fresh install MUST ship one. Shape must match lib/state-schema.nix.
# Quoted heredoc — no shell expansion except the explicit $TIMEZONE below.
# `jq` the file in place and fail hard if it doesn't exist or isn't
# valid JSON, so a fresh install MUST ship one.
#
# Source of truth: lib/state-schema.nix. We eval its `system` block and
# overlay the installer-chosen timezone, so this generator no longer
# drifts from the schema or the *.nix consumers — the previous heredoc
# was the last source-of-truth split after the state centralization.
# Adding a new default in the schema now reaches the installer without
# any further plumbing.
local _state_tz="${TIMEZONE:-UTC}"
cat > /mnt/etc/nixos/state.json <<JSON_EOF
{
"theme": "nord",
"timezone": "${_state_tz}",
"dns": "DHCP",
"customDns": [],
"wifi": {
"powersave": true
},
"features": {
"fingerprint": false,
"fido2": false,
"hybridGPU": false,
"makima": false
}
}
JSON_EOF
nix --extra-experimental-features 'nix-command flakes' eval \
--impure --raw \
--expr "
let
flake = builtins.getFlake \"$NOMARCHY_REPO\";
lib = flake.inputs.nixpkgs.lib;
schema = import \"$NOMARCHY_REPO/lib/state-schema.nix\" { inherit lib; };
state = schema.system // { timezone = \"$_state_tz\"; };
in builtins.toJSON state
" | nrun jq '.' > /mnt/etc/nixos/state.json
}
# ============================================================================