Skip to content

feat(cli): pearlite bootstrap subcommand wires Engine::bootstrap#57

Merged
UnbreakableMJ merged 1 commit into
mainfrom
feat/cli-bootstrap
Apr 28, 2026
Merged

feat(cli): pearlite bootstrap subcommand wires Engine::bootstrap#57
UnbreakableMJ merged 1 commit into
mainfrom
feat/cli-bootstrap

Conversation

@UnbreakableMJ

Copy link
Copy Markdown
Contributor

Summary

Surfaces ADR-0012's bootstrap entry point to operators. Verifies the operator-supplied Determinate installer script against the host's declared SHA-256 pin, runs the installer if nix is missing, and writes /etc/nix/nix.conf with the experimental-features minimum (ADR-0013).

  • New Command::Bootstrap { host_file, installer_script, nix_conf } in args.rs. installer_script is required (operator pre-downloads — URL-fetch is a follow-up). nix_conf defaults to /etc/nix/nix.conf.

  • dispatch_bootstrap calls Engine::bootstrap with the per-host declared SHA and renders BootstrapOutcome in the envelope data.

  • bootstrap_error_payload maps every BootstrapError variant to a typed error code with a runnable hint:

    • NIX_NOT_DECLARED — host has no [nix.installer] block
    • NIX_INSTALLER_SHA256_MISMATCH — declared vs. observed SHA (ADR-004)
    • NIX_INSTALLER_FAILED — script exec, missing shell, or non-zero exit
    • BOOTSTRAP_NIX_CONF_WRITE_FAILED / BOOTSTRAP_NIX_CONF_READ_FAILED
    • BOOTSTRAP_NICKEL_FAILED

    All are class=preflight, exit=2 — bootstrap halts before mutating state, so even installer failures are recoverable from the operator's perspective.

  • RunContext gains nix_installer: Box<dyn NixInstaller>. main.rs wires LiveNixInstaller; the six dispatch test sites wire MockNixInstaller. Two new dispatch tests cover the happy path and the NIX_NOT_DECLARED error.

The next chunk lands the apply-side preflight check (NIX_NOT_INSTALLED when home_manager.enabled = true and nix --version fails — per ADR-0012 decision 3).

Test plan

  • cargo test --workspace --all-features — 314 passing (+2 new)
  • cargo clippy --workspace --all-targets --all-features -- -D warnings — clean
  • cargo fmt --all -- --check — clean
  • scripts/ci/check-spdx.sh — clean
  • pearlite-audit check . — 1 check, 0 violations
  • CI green on T1 / T2 / T3

🤖 Generated with Claude Code

Surfaces ADR-0012's bootstrap entry point to operators. Verifies the
operator-supplied Determinate installer script against the host's
declared SHA-256 pin, runs the installer if nix is missing, and writes
/etc/nix/nix.conf with the experimental-features minimum (ADR-0013).

- New `Command::Bootstrap { host_file, installer_script, nix_conf }`
  in args.rs. `installer_script` is required (operator pre-downloads;
  URL-fetch is a follow-up). `nix_conf` defaults to /etc/nix/nix.conf.
- `dispatch_bootstrap` calls Engine::bootstrap with the per-host
  declared sha and renders BootstrapOutcome as the envelope `data`.
- `bootstrap_error_payload` maps every BootstrapError variant to a
  typed error code with a runnable hint:
  - NIX_NOT_DECLARED — host has no [nix.installer] block
  - NIX_INSTALLER_SHA256_MISMATCH — declared vs. observed sha (ADR-004)
  - NIX_INSTALLER_FAILED — script exec, missing shell, or non-zero exit
  - BOOTSTRAP_NIX_CONF_WRITE_FAILED / BOOTSTRAP_NIX_CONF_READ_FAILED
  - BOOTSTRAP_NICKEL_FAILED
  All are class=preflight, exit=2 — bootstrap halts before mutating
  state, so even installer failures are recoverable from the operator's
  perspective.
- RunContext gains `nix_installer: Box<dyn NixInstaller>`. main.rs
  wires LiveNixInstaller; the six dispatch test sites wire
  MockNixInstaller. Two new dispatch tests cover the happy path and
  the NIX_NOT_DECLARED error.

Tests: 314 passing (+2). Clippy clean. fmt clean. audit clean.
The next chunk lands the apply-side preflight check (NIX_NOT_INSTALLED
when home_manager.enabled = true and `nix --version` fails).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@UnbreakableMJ
UnbreakableMJ merged commit 2f83813 into main Apr 28, 2026
3 checks passed
@UnbreakableMJ
UnbreakableMJ deleted the feat/cli-bootstrap branch April 28, 2026 22:30
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