From 49b1136ded9b522a05067e248bf4a757d671cd7a Mon Sep 17 00:00:00 2001 From: jochens Date: Wed, 30 Sep 2026 13:28:53 +0200 Subject: [PATCH] Issues 164-168: found provisioning every dependency on ace 164 a credential that must be accepted is minted anyway 165 one accepted value must be accepted once per consumer 166 a requirement cannot be optional 167 code several modules share has no home 168 a setting reaches every file and every contribution --- .../00-report.md | 29 +++++++++++++++++ .../00-report.md | 24 ++++++++++++++ .../00-report.md | 24 ++++++++++++++ .../00-report.md | 26 +++++++++++++++ .../00-report.md | 32 +++++++++++++++++++ 5 files changed, 135 insertions(+) create mode 100644 04-ISSUES/164-a-credential-that-must-be-accepted-is-minted-anyway/00-report.md create mode 100644 04-ISSUES/165-one-accepted-value-must-be-accepted-once-per-consumer/00-report.md create mode 100644 04-ISSUES/166-a-requirement-cannot-be-optional/00-report.md create mode 100644 04-ISSUES/167-code-several-modules-share-has-no-home/00-report.md create mode 100644 04-ISSUES/168-a-setting-reaches-every-file-and-contribution/00-report.md diff --git a/04-ISSUES/164-a-credential-that-must-be-accepted-is-minted-anyway/00-report.md b/04-ISSUES/164-a-credential-that-must-be-accepted-is-minted-anyway/00-report.md new file mode 100644 index 0000000..b65bd92 --- /dev/null +++ b/04-ISSUES/164-a-credential-that-must-be-accepted-is-minted-anyway/00-report.md @@ -0,0 +1,29 @@ +--- +status: open +opened: 2026-09-30 +located-in: + - mesh-controller internal/inventory/secrets.go (SecretFor mints a pair credential nobody accepted) +fixed-by: +amended-design: +--- + +# 164 — A credential that must be accepted is minted anyway + +## What was observed + +Provisioning ace's modules. Several providers hold exactly one credential they did not get from the +mesh and cannot take one from it: a Servarr app's API key (sonarr, radarr, lidarr), jackett's API key, +plex's X-Plex-Token, nzbget's ControlPassword, qBittorrent's WebUI password. Their consumers' pair +credential must be **accepted** by the operator (ADR 0092). Until it is, `SecretFor` mints a random +value, seals it to both ends, and reports nothing: the value can never work. + +Every consumer therefore had to learn to detect it — try the credential against the provider first, +refuse a value the provider rejects, print the `secret accept` command — six write-in steps, one probe +each (ombi, home-assistant, and the four download-stack consumers). qBittorrent bans an address after +five failed logins, so a consumer retrying a minted value locks itself out. + +## What would be right + +A provision (or a provider's `serves`) can declare its pair credential **accepted-only**. The plan then +refuses the pair — naming the accept command — instead of minting, and a consumer is never handed a +value the mesh knows cannot work. diff --git a/04-ISSUES/165-one-accepted-value-must-be-accepted-once-per-consumer/00-report.md b/04-ISSUES/165-one-accepted-value-must-be-accepted-once-per-consumer/00-report.md new file mode 100644 index 0000000..22a237b --- /dev/null +++ b/04-ISSUES/165-one-accepted-value-must-be-accepted-once-per-consumer/00-report.md @@ -0,0 +1,24 @@ +--- +status: open +opened: 2026-09-30 +located-in: + - mesh-controller internal/inventory/secrets.go (AcceptSecretForPair is per consumer) +fixed-by: +amended-design: +--- + +# 165 — One accepted value must be accepted once per consumer + +## What was observed + +On ace, jackett's API key is the pair credential for sonarr, radarr, lidarr and bookshelf; sonarr's is +the credential for ombi, bazarr and home-assistant. It is **one value**, owned by the provider — yet +`secret accept` is per pair, so ace's download stack alone needs 12 accepts of 3 values, and rotating +a provider's key means finding and re-accepting every pair. Missing one leaves that consumer on a +stale (or minted, 164) value. + +## What would be right + +A provider-level accept: "this provider's credential for `` is X" — delivered to every +consumer pair, current and future, and rotated in one place. Pairs whose credential is genuinely per +consumer (postgres, keycloak, mosquitto, influxdb — minted and created by a provisioner) are unaffected. diff --git a/04-ISSUES/166-a-requirement-cannot-be-optional/00-report.md b/04-ISSUES/166-a-requirement-cannot-be-optional/00-report.md new file mode 100644 index 0000000..6cffbc9 --- /dev/null +++ b/04-ISSUES/166-a-requirement-cannot-be-optional/00-report.md @@ -0,0 +1,24 @@ +--- +status: open +opened: 2026-09-30 +located-in: + - mesh-controller internal/catalogue (requires is a list of hard requirements) +fixed-by: +amended-design: +--- + +# 166 — A requirement cannot be optional + +## What was observed + +Making every dependency on ace a provision turned soft dependencies into hard ones. grafana now +requires `influxdb-api` (a data source), ombi requires `sonarr-api`, `radarr-api` and `lidarr-api`, +home-assistant requires the Servarr APIs and `mqtt-topic`. Each is optional to the software — grafana +runs without a data source, ombi without lidarr — but a mesh without influxdb cannot assign grafana at +all, and a mesh without lidarr cannot run ombi. + +## What would be right + +A requirement a module can run without: resolved and bound when a provider exists, absent (with its +`${bound:…}` placeholders refused or defaulted explicitly, never rendered empty) when none does — so +the module description stays true on every mesh. diff --git a/04-ISSUES/167-code-several-modules-share-has-no-home/00-report.md b/04-ISSUES/167-code-several-modules-share-has-no-home/00-report.md new file mode 100644 index 0000000..fe46de6 --- /dev/null +++ b/04-ISSUES/167-code-several-modules-share-has-no-home/00-report.md @@ -0,0 +1,26 @@ +--- +status: open +opened: 2026-09-30 +located-in: + - mesh-catalog (each module builds from its own directory, ADR 0069) + - mesh-sdk +fixed-by: +amended-design: +--- + +# 167 — Code several modules share has no home + +## What was observed + +The download-stack write-in step (register download clients and torznab indexers through the Servarr +API) is identical for sonarr, radarr, lidarr and bookshelf. Because a module builds from its own +directory, it now exists as four byte-identical copies under `modules//downloads/`, kept honest by a +test that fails when one differs. The same shape repeats: an MQTT probe copied into two modules, and a +"write the provider into the app through its API, idempotently, refuse a minted value" step in ombi, +home-assistant, nodered, tautulli and the four downloaders. + +## What would be right + +A home for shared module code the builder can use — an sdk helper (a write-in step harness: read +bindings and pair credentials, probe the provider, diff, write, report) or a shared package the +catalogue builds once — so a fix lands in one place. diff --git a/04-ISSUES/168-a-setting-reaches-every-file-and-contribution/00-report.md b/04-ISSUES/168-a-setting-reaches-every-file-and-contribution/00-report.md new file mode 100644 index 0000000..6b9f971 --- /dev/null +++ b/04-ISSUES/168-a-setting-reaches-every-file-and-contribution/00-report.md @@ -0,0 +1,32 @@ +--- +status: open +opened: 2026-09-30 +located-in: + - mesh-controller internal/catalogue/settings.go (settle: every key but `ports` merges into every mergeable file and every contribution) + - mesh-controller internal/catalogue/declaration.go (a provider's settings are laid over what it serves) +fixed-by: +amended-design: +--- + +# 168 — A setting reaches every file and every contribution + +## What was observed + +Settings merge key by key into **every** `"merge": "json"` file of a module **and** every contribution +it makes; a provider's settings are also laid over what it serves. Seen on ace: + +- searxng's `endpoints` and a route `label` land in searxng's own `settings.yml`; nodered's + `timeZone` and `mqtt` keys land in mosquitto's grants file; keycloak's `issuer` lands in its + `postgres-database` and `route` contributions. +- every consumer's `plex-api` binding carries plex's `endpoints` and `expose` settings — and a provider + setting named `port` would silently redirect every consumer. +- a module cannot have two configurable files: searxng's sidecar config had to stop being mergeable + so searxng's keys would not reach it. + +Harmless today only because every receiver happens to ignore unknown keys. + +## What would be right + +A setting is aimed: at a file (by resource id), at a contribution (by requirement), or at what the +module serves — declared settable by the module (ADR 0046 already says settings drive "the fields the +manifest marks") — and an unaimed key is refused like any unknown setting.