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 bench, 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, bench, 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 the live vyoslab instance, not just against mocks.
  • validate.sh on the bench 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 on the bench 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 rather than pretending, and why the WireGuard page says handshake counters need something the agent does not do yet instead of showing a plausible number.

What a change owes the next person#

Beyond the six, three habits are visible throughout the tree and are worth adopting because the code already assumes them:

Comment the reasoning, not the mechanism. Nearly every non-obvious line in this repository carries a note saying what went wrong without it — the login limiter that ran after the decode, the health probe that only spoke HTTP and rolled back a good binary, the two postinst scripts where the stale one won. Those comments are why the code can be changed safely 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#

Checked against#

AGENTS.md · PLAN.md · docs/licenses.md · agent/main.go · agent/catalog.go · docs/adr/001-desired-state-file.md · docs/adr/002-oidc-client.md

Updated 2026-09-02 development contributing process licensing