From a89b8f10c53fe4861495f3e424de301a62e22774 Mon Sep 17 00:00:00 2001 From: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com> Date: Wed, 7 Oct 2026 19:05:42 +0200 Subject: [PATCH 01/57] Describe the module design principles in CONTRIBUTING Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com> --- CONTRIBUTING.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index da9c01d..fc620b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,6 +74,31 @@ export HODEISHIELD_API_KEY=... # never commit or paste it anywhere cargo run -- vendors list ``` +## Design + +A short vocabulary for designing or refactoring a module, adapted from +[aihero.dev/codebase-design](https://www.aihero.dev/skills-codebase-design). A **module** is anything +with an interface and an implementation, at any scale: a function, a file, a crate. Its **interface** +is everything a caller must know to use it: signature, invariants, errors and ordering. A **seam** is +a place where behaviour can change without editing that place, and an **adapter** is a concrete +implementation plugged into one. **Depth** is the behaviour available per unit of interface, and +**locality** means that what changes together lives together. + +- **Depth lives in the interface.** Judge a module by how little a caller must learn, not by how + much code it hides. `hodeishield-api` is the model: the CLI calls `client.list_vendors(¶ms)` + and gets typed results, while URL building, authentication, retries, rate limits and the response + size cap stay behind it. +- **Deletion test.** Imagine deleting the module and inlining it into its callers. If the + complexity vanishes, it was a pass-through and should not exist; if it spreads to every caller, it + is earning its place. +- **The interface is the test surface.** Test through the interface. A test that reaches past it + pins the implementation and breaks on every refactor. +- **One adapter is a hypothetical seam; two make it real.** Add a trait only when a second + implementation exists today, a test double included. `TokenStore` qualifies: the OS keychain and + the in-memory store used by tests both implement it. +- **Locality.** Table, JSON and CSV rendering, including the sanitising of terminal control + characters, lives in `output.rs`, so a change to it touches one module, not every command. + ## Pull requests - Branch from `dev` and open the pull request against `dev`. `main` only receives releases. From 073e932ac6ed79443722dd0a71f4abfc15066ea4 Mon Sep 17 00:00:00 2001 From: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com> Date: Wed, 7 Oct 2026 19:09:09 +0200 Subject: [PATCH 02/57] Report OpenAPI drift in an issue instead of a pull request The weekly check still compares the published /v1 document with openapi/v1.json and classifies breaking changes with the pinned oasdiff, but it no longer pushes a branch, regenerates the client or opens a pull request. It opens or updates one issue labelled openapi-drift, closes it when the documents match again, and fails the run on drift. A failed fetch, parse or oasdiff run is reported in an issue labelled openapi-check-failed. Permissions are reduced to contents: read and issues: write. Signed-off-by: d0ubl3g <48954024+d0ubl3g@users.noreply.github.com> --- .github/scripts/openapi-drift-issue.sh | 63 ++++++++ .github/scripts/openapi-drift-report.py | 125 ++++++++++++++++ .github/scripts/openapi-sync.py | 77 +++------- .github/workflows/openapi-sync.yml | 183 ++++++++---------------- CONTRIBUTING.md | 3 +- openapi/README.md | 14 +- 6 files changed, 273 insertions(+), 192 deletions(-) create mode 100755 .github/scripts/openapi-drift-issue.sh create mode 100755 .github/scripts/openapi-drift-report.py diff --git a/.github/scripts/openapi-drift-issue.sh b/.github/scripts/openapi-drift-issue.sh new file mode 100755 index 0000000..a1970ee --- /dev/null +++ b/.github/scripts/openapi-drift-issue.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2026 Hodeitek S.L. +# Keeps one open issue per label in step with the state of the OpenAPI check. +# +# openapi-drift-issue.sh report