Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .claude/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,37 @@ The format is based on the regulated environment requirements:

---

## [2026-05-31 00:00] - Adopt Architecture Driven Development (ADD) methodology

**Author:** Erick Bourgeois

### Changed
- `docs/adr/`: new directory for Architecture Decision Records —
`template.md`, `README.md` (conventions + index), and
`0001-adopt-architecture-driven-development.md` (Accepted) recording the
adoption decision and rationale.
- `.claude/rules/architecture-driven-development.md`: new rule file defining the
ADD methodology (`ADR → CALM → TDD → implement → docs`), adapted to 5-Spot
(`src/crd.rs` source of truth, `make crds`/`crddoc`, CALM targets,
`cargo-quality`/`sync-docs`, roadmaps external at `~/dev/roadmaps/`).
- `.claude/CLAUDE.md`: added ADD as the governing methodology (new section + as
the first "CRITICAL Coding Pattern"); links to the rule file and ADR-0001.
- `.claude/SKILL.md`: added an ADD gate to the top of `pre-commit-checklist`
(ADR written/indexed; CALM updated or "no CALM impact"; ADR precedes code).

### Why
5-Spot already had strong TDD and a CALM model, but no first-class, ordered way
to record *why* an architecturally significant change was made before building
it. ADD (per the sibling banlieue project) layers ADR + CALM on top of TDD so
decisions are auditable and traceable — fitting the regulated context — instead
of reconstructed from diffs and changelog entries. See ADR-0001.

### Impact
- [ ] Breaking change
- [ ] Requires cluster rollout
- [ ] Config change only
- [x] Process / documentation only

## [2026-05-30 12:00] - Revert docs deploy trigger to release:published (CodeQL: pwn-request + cache poisoning)

**Author:** Erick Bourgeois
Expand Down
20 changes: 20 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
> **Project Focus**: Time-based scheduling of physical machines in k0smotron clusters. This controller manages machine lifecycle (add/remove from cluster) based on configurable time schedules with timezone support.
>
> **CRITICAL Coding Patterns**:
> - **Architecture Driven Development (ADD)**: For any architecturally significant change, architecture is decided, recorded, and visualized BEFORE code: `ADR → CALM → TDD → implement → docs`, in that order. ADRs (`docs/adr/`) and CALM diagrams are first-class deliverables, equal to code and tests. Full rule: `.claude/rules/architecture-driven-development.md`. ADD wraps TDD below — it does not replace it.
> - **Test-Driven Development (TDD)**: ALWAYS write tests FIRST before implementing functionality. Write failing tests that define the expected behavior, then implement code to make tests pass. This ensures all code is testable and has comprehensive test coverage from the start.
> - **Event-Driven Programming**: In Kubernetes controller development, ALWAYS use event-driven programming (e.g., "watch" on kube API) as opposed to polling. Controllers must react to cluster state changes efficiently.
> - **Early Returns**: Use as few `else` statements as possible. Return from functions as soon as you can to minimize nesting and improve code clarity (see Early Return / Guard Clause Pattern section).
Expand All @@ -14,6 +15,25 @@

---

## 🏛️ GOVERNING METHODOLOGY: Architecture Driven Development (ADD)

**5-Spot is built ADR-first. Architecture is decided, recorded, and visualized BEFORE code.** For any architecturally significant change, follow this order — full details in `.claude/rules/architecture-driven-development.md`:

```
ADR → CALM → TDD → implement → docs
```

1. **ADR** — record the decision in `docs/adr/NNNN-title.md` (Status / Context / Decision / Consequences) from `docs/adr/template.md`; update the index in `docs/adr/README.md`.
2. **CALM** — model it in `docs/architecture/calm/architecture.json`; `make calm-validate` + `make calm-diagrams`. *(Process-only decisions have no CALM impact — say so in the ADR and skip this step.)*
3. **TDD** — only then write failing tests, then the minimum implementation (`tdd-workflow` skill); `cargo-quality` gate.
4. **Docs** — CHANGELOG (`**Author:**`) + affected `docs/src/`; `sync-docs`.

ADRs and CALM diagrams are **first-class deliverables, equal to code and tests.** ADD applies to new CRDs / CRD-field contract changes, controllers/reconcilers/binaries, changes to the CAPI interaction (Machine / bootstrap / infrastructure contract, allowed API groups), deploy/admission/GitOps topology, and cross-cutting security / RBAC / scheduling concerns. Typos, isolated bug fixes, and behavior-preserving refactors are **TDD-only**. **When unsure whether a change is architectural, write the ADR.**

> See ADR [0001](../docs/adr/0001-adopt-architecture-driven-development.md) for the adoption decision and rationale.

---

## ⚙️ Claude Code Configuration

### 🚨 CRITICAL: Always Verify CRD Schema Sync
Expand Down
6 changes: 6 additions & 0 deletions .claude/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,12 @@ done

**Checklist:**

### If the change is architecturally significant (ADD — do FIRST):
See `.claude/rules/architecture-driven-development.md`. Applies to new CRDs / CRD-field contract changes, controllers/reconcilers/binaries, CAPI-interaction changes, deploy/admission/GitOps topology, and security/RBAC/scheduling concerns.
- [ ] ADR written/updated in `docs/adr/NNNN-*.md` (Status/Context/Decision/Consequences) and indexed in `docs/adr/README.md`
- [ ] CALM model updated, `make calm-validate` + `make calm-diagrams` pass — OR the ADR states "no CALM impact (process-only)"
- [ ] ADR was written BEFORE the implementation (ADR → CALM → TDD order)

### If ANY `.rs` file was modified:
- [ ] Tests updated/added/deleted to match changes (TDD — see `tdd-workflow`)
- [ ] All new public functions have tests
Expand Down
100 changes: 100 additions & 0 deletions .claude/rules/architecture-driven-development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Architecture Driven Development (ADD)

> **ADD is the governing methodology for 5-Spot.** Architecture is designed,
> recorded, and visualized **before** code is written. ADRs and CALM diagrams
> are first-class deliverables — equal in importance to the code and the tests.

ADD layers *on top of* the existing TDD discipline; it does not replace it. The
order is fixed:

```
ADR → CALM → TDD → implement → docs
```

## The ADD cycle

For any **architecturally significant** change, complete each step before
starting the next:

### 1. ADR — decide and record (FIRST)

Write or update an Architecture Decision Record in
`docs/adr/NNNN-title.md` (lowercase-hyphen, zero-padded sequential number)
using `docs/adr/template.md`, with the standard sections:

- **Status** — Proposed → Accepted (→ Superseded by NNNN)
- **Context** — the forces, constraints, and the problem being solved
- **Decision** — what we will do, stated plainly
- **Consequences** — trade-offs, follow-ups, what this rules out

ADRs are kept **in the repo** (unlike roadmaps, which live outside it at
`~/dev/roadmaps/`). One decision per ADR. If a change reverses an earlier ADR,
mark the old one *Superseded* and link forward. Keep the index in
`docs/adr/README.md` current.

### 2. CALM — model and visualize

Update the FINOS CALM architecture model
(`docs/architecture/calm/architecture.json`) to reflect the decision: nodes,
relationships, interfaces, controls, and flows. Then:

```sh
make calm-validate # architecture conforms to the meta-schema (hard gate)
make calm-diagrams # regenerate Mermaid diagrams into docs/src/architecture/
```

The architecture must be modeled and the diagrams must render cleanly **before**
implementation begins. A change that isn't reflected in CALM isn't designed yet.

> **Process-only decisions** (e.g. adopting a methodology, CI policy) have **no
> CALM impact** — CALM models the running system (controller, `ScheduledMachine`
> CRD, CAPI/provider resources, flows), not the development process. Say so
> explicitly in the ADR's Consequences and skip step 2.

### 3. TDD — red / green / refactor

Only now write code, **tests first**, per the `tdd-workflow` skill: failing test
→ minimum implementation → refactor. Tests go in separate `_tests.rs` files
(`src/foo.rs` → `#[cfg(test)] mod foo_tests;` → `src/foo_tests.rs`). After any
`.rs` change, run the `cargo-quality` skill (fmt + clippy + test — all must pass).

CRD shape changes start in `src/crd.rs` (the source of truth), then regenerate:
`regen-crds` skill (`make crds`) → update `examples/` → `regen-api-docs`
(`make crddoc`, LAST). Never hand-edit `deploy/crds/*.yaml`.

### 4. Docs

Update `.claude/CHANGELOG.md` (with `**Author:**`) and any affected `docs/src/`
pages / examples. Run the `sync-docs` skill to verify docs match the code.

## When does ADD apply?

**Full ADR + CALM** (architecturally significant):

- New CRDs / CRD fields that change a contract, new controllers, reconcilers, or binaries
- Changes to how 5-Spot interacts with CAPI (Machine / bootstrap / infrastructure contract, allowed API groups)
- New deploy / admission / GitOps topology (e.g. ValidatingAdmissionPolicy posture, child-cluster routing)
- Cross-cutting concerns: security boundaries, RBAC posture, failure domains, scheduling semantics
- Any decision where "why A over B" is worth recording

**ADR only, no CALM** (process / policy, no system-topology change):

- Methodology, CI/CD policy, repository conventions

**TDD only** (no ADR/CALM needed):

- Typos, comment/doc tweaks, formatting
- Isolated bug fixes with no architectural impact
- Mechanical refactors that preserve behavior and structure

> When unsure whether a change is "architectural," **write the ADR.** A short,
> slightly-redundant ADR costs little; an undocumented architectural decision
> costs the next person a re-derivation.

## Checklist (paste into the work)

- [ ] ADR written/updated in `docs/adr/NNNN-*.md` (Status/Context/Decision/Consequences); index in `docs/adr/README.md` updated
- [ ] CALM model updated; `make calm-validate` passes; `make calm-diagrams` renders — **or** ADR states "no CALM impact (process-only)"
- [ ] Tests written **first**, then implementation (TDD); CRD changes regenerated via `regen-crds` → `regen-api-docs`
- [ ] `cargo-quality` passes (fmt + clippy + test)
- [ ] CHANGELOG (`**Author:**`) + docs updated; `sync-docs` clean
85 changes: 85 additions & 0 deletions docs/adr/0001-adopt-architecture-driven-development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<!--
Copyright (c) 2026 Erick Bourgeois, 5-Spot
SPDX-License-Identifier: Apache-2.0
-->
# 0001 — Adopt Architecture Driven Development (ADD)

- **Status:** Accepted
- **Date:** 2026-05-31
- **Deciders:** Erick Bourgeois
- **Supersedes:** —
- **Related:** `.claude/rules/architecture-driven-development.md`; CALM model at `docs/architecture/calm/architecture.json`; the existing TDD discipline in `.claude/CLAUDE.md`.

## Context

5-Spot already enforces strong **Test-Driven Development** (tests first, separate
`_tests.rs` files, `cargo-quality` as a hard gate) and already maintains a
**FINOS CALM** architecture model with `make calm-validate` / `make
calm-diagrams`. What it lacked was an explicit, ordered methodology tying the
*decision*, the *model*, and the *code* together — and a durable home for the
"why A over B" reasoning behind architecturally significant changes.

Several recent changes illustrate the gap. The RBAC anti-escalation design (VAP
`authorizer` checks for the requesting user + a controller-side
`SelfSubjectAccessReview`), the embedded-`metadata` policy (reject
`name`/`namespace`, allow reserved-prefix-checked `labels`/`annotations`), and
the child-cluster Node-routing model were all real architectural decisions with
non-obvious trade-offs. They were captured in the changelog and code comments,
but there was no first-class record of the decision and the alternatives
weighed — so the next contributor must re-derive the reasoning from the diff.

A sibling project (banlieue) adopted **Architecture Driven Development**:
decisions are recorded as ADRs and modeled in CALM *before* code, on top of the
existing TDD loop. The order is fixed:

```
ADR → CALM → TDD → implement → docs
```

The alternative — staying TDD-only and relying on the changelog plus code
comments — keeps the process lighter, but leaves architectural intent scattered
and reconstructed rather than stated. Given 5-Spot operates in a regulated
environment where changes must be auditable and traceable to a rationale, a
first-class decision log is worth the modest per-change overhead.

## Decision

We adopt **Architecture Driven Development (ADD)** as the governing methodology
for 5-Spot. For any architecturally significant change, contributors complete
the steps in order — **ADR → CALM → TDD → implement → docs** — before the next
step begins:

1. **ADR** — record the decision in `docs/adr/NNNN-title.md` (Status / Context /
Decision / Consequences), from `docs/adr/template.md`, indexed in
`docs/adr/README.md`.
2. **CALM** — reflect it in `docs/architecture/calm/architecture.json`;
`make calm-validate` + `make calm-diagrams` must pass. *Process-only decisions
have no CALM impact and say so.*
3. **TDD** — failing tests first, then minimum implementation; `cargo-quality`
gate; CRD changes regenerate via `regen-crds` → `regen-api-docs`.
4. **Docs** — CHANGELOG (`**Author:**`) + affected `docs/src/`; `sync-docs` clean.

ADRs and CALM diagrams are first-class deliverables, equal to code and tests.
The full rule lives in `.claude/rules/architecture-driven-development.md` and is
referenced as the governing methodology from `.claude/CLAUDE.md`. ADD applies to
new CRDs/CRD-field contract changes, controllers/reconcilers/binaries, changes
to the CAPI interaction, deploy/admission/GitOps topology, and cross-cutting
security/RBAC/scheduling concerns. Typos, isolated bug fixes, and behavior-
preserving refactors remain TDD-only. **When unsure, write the ADR.**

## Consequences

- **Easier:** architectural intent is recorded once, at decision time, with the
alternatives weighed — auditable and traceable, which suits the regulated
context. New contributors read `docs/adr/` instead of re-deriving from diffs.
- **Harder / slower:** a modest per-change overhead for significant work (write
the ADR, touch CALM). Mitigated by scoping ADD to *architecturally
significant* changes and keeping ADRs short.
- **Ruled out:** silently making a significant decision in code-only form. If
it's worth a "why A over B," it gets an ADR.
- **Retroactive ADRs:** existing significant decisions (RBAC anti-escalation,
embedded-metadata policy, child-cluster routing, `release:published` docs
trigger) may be back-filled as ADRs over time; not required immediately.
- **CALM impact:** **none.** This is a process decision, not a change to the
running system's topology, so the CALM model is unchanged. (This ADR is itself
an instance of the "process-only → no CALM" rule it establishes.)
39 changes: 39 additions & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!--
Copyright (c) 2026 Erick Bourgeois, 5-Spot
SPDX-License-Identifier: Apache-2.0
-->
# Architecture Decision Records

This directory holds 5-Spot's **Architecture Decision Records (ADRs)** — the
durable log of *why* the system is shaped the way it is.

5-Spot follows **Architecture Driven Development (ADD)**: for any
architecturally significant change, the decision is recorded here **before** code
is written, then modeled in CALM, then implemented test-first. See
[`.claude/rules/architecture-driven-development.md`](../../.claude/rules/architecture-driven-development.md)
for the full methodology.

## Conventions

- **Filename:** `NNNN-title.md` — zero-padded sequential number, lowercase, hyphenated.
- **One decision per ADR.** Copy [`template.md`](./template.md) to start.
- **Status lifecycle:** `Proposed` → `Accepted` → (`Superseded by ADR-NNNN`).
Never delete or rewrite a decision — supersede it and link forward.
- **In the repo.** ADRs are version-controlled here. (Roadmaps and phase plans
are *not* — those live outside the repo at `~/dev/roadmaps/`.)

## When to write one

Write a full ADR (and update the CALM model) for: new CRDs/CRD-field contract
changes, controllers/reconcilers/binaries, changes to the CAPI interaction
(Machine / bootstrap / infrastructure contract, allowed API groups), deploy /
admission / GitOps topology, and cross-cutting concerns (security boundaries,
RBAC posture, scheduling semantics). Process/policy decisions get an ADR with
**no CALM impact**. Trivial changes (typos, isolated bugfixes, mechanical
refactors) need neither. When unsure, **write the ADR.**

## Index

| ADR | Title | Status |
|----:|-------|--------|
| [0001](./0001-adopt-architecture-driven-development.md) | Adopt Architecture Driven Development (ADD) | Accepted |
30 changes: 30 additions & 0 deletions docs/adr/template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!--
Copyright (c) 2026 Erick Bourgeois, 5-Spot
SPDX-License-Identifier: Apache-2.0
-->
# NNNN — <short decision title>

- **Status:** Proposed | Accepted | Superseded by ADR-NNNN
- **Date:** YYYY-MM-DD
- **Deciders:** <name(s)>
- **Supersedes:** <ADR-NNNN, or "—">
- **Related:** <ADRs, CALM nodes, docs, or "—">

## Context

The forces, constraints, and the problem being solved. What is true today, what
pressure is pushing for a change, and what options were on the table. State the
alternatives you weighed and why they were rejected — that is the part future
readers cannot reconstruct.

## Decision

What we will do, stated plainly and in the present tense ("We use X", "Providers
satisfy Y"). One decision per ADR.

## Consequences

The trade-offs this locks in: what becomes easier, what becomes harder, what is
now ruled out, and any follow-up work it implies. Note CALM impact explicitly —
either "CALM updated (nodes/flows …)" or "no CALM impact (process-only / no
system-topology change)".
Loading
Loading