Start Housecarl: the logo, the wordmark and the skeleton
Housecarl will be a firewall manager for nftables, built the way Jarl and Steward are: housecarld (a daemon with a REST API and web UI), hc (the CLI) and SQLite. - The logo: a carved Nordic doorway in Jarl's blue (artwork/logo.svg), with a small version without the carvings, lighter on dark backgrounds. scripts/logo.py builds the web UI's copies and scripts/banner.py the README banner. - The HOUSECARL wordmark in Jarl's and Steward's angular letters, with new H, O, U and C (assets/brand.js), and the UI's color tokens. - housecarld and hc print their version; the Makefile, version package, AGENTS.md, CHANGELOG and the design sketch (docs/design.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
54beb0bba3
24 files changed
+949
No files matched your search
@@ -0,0 +1,92 @@
|
||||
# Working on Housecarl
|
||||
|
||||
Notes for coding agents (and people) changing this repository. Read this
|
||||
first, then [docs/design.md](docs/design.md), the plan and its open
|
||||
questions.
|
||||
|
||||
Housecarl is a firewall manager for Linux: `housecarld` keeps the
|
||||
machine's nftables ruleset and serves a REST API and a web UI; `hc` is the
|
||||
CLI; SQLite holds everything. It is the third of a set with Jarl (the BIND
|
||||
manager, `../jarl`) and Steward (the DHCP server, `../steward`) and copies
|
||||
their ways: the same auth, socket and web UI helpers, the same release
|
||||
process, the same look. When in doubt, do it the way Jarl and Steward do.
|
||||
Go module `housecarl`, `CGO_ENABLED=0`, Linux only for housecarld.
|
||||
|
||||
Housecarl is at its start: only the version commands, the build and the
|
||||
brand exist. Most rules below are for what is coming.
|
||||
|
||||
## Ground rules
|
||||
|
||||
* **The database is the source of truth.** The ruleset is rendered from
|
||||
it; never read nftables' state back as configuration (an importer would
|
||||
be the only exception).
|
||||
* **Every change goes through one engine**: edit a copy of the
|
||||
configuration, validate the whole result, render, check with
|
||||
`nft -c -f`, apply with `nft -f`, and save the objects, the history
|
||||
entry and the audit record together. Never write to the store from a
|
||||
handler.
|
||||
* **Housecarl's own table only.** Write `inet housecarl` and nothing
|
||||
else; never flush the whole ruleset (Docker, libvirt and others keep
|
||||
theirs).
|
||||
* **Don't lock the user out.** Changes to the rules for the machine itself
|
||||
are applied on probation and rolled back unless confirmed
|
||||
(docs/design.md).
|
||||
* **Every user-visible change updates `CHANGELOG.md`** under
|
||||
`## [Unreleased]`, and the matching `docs/` page in the same change.
|
||||
* **Errors** say what is wrong and how to fix it, naming the object.
|
||||
* **Schema changes** append a migration; never edit a shipped one.
|
||||
* `make test` runs `go vet` and a `gofmt -l` check. `goimports` isn't
|
||||
installed, so fix imports by hand.
|
||||
|
||||
## The logo and wordmark
|
||||
|
||||
* The masters are `artwork/logo.svg` (the carved doorway) and
|
||||
`artwork/logo-small.svg` (without its carvings, for under about 64 px).
|
||||
Each is one evenodd path in a shared viewBox; their color comes from
|
||||
CSS (`--logo`, lighter in the dark theme).
|
||||
* `make logo` (`scripts/logo.py`) copies them into the web UI
|
||||
(`assets/logo.js`, and `assets/logo.svg`, the favicon, from the small
|
||||
one) and runs `scripts/banner.py`, which rebuilds `artwork/banner.svg`.
|
||||
Never edit those outputs by hand.
|
||||
* The wordmark's letters are paths in `assets/brand.js`, in the angular
|
||||
style of Jarl's and Steward's (A, R and L are Jarl's, S and E Steward's).
|
||||
`banner.py` reads them from there.
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
make test # vet + gofmt check + unit tests
|
||||
```
|
||||
|
||||
## Web UI rules
|
||||
|
||||
As in Jarl and Steward:
|
||||
|
||||
* Build DOM only with `h()` from `ui.js`, never `innerHTML`.
|
||||
* The CSP is `self` only: no inline styles or scripts. Use a class, or set
|
||||
`el.style.prop`.
|
||||
* Colors are the CSS custom properties in `style.css`, with light and dark
|
||||
values; reuse them.
|
||||
* Rebuild housecarld after editing, since the files are embedded.
|
||||
* Function over polish. Leave pick-list checkboxes unticked by default.
|
||||
|
||||
## Git and releases
|
||||
|
||||
The maintainer's rules:
|
||||
|
||||
* **Commit only when asked. Never push.** The maintainer pushes, to Gitea
|
||||
at gitea.adbraun.lol.
|
||||
* **Branches** are `dev-X.Y.Z`, never named like a tag.
|
||||
* **A release** is a commit "Release X": it sets `VERSION`, updates the
|
||||
README status line, and (for a final release) moves `[Unreleased]` to
|
||||
`## [X] - YYYY-MM-DD`. The annotated tag is `vX` with message
|
||||
"Housecarl X".
|
||||
|
||||
## Shell hygiene
|
||||
|
||||
* **Never kill processes by pattern** (`pkill -f`). The pattern matches
|
||||
the shell running it. Find the PID with `ps` and kill that.
|
||||
* **Run long-lived test servers in the background mode of your tool**, not
|
||||
with `&` in a shell that exits.
|
||||
* **Never apply a test ruleset to this machine's own nftables.** Test in a
|
||||
network namespace or a container.
|
||||
Reference in new issue
Block a user