Files
jakman85andClaude Opus 5.5 250fb54154 docs: bring the specification in line with the accepted implementation
The operator ruled the implementation repo's main (50c8719) the latest
and accepted state. Sync the spec to it.

Accepted changes are reflected: one bare-metal environment, TrueNAS bulk
storage, R2 off-cluster backup, CloudNativePG, single-node VPN gateway
with Cilium fail-closed, inbound WireGuard, per-app auth sidecars,
Renovate, the CI gate as approver, and the pm-agent. New ADR-0017..0025;
ADR-0016 corrected and accepted; R-* IDs unchanged, eight amended.

Where the implementation has simply not met a requirement, the
requirement stands and the shortfall is recorded in docs/16-known-gaps.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-08 22:46:00 -06:00

93 lines
5.2 KiB
Markdown

# Contributing & Development Workflow
How work is version-controlled for this repository. This complements the governance rules in
[`AGENTS.md`](AGENTS.md) (what agents may/may not change) — this file covers *how changes land in
git*.
## This repo (the spec)
The spec repo is hosted on the platform's own Gitea (`gitea.home.keithjackson.dev`).
- **No work on `main`.** `main` holds only reviewed, completed work.
- **Every change is a feature branch**, merged into `main` by pull request. Only the human operator
merges a spec change (R-TEST-06).
- **Merge a coherent batch.** Every spec commit on `main` must be adopted by the implementation (see
below), so small drive-by commits each carry a real cost.
### Branch naming
- `feature/<slug>` — new capability or spec area
- `fix/<slug>` — corrections
- `docs/<slug>` — documentation-only changes
- `chore/<slug>` — tooling/repo housekeeping
The implementation repo has its own convention (`feat/`, `fix/`, `docs/`, `chore/`).
### Commit hygiene
- Small, single-responsibility commits; imperative subject lines.
- Reference requirement IDs / ADR numbers where relevant (they're stable across file moves).
- **Never commit plaintext secrets** — secrets are SOPS-encrypted only ([`docs/07-security-and-secrets.md`](docs/07-security-and-secrets.md));
the [`.gitignore`](.gitignore) guards common leak paths but is not a substitute for care.
## The implementation repo
The [implementation repo](https://gitea.home.keithjackson.dev/Home-Network/home-network-k3s-impl) is
CI/CD-driven GitOps. Its `CLAUDE.md` is the delivery contract for how work lands there; intent is in
[`docs/05-gitops-and-delivery.md`](docs/05-gitops-and-delivery.md) and
[ADR-0024](decisions/adr-0024-delivery-authority-ci-gate.md).
- Every change is branch → PR → **merge gate green** → merge. Direct pushes to `main` are rejected.
- The CI gate is the approver; sensitive paths also need a non-author review.
- Flux reconciles the cluster from that repo's `main`.
- Each unit of work records a dated handoff entry under that repo's `decisions/`. Those are
implementation handoffs; this repo's `decisions/` holds ADRs.
### Where status lives
**`./conformance/run.sh --status` in the implementation repo is the live status surface**: per
requirement, whether it is implemented, reconciled, has an executable test, and has recorded proof.
[`docs/16-known-gaps.md`](docs/16-known-gaps.md) is a dated snapshot of the shortfalls at one point in
time. [`agents/task-board.md`](agents/task-board.md) is a frozen historical seed.
## Adopting a spec change in the implementation
The implementation pins the exact spec commit it is built against, in `ci/SPEC_PIN`. Its
spec-immutability check (R-TEST-06) fails when a spec checkout has uncommitted changes or its `HEAD`
differs from the pin, so every movement of spec `main` is an explicit, reviewed act. On **every**
spec change:
1. **Merge to spec `main`.** The human operator does this. Until step 2 lands, a local gate against
a checkout of the new `main` reports blocked.
2. **Bump the pin** in an implementation PR, to the new spec `main` commit. `ci/` is a sensitive path,
so the PR needs the operator's review or the operator's own override; an agent never overrides
for itself.
3. **Reconcile requirement IDs in that same PR.** The registry
(`conformance/requirements/registry.yaml`) mirrors the `R-*` IDs in
[`docs/00-vision-and-scope.md`](docs/00-vision-and-scope.md):
- A **new ID** must arrive with a requirement-tagged test, or be listed as a documented gap in the
harness. Adding the registry entry attributes that ID to the change, so an uncovered ID blocks
the merge; a safety-critical ID also needs an L3 test.
- An **amended requirement** needs only its abridged registry summary updated, when the meaning
changed.
- A **retired ID** leaves the registry, every test label, and the gate's path-to-requirement map
together. IDs are never renumbered or reused.
4. **Write the handoff entry** for the adoption.
Some implementation checks read spec text when a spec checkout is present: the auditability section
of [`docs/07`](docs/07-security-and-secrets.md), the Phase 7 entry in
[`roadmap/phases.md`](roadmap/phases.md), and the requirement definitions in `docs/00`. Change those
structures knowingly.
## The bootstrapping caveat (self-hosted git is circular)
Gitea runs *on* the cluster that Flux reconciles *from* Gitea — a chicken-and-egg. Handling:
- Bring the cluster up from a **bootstrap source** (an out-of-band copy of the repo), stand up Gitea,
then **cut Flux's source over to Gitea** ([`docs/05-gitops-and-delivery.md`](docs/05-gitops-and-delivery.md)).
- Because a cluster loss would take its own git host with it, **Gitea is DR-critical**: its repos are
backed up **off-cluster** ([`docs/04-storage-and-state.md`](docs/04-storage-and-state.md)), and an
off-cluster mirror of the platform repo is kept so the platform can always be rebuilt from a source
that outlives the cluster.
## What does not change
- Specs remain **human-owned and immutable to agents** ([`AGENTS.md` §11](AGENTS.md)) regardless of
where git is hosted.
- "Done" remains a **green, reproducible conformance test**, not "merged."