Files
guard/AGENTS.md
T
abrown38andClaude Opus 5.5 941d4fb10d Release setup: tarballs, Gitea workflow, apt registry
make dist builds tarballs for linux/amd64 and linux/arm64. A pushed v*
tag runs .gitea/workflows/release.yml, which checks the tag against
VERSION and the CHANGELOG, tests, builds the tarballs and the .debs
(amd64, arm64) and publishes them with scripts/gitea-release.sh: a Gitea
release, and the .debs in the Debian registry (stable, or testing for a
release candidate). As in Housecarl and Steward; no cli-dist, Guard is
Linux only. docs/development.md has the steps, docs/install.md the apt
source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 16:44:58 +01:00

2.5 KiB

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 <IP>; 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 <IP> 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

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.