Wheelhouse docs

Working agreements#

AGENTS.md is the standing instruction for anyone changing this repository, and it opens with the reason the rest of it exists: you are working on a product with commercial ambitions — act like it: decisions get recorded, shortcuts get flagged, and the plan stays truthful. Six agreements follow, plus a protocol for which of three repositories a change belongs in and a boundary that keeps proprietary code proprietary. This page restates them, with the file to open in each case.

Read these first, in this order#

  1. PLAN.md — mission, architecture, milestones. The standing prompt.
  2. wheelhouse-infra's own AGENTS.md — the development environment, its access paths, and the shell traps that have already cost hours.
  3. HomelabInfra — the environment. The production router configuration there is the reference workload.

Which repository a change belongs in#

Kind of changeRepository
Product decisions, feature scope, UX, architectureThis one — PLAN.md, or docs/adr/NNN-*.md for a decision that changes it
Platform, build-host and deployment workwheelhouse-infra
Facts about the homelab: hosts, the production router, addressesHomelabInfra

Never duplicate; always link. A commit message that spans repositories names the sibling commit.

There is a fourth boundary inside this repository, and it is the one two people most often collide on: docs/ and the root Markdown files are the repository's own documentation and are versioned with the code. site/ is the published website and is built separately. Where the website carries something better, docs/ links to it rather than repeating it.

The six agreements#

1. Milestones are the backlog#

Work the lowest unfinished milestone in PLAN.md §10. A deviation is allowed; an unexplained one is not — edit PLAN.md in the same change with a one-line reason.

2. The definition of done#

A feature is done when all of this is true:

  • It works against a live router, not just against mocks.
  • validate.sh against that router is still green.
  • The API contract is typed and documented.
  • There are tests: unit, plus one end-to-end happy path.
  • The change carries a screenshot or a terminal capture.
  • PLAN.md's coverage matrix is updated if coverage changed.

3. The reference workload is sacred#

The production router's configuration — 19 forwards, 20 reservations, split DNS, PXE and CAKE — is the fixture set. A feature that cannot express it is not done. That is what keeps the product measured against a real network rather than against a demo.

4. Licence hygiene#

This is the rule with the least room for interpretation, because the company depends on it:

  • No GPL or AGPL code is copied into agent/ or ui/. Not a function, not a parser, not a constant table.
  • VyOS is driven through its API and its op-mode commands only.
  • Every compiled-in dependency is permissive, and each is recorded in docs/licenses.md with its version and licence.

Two of the three architecture decision records are, in part, a written justification for taking a dependency instead of writing a half-implementation. That is the shape the trade is meant to have: name the dependency, name its licence, record it.

The boundary is also what the image pipeline defends — The flavor and the branding hooks — and what the customer-facing statement on About Wheelhouse rests on.

5. Secrets#

Development credentials live in one place in the development environment and nowhere else. Nothing secret goes into git, an issue or a transcript. The dev instance password is to be rotated before any external collaborator gets access, because it appeared in a session log once.

The same discipline is enforced in code: the agent refuses a secret file that is group- or world-readable, and every secret has a --…-file form because a flag value is visible to every user on the box through /proc.

6. Honesty over demo-ware#

If a panel shows state, it must be real state from the router. Mocked data ships only behind an explicit --demo flag.

That single rule explains a surprising amount of the codebase: why an app health probe reports "not probed — this agent runs off-router" instead of a red cross it cannot justify, why packet capture answers 501 with the command to run by hand exactly where it cannot run — an agent off the router, or a router with no tcpdump — and captures everywhere else, and why a WireGuard peer that has never completed a handshake is drawn as such rather than as one with no traffic.

What a change owes the next person#

Beyond the six, three habits the code already assumes:

Comment the reasoning, not the mechanism. Nearly every non-obvious line in this repository carries a note saying what goes wrong without it. Those comments are what lets the code be changed by someone who was not there.

Assert, do not assume. The image pipeline patches a file and then checks the patch took; the branding hooks fail the build rather than ship a half-branded image; the ISO inspection refuses an artefact older than 48 hours. An upstream change should break the build loudly, on the machine that can still do something about it.

Name a regression test after the behaviour. TestAStaleCookieDoesNotMaskAValidBearerToken tells a reader what they broke from the failure line alone; TestBug47 does not.

See also#

Updated 2026-09-18 development contributing process licensing