diff --git a/.claude/devil-advocate.md b/.claude/devil-advocate.md new file mode 100644 index 0000000..16195f6 --- /dev/null +++ b/.claude/devil-advocate.md @@ -0,0 +1,28 @@ +# Devil's Advocate Review — Project Conventions + +## Critical rules (must never be violated) + +- **Never update `system.stateVersion`** — it must remain at the original installation version. NixOS upgrades are done by updating the `channel` file, not `stateVersion`. +- **Never modify `secrets.yaml` directly** — these are SOPS-encrypted. Changes must be made via `nix-shell -p sops --run 'sops '`. +- **No plaintext secrets in Nix files** — passwords, API keys, tokens, and private keys must use `sops.secrets`, never hardcoded strings. + +## Architecture rules + +- **Explicit module imports only** — no wildcard or directory-level imports. Each module must be imported by its explicit path. +- **Host structure** — each host in `hosts//` must have `configuration.nix` and `hardware-configuration.nix`. Symlinks `fleet.nix` and `utils/` point to root level. +- **Shared modules** go in `utils/modules/`, not duplicated across hosts. +- **Custom packages** in `utils/pkgs/` must include an `update.sh` script for automated version updates. + +## Code style + +- **Two-space indentation** in all Nix files. +- **Lower kebab-case** for file and directory naming. +- **Conventional Commits** format: `fix:`, `feat:`, `chore:`, with optional scope by host (e.g., `fix(mail):`). +- No "Generated with Claude Code" or "Co-Authored-By: Claude" footers in commits. + +## Common review checks + +- New network services must have corresponding `networking.firewall.allowedTCPPorts` or `allowedUDPPorts` entries. +- New `sops.secrets.` references must have a corresponding entry in the host's `secrets.yaml` (or the relevant module's `secrets.yaml`). +- Changes to `utils/` affect all hosts — verify cross-host compatibility. +- Package modifications should be testable with a direct `nix-build`, not just `test-configuration`. diff --git a/.claude/lint-fixer.md b/.claude/lint-fixer.md new file mode 100644 index 0000000..93af5e7 --- /dev/null +++ b/.claude/lint-fixer.md @@ -0,0 +1,26 @@ +# Lint Fixer Instructions + +## Formatter + +This project uses **nixpkgs-fmt** for Nix file formatting. + +## How to run + +1. Find changed `.nix` files: + ```bash + git diff --name-only --diff-filter=d HEAD | grep '\.nix$' + ``` +2. Format only those files: + ```bash + nix run nixpkgs#nixpkgs-fmt -- ... + ``` +3. Stage any formatting changes: + ```bash + git add + ``` + +## Notes + +- Only format files that were actually modified, not the entire repo. +- There is no `.editorconfig` or other formatter config; `nixpkgs-fmt` uses its own defaults. +- Non-Nix files do not need formatting. diff --git a/.claude/secret-scanner.md b/.claude/secret-scanner.md new file mode 100644 index 0000000..34333af --- /dev/null +++ b/.claude/secret-scanner.md @@ -0,0 +1,35 @@ +# Secret Scanner Allowlist + +## False positive patterns to ignore + +### SOPS-encrypted secrets files +All `secrets.yaml` files in this repo are **SOPS-encrypted** (not plaintext). They contain encrypted ciphertext, not actual secrets. Ignore: +- `hosts/*/secrets.yaml` +- `hosts/*/modules/*/secrets.yaml` +- `utils/modules/*/secrets.yaml` +- Any `.yaml` file matching a `path_regex` in `.sops.yaml` + +### Age public keys +The file `.sops.yaml` contains **age public keys** (prefix `age1...`). These are public keys used for encryption, not private keys. Ignore: +- Age public keys (`age1...`) in `.sops.yaml` +- Age public key references (YAML anchors like `&dominik`, `&fw`, etc.) in `.sops.yaml` + +### Nix hashes and store paths +Nix derivations contain SHA256/SRI hashes for source integrity verification. These are not secrets. Ignore: +- `sha256` / `hash` attributes in `.nix` files (e.g., `sha256 = "sha256-..."` or `hash = "sha256-..."`) +- `npmDepsHash`, `vendorHash`, `cargoHash`, and similar dependency hashes +- Nix store paths (`/nix/store/...`) +- `nix-prefetch-url` output hashes +- SRI hashes (`sha256-...`, `sha512-...`) + +### sops-nix module configuration +Nix files reference sops secret paths as configuration, not actual secret values. Ignore: +- `sops.secrets.` attribute sets +- `sopsFile` path references +- `key` attributes within `sops.secrets` blocks (these are YAML key paths, not cryptographic keys) +- `neededForUsers` attributes + +### Other safe patterns +- `flake.lock` — contains Nix flake input hashes (integrity, not secrets) +- SSH **public** key strings in NixOS configuration (e.g., `openssh.authorizedKeys.keys`) +- Wireguard **public** keys in NixOS configuration diff --git a/.claude/test-runner.md b/.claude/test-runner.md new file mode 100644 index 0000000..63373d0 --- /dev/null +++ b/.claude/test-runner.md @@ -0,0 +1,34 @@ +# Test Runner Instructions + +## Determine affected hosts + +Run `git diff --name-only HEAD` (or `git diff --name-only` for unstaged changes) to find changed files. + +### Scope rules + +- If changes are **only** under `hosts//`, test only that specific host: + ```bash + ./scripts/test-configuration + ``` +- If changes touch `utils/`, root-level `.nix` files, or any shared configuration, test **all** hosts: + ```bash + for host in amzebs-01 dev fw mail nas nb web-arm; do + ./scripts/test-configuration "$host" + done + ``` + +### Custom package changes + +If any files under `utils/pkgs//` were modified, also build the package directly: + +```bash +nix-build -E 'with import { overlays = [ (import ./utils/overlays/packages.nix) ]; config.allowUnfree = true; }; ' +``` + +This catches build failures that `test-configuration` (evaluation-only) would miss. + +## Notes + +- Each `test-configuration` run performs a `nix-instantiate` dry-build (evaluation only, no binary builds). +- A non-zero exit code from any host means the test failed. +- Hosts: `amzebs-01`, `dev`, `fw`, `mail`, `nas`, `nb`, `web-arm`.