# Working on Guard Notes for coding agents (and people) changing this repository. Guard watches logs and bans misbehaving addresses in Housecarl's ban lists (`../housecarl`, its docs/bans.md). It is the fourth of a set with Jarl (`../jarl`), Steward (`../steward`) and Housecarl, and copies their ways: Go, `CGO_ENABLED=0`, one YAML file, the same release process. It has no web UI and no database: bans are shown by Housecarl. ## Layout * `cmd/guard`: the one binary (cobra): `run` is the daemon, the rest are tools. * `internal/config`: guard.yaml, with `presets.yaml` and `example.yaml` embedded. A watch's preset is resolved here (`Watch.resolve`). * `internal/match`: patterns with ``; `Group` (IPv6 by prefix). * `internal/source`: files (polled tail -F), the journal (journalctl subprocess, `GUARD_JOURNALCTL` for tests), Housecarl's log. * `internal/bounty`: per-watch counts within a window. * `internal/daemon`: lines → matches → bounties → bans, the retry queue, the status socket, `never_ban`. * `internal/housecarl`: the API client (ban lists, bans, the log). * `internal/state`: the JSON state file. ## Ground rules * **Never trust a client's text for the address.** Preset patterns put `` where the program writes the address, after anything a client chose, anchored at the line's end where the format allows. Every preset has sample lines in `testdata/presets/NAME.txt` (the address to find, or `-`), including an attempt to plant an address; `TestPresets` runs them. * **No timestamp parsing.** Lines count when read (the journal's and Housecarl's carry their own time). * **Never ban on spoofable evidence by default**: UDP sources can be faked (`housecarl-drops` is TCP unless told otherwise; no preset for BIND's UDP refusals). * **Every user-visible change updates `CHANGELOG.md`** under `## [Unreleased]`, and the matching `docs/` page. * `make test` runs `go vet`, a `gofmt -l` check and the tests. ## Testing ```sh make test make e2e # with ../housecarl's lab: needs Docker (DOCKER_HOST=unix:///var/run/docker.sock here) ``` ## Git and releases As in Housecarl: commit only when asked, never push; branches `dev-X.Y.Z`; a release is a commit "Release X" setting `VERSION`, with the annotated tag `vX` ("Guard X"). Pushing the tag runs `.gitea/workflows/release.yml` (docs/development.md, "Releasing"). ## Shell hygiene Never kill processes by pattern (`pkill -f`): the pattern matches the shell running it. Find the PID and kill that.