Light IPAM is a Go / PostgreSQL / Tailwind / Docker Compose IPAM application with
an optional, isolated network-discovery scanner agent. This guide captures the
working agreement. AGENTS.md is the canonical contract for humans and
AI agents alike (invariants, workflow, PR rules); for deeper context also read
README.md, docs/ARCHITECTURE.md, the
docs/SCANNER_* files, and the agent guides under docs/agent/.
New issues go through the structured forms (bug, feature, scanner/networking, ADR,
release).
- The web app stays unprivileged. No raw sockets, nmap, packet capture, or
trunked-network scanning in the app container. All privileged/active discovery
lives in the scanner agent — it alone may hold
NET_RAW. SNMP and NetBIOS/mDNS discovery are unprivileged unicast UDP and also live in the agent, never the app. See docs/SECURITY.md. - Strict CSP, no inline JS/CSS. Progressive enhancement only: every page
renders server-side, and any script is a same-origin file embedded under
internal/ui/static. - No large frameworks. Stdlib
net/httprouting,pgx/v5, embedded SQL migrations ininternal/db/migrations.go. A new external dependency is an explicit, reviewable decision (and usually an ADR). - IPv4 only, sparse address records, globally-blocked overlapping subnets, append-only audit log — keep these invariants intact.
- Branch from
main. - Implement the change.
- Verify (see below).
- Open a PR with
ghand fill in the template. - Wait for maintainer approval to merge — the maintainer says when to merge.
PRs are squash-merged; the branch is deleted and
mainis synced afterward.
For an architectural decision, add a numbered ADR under
docs/adr (next number, copy the existing format) and link it from the
PR. Update the docs that describe the area you changed — at minimum
docs/agent/PROJECT_STATE.md (the agent-facing "where
are we now?" snapshot), plus README.md,
docs/ROADMAP.md, CHANGELOG.md if it shipped, and
the relevant docs/SCANNER_*. The lightipam-doc-sync skill checks these stay
consistent.
Run before opening a PR (or run ./scripts/verify.sh, which does the first four; add
--docker for the image builds). See docs/agent/VALIDATION.md
for the tiered detail and troubleshooting; CI runs the same checks.
npm run build:css # regenerate the committed Tailwind CSS
go build ./... && go vet ./...
go test ./...
gofmt -l internal cmd # must print nothing
docker compose build # app image
docker compose --profile scanner build # agent image, if the agent changedgo build ./cmd/... can drop stray /scanner-agent and /server binaries at the
repo root; both are gitignored — do not commit them.
cmd/server— app entrypoint;cmd/scanner-agent— the agent;cmd/scanner-certs— dev mTLS material.internal/app— HTTP routes, handlers, form parsing, auth/session checks.internal/store— database query layer;internal/db— connection + embedded migrations.internal/ipam,internal/macaddr,internal/auth,internal/config— domain helpers.internal/ui— embedded templates (templates/), Tailwind source (assets/app.css), generated CSS (static/app.css), and same-origin JS (static/*.js).internal/scanner— protocol, allowlist validation, scan budget;internal/scanner/{agent,dispatch,orchestrator,pki}.
- Keep commits focused; write a clear subject line and a body explaining the why.
- Match the surrounding code's naming, comment density, and idioms.
- Run scanner builds with
go build -mod=readonly ./cmd/scanner-agentto confirm you have not silently pulled in a new dependency.