banger/AGENTS.md
Thales Maciel b1fbf695ca
ssh-config: narrow the legacy-dir cleanup so it can't delete a user key
Bug: syncVMSSHClientConfig did os.RemoveAll on $ConfigDir/ssh every
daemon Open. The intent was to migrate off the pre-opt-in layout,
where banger used to write $ConfigDir/ssh/ssh_config. But a user who
sets ssh_key_path = "~/.config/banger/ssh/id_ed25519" in config.toml
has their key live exactly in that dir — and the scrub deletes it
along with every other file in the tree.

This is the same class of bug that cost the default key until
ebe6517 moved it to StateDir, but that fix was scoped to the default
path. A configured ssh_key_path pointed under the legacy dir still
dies.

Fix: replace os.RemoveAll with a narrow two-step cleanup:

 1. Skip the cleanup entirely when the configured ssh_key_path
    resolves under the legacy dir. A user who pointed banger at a
    key there must keep the enclosing directory.
 2. Otherwise, os.Remove the specific legacy file ($ConfigDir/ssh/
    ssh_config) and then os.Remove the directory. The second
    os.Remove fails with ENOTEMPTY if the dir still holds anything
    (e.g. a user-managed sibling file we don't own). Both errors
    are swallowed — this is best-effort migration, not a hard
    failure.

Tests pin all three paths: user key under legacy dir survives,
legacy dir empties and is removed when the user moved on, and a
user-managed sibling file in the legacy dir is preserved.

Also fix stale doc claims in README.md and AGENTS.md — both still
pointed at the old ~/.config/banger/ssh/id_ed25519 default, which
moved to ~/.local/state/banger/ssh/id_ed25519 in ebe6517.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 16:31:07 -03:00

4 KiB

Repository Guidelines

Always run make build before commit.

Project Structure

  • cmd/banger, cmd/bangerd, and cmd/banger-vsock-agent are the three binaries. The first two are user-facing; the third is a companion that ships inside each guest VM.
  • internal/ contains the daemon, CLI, RPC, storage, Firecracker integration, and guest helpers.
  • internal/daemon/ is the composition root; pure helpers live in its subpackages (opstate, dmsnap, fcproc, imagemgr, workspace). See internal/daemon/ARCHITECTURE.md.
  • internal/imagecat/ and internal/kernelcat/ embed the image + kernel catalogs.
  • images/golden/ is the Dockerfile for the debian-bookworm catalog entry.
  • scripts/ contains manual helper workflows for rootfs, kernel, and bundle preparation.
  • build/bin/ is the canonical source-checkout build output.
  • build/manual/ is the canonical source-checkout location for manual rootfs/kernel artifacts.

Build and Test

  • make build builds ./build/bin/banger, ./build/bin/bangerd, and ./build/bin/banger-vsock-agent.
  • make test runs go test ./....
  • make lint runs gofmt -l, go vet ./..., and shellcheck --severity=error on scripts/*.sh. Run before commits.
  • ./build/bin/banger doctor checks host readiness.
  • ./build/bin/banger vm run is the primary user-facing entry point — auto-pulls the default image + kernel from the catalogs if missing.
  • ./build/bin/banger image pull <name> uses the bundle catalog (fast) when <name> is a catalog entry, or falls through to the OCI path for arbitrary registry refs. See docs/image-catalog.md and docs/oci-import.md.
  • ./build/bin/banger image register ... registers an unmanaged host-side image stack.
  • ./build/bin/banger image promote <image> copies an unmanaged image into daemon-owned managed artifacts.
  • scripts/make-generic-kernel.sh builds a Firecracker-optimized vmlinux from upstream sources. scripts/publish-kernel.sh <name> publishes it to the kernel catalog.
  • scripts/publish-golden-image.sh rebuilds + publishes the golden image bundle and patches the image catalog.

Image Model

  • Managed images own the full boot set: rootfs, optional work-seed, kernel, optional initrd, and optional modules.
  • The image catalog ships pre-built bundles. vm run auto-pulls the default catalog entry; image pull <name> can be invoked explicitly.
  • default_image_name defaults to debian-bookworm. On miss, the daemon auto-pulls from imagecat before surfacing "not found".
  • Kernel references follow the same auto-pull pattern against kernelcat.

Config

  • Config lives at ~/.config/banger/config.toml.
  • Firecracker comes from PATH by default, or firecracker_bin.
  • SSH uses ssh_key_path or an auto-managed default key at ~/.local/state/banger/ssh/id_ed25519.

Coding Style

  • Prefer small, direct Go code and standard library solutions.
  • Keep shell scripts strict with set -euo pipefail.
  • Use gofmt for Go formatting.
  • When a CLI accepts either an inline string or a file input, always prefer the file-based form.
  • For shell commands and AI/LLM tooling, prefer passing files as input whenever the CLI allows it.
  • Create temporary files as needed to follow the file-first rule.
  • Examples: use git commit -F <file> instead of git commit -m <message>, and use prompt files instead of inline prompt strings when invoking LLM CLIs.

Testing Guidance

  • Primary automated coverage is go test ./... (wired through make test).
  • make coverage runs the suite with -coverpkg=./... and prints per-package averages plus a total; make coverage-html writes a browsable report to coverage.html; make coverage-total prints just the total (for scripts/CI).
  • For lifecycle changes, smoke-test with vm run end-to-end (covers create + start + boot + ssh).
  • If guest provisioning changes, document whether existing images must be rebuilt or recreated.

Security

  • Do not commit secrets.
  • VM workflows require sudo and /dev/kvm.
  • The default SSH key is local configuration, not a checked-in runtime artifact.