Angelegt am 2026-10-09 in der Design-Sitzung zu #87/#200 (Stand 9.0.0, 7cfafd7). Entscheidungen des Betreibers vom 2026-10-10 sind eingearbeitet (§ Entscheidungen). Dieses Paket baut den Mechanismus nur für neue Einstellungen. Die bestehenden Dateien zieht #208 um, und erst dort verschwinden die Altlasten.
Abgeschlossen (2026-10-10). Publiziert als 9.1.0-beta.1, Commit f6aaadc (nach Freigabe des Mass-Update Gate, 40 Dateien). Verifiziert durch CI-Run 644 (https://gitea.nehmer.net/torben/chemenu/actions/runs/644): verify grün (2762 passed, Coverage 91,7 %; die 1Password-Action hat WIKITOOL_SECRET_CI_SMOKE geladen, der Smoke-Test lief mit 1 passed, nicht übersprungen), pwsh grün; Release-Run 645 grün. Schlussphase: Doku-Nachzug e085a8b (nur docs/, außerhalb des Version-Gates, kein Bump): Das How-to nennt jetzt auch den Pfad der Secret-Datei unter Windows und mit $XDG_CONFIG_HOME; die Erklärseite sagt, dass die Freigabe-Abfrage von 1Password je Terminal-Sitzung gilt und nicht je Wert. Verifiziert durch CI-Run 646 (https://gitea.nehmer.net/torben/chemenu/actions/runs/646), verify und pwsh grün, Smoke-Test erneut 1 passed. Die übrigen neuen und berührten Dokumente (AGENTS.md § Settings, docs/reference/configuration.md § Tiered settings, tools/CONTRACT.md mit den Records zu config set, doctor und docs verify, INSTALL.md, instructions/preflight.md, tools/README.md) habe ich gegen den Code gelesen. Sie stimmen. Die CI-Boilerplate des Betreibers: torben/gitea-mcp, Branch ci-binford, .gitea/workflows/binford-release.yaml. Abweichungen vom Entwurf, die der Bau ergeben hat, stehen jeweils am Punkt selbst und sind mit Bau: markiert.
Befund
Bis zu diesem Paket lag jede Einstellung von wikitool in einer eigenen, gitignorierten Datei pro Feature: .wikitool-remotes.json, .wikitool-telemetry.json, .wikitool-upload.json, .wikitool-tasks.json (dazu .wikitool-tasks.d/) und .wikitool-tools.json. Eingecheckt ist nur .wikitool-kb.json, und die beschreibt die Form des Korpus, ist also keine Einstellung.
Jede neue Datei kostet etwa fünf Stellen: Konstante in tools/chemenu/config.py, Absatz in .gitignore, Ignore-Kanarie in docs verify, Zeile in doctor, Doku.
Die Formprüfung ist schon zentral (tools/chemenu/config_shapes.py: Shape/Field/check, benutzt von upload.py, telemetry/policy.py, git_publish.py, tasks/*.py). Jeder Leser liest seine Datei aber selbst.
Drei Arten von Daten liegen dort gemischt:
was zur Instanz gehört (Schwellen der Aufgaben-Schicht);
was zu einem Checkout gehört (Werkzeugpfade, Remotes-Allowlist, Telemetrie-Zustimmung);
Secrets (api_token in superproductivity, app_password in caldav), im Klartext im Arbeitsbaum und nur durch .gitignore geschützt.
Die Altdateien bleiben bis #208 bestehen. Dieses Paket stellt nur das Ziel bereit.
Ziel
Stufe
Inhalt
Ablage
instance, eingecheckt
Was zum Korpus gehört und in jedem Klon gleich sein soll
wikitool.json im Instanz-Root
checkout, lokal
Was nur auf diesem Rechner oder in diesem Klon stimmt
.wikitool-local.json, gitignored
secret
Tokens, Passwörter, Sessions
außerhalb des Arbeitsbaums. Die beiden Dateien verweisen nur darauf
Entscheidungen des Betreibers (2026-10-10)
Eingecheckte Datei wikitool.json, lokale Datei .wikitool-local.json.
Secrets über eine Umgebungsvariable oder eine Datei im Nutzerverzeichnis (Entwurf 4), ohne OS-Keyring.
Geschrieben wird über wikitool config set (Entwurf 7).
Zusätzlich die 1Password-CLI (op) als Secret-Quelle (Entwurf 5): für Desktop-Installationen die bevorzugte Variante, in der CI wie bei anderen Action-Runnern. op kann auch Nicht-Secrets liefern (URLs, Connection-Strings), was die Konfiguration über Rechner hinweg portabel macht.
Freigabe des Publish mit 40 Dateien über das Mass-Update Gate (Token 1da42d56b1be), samt der Bau-Entscheidungen unten (CI-Element, gate-Felder nur durch den Nutzer, WARN bei gesperrtem 1Password).
Entwurf (gebaut)
Jedes Feld gehört genau einer Stufe, deklariert im Field von config_shapes.py (tier="instance" | "checkout" | "secret"). Ein Wert in der falschen Stufe ist ein Fehler, keine Überschreibung; derselbe Schlüssel in beiden Dateien ebenso. Die Abschnitte stehen in config_shapes.SETTINGS_SECTIONS. Nach diesem Paket ist das Tupel leer, Abschnitte bringen #208 und die Verbraucher #200/#169. Bau: Ein Abschnitt ist flach - keine verschachtelten Felder, keine Varianten -, damit die Stufe am Feld allein ablesbar ist.
Harte Regel: Was ein Programm zum Ausführen benennt (names_command) oder ein Gate betrifft (gate), ist nie instance.Field.__post_init__ wirft beim Deklarieren. Auch als Verweis steht so ein Feld nie in wikitool.json. Die Regel steht für Agenten genau einmal: AGENTS.md § Settings.
Verweise statt Werte. Ein secret-Feld nimmt nur einen Verweis, ein private-Feld (private Infrastruktur) darf einen nehmen, alle anderen keinen. Zwei Formen: {"ref": "<name>"} (Kleinbuchstaben, Ziffern, einzelne _) und {"ref": "op://<vault>/<item>/<field>"}. Bau: Ein private-Feld ist immer Stufe checkout (beim Deklarieren erzwungen): Klartext nur in .wikitool-local.json, als Verweis in beiden Dateien.
Quelle Name: zuerst WIKITOOL_SECRET_<NAME>, sonst ~/.config/chemenu/<instanz-id>/secrets.json (Windows: %APPDATA%\chemenu\<instanz-id>\secrets.json). Die <instanz-id> (UUID) erzeugt das erste config set in wikitool.json. Bau:$XDG_CONFIG_HOME wird statt ~/.config beachtet, wenn gesetzt. "Nur für den Nutzer lesbar" wird erzwungen: außerhalb Windows wird eine Datei mit Rechten für Gruppe oder andere abgelehnt (exit 1, Hinweis chmod 600).
Quelle 1Password:op read --no-newline <ref> ohne Shell, stdin /dev/null, Timeout 60 s, Wert nur im Speicher. Fehlt op → exit 1 mit Preflight-Hinweis. Element/Feld/Tresor fehlt (op-Meldung "isn't an item/a vault/a field", "does not have a field" …) → exit 1 mit dem Verweis. Jeder andere Fehler und ein Timeout gelten als gesperrt/nicht angemeldet → exit 42, ohne den Verweis. Bau:op steht als neue Zeilenart optional|op|… in tools/prerequisites.txt; beide Preflights erfassen es, wenn vorhanden (ABSENT sonst, nie ein Problem), --set op= geht. Geprüft: Der Launcher liest aus .wikitool-tools.json nur "complete": true, toolpaths nur benannte Schlüssel - ein zusätzlicher Schlüssel stört keine ältere Version. Neu: toolpaths.optional().
CI.Bau, nach der Boilerplate des Betreibers: Der Weg ist die Action. 1password/load-secrets-action@v2 lädt op://CI-CD/gitea-package-token/username (das am wenigsten sensible Feld, das der Service-Account sieht) nach WIKITOOL_SECRET_CI_SMOKE; der Test test_live_secret_reference_resolves_from_ci löst {"ref": "ci_smoke"} darüber auf und läuft mit CHEMENU_LIVE_SECRET_REQUIRE=1, damit "kein Wert" rot statt übersprungen ist. Dazu curl unzip in den Systemabhängigkeiten, wie in der Boilerplate. In Run 644 und 646 bestätigt. Einschränkung, die der Bau gezeigt hat: Der Action-Weg bedient Namensverweise. Eine Konfiguration mit op://-Verweisen braucht in der CI den anderen Weg (op im Job plus OP_SERVICE_ACCOUNT_TOKEN). Der Code kann das, diese CI testet es nicht. "Dieselbe Konfiguration auf beiden Wegen" gilt also nur je Verweisform, und so steht es im How-to. Nicht blockierend: Braucht ein Verbraucher (#200, #169) op:// in der CI, kommt der zweite Weg dort dazu.
wikitool config set <schlüssel> <wert|--ref …> prüft Stufe und Form. Klartext instance → wikitool.json, Klartext checkout/private → .wikitool-local.json, Verweis → wikitool.json; derselbe Schlüssel in der anderen Datei wird entfernt und gemeldet. Ein Secret-Wert wird abgelehnt (exit 1, Wert nicht ausgegeben). Bau: "Nur der Nutzer setzt" gilt für names_commandundgate - wie bei der Allowlist des Publish-Remote Gate; config set endet dort mit exit 42 und nennt die Datei zum Selbst-Editieren. Vor dem Schreiben werden beide Dateien geprüft, aber ohne Pflichtfelder, sonst ließe sich der erste Wert eines Abschnitts nie schreiben (check_files(..., complete=False)).
Leseschicht tools/chemenu/settings.py: liest beide Dateien, prüft Platzierung und Form, löst Verweise erst beim Zugriff auf, gibt einem Leser seinen Abschnitt. Bau: Für Kommandos gibt es _util.load_settings() und _util.setting_value() (exit 1 bzw. 42) - darüber testen die Kriterien die Exit-Codes, darüber lesen #200/#169. doctor: Zeilen settings-instance, settings-checkout, settings-secrets; ein nicht auflösbarer Verweis ist FAIL, ein gesperrtes 1Password WARN (sonst wäre doctor bei gesperrter App rot), ein unbekannter Abschnitt WARN.
Erste Verbraucher:#200 (Site-Handler) und #169 (Abruf mit Session). Hier wird mit einem Test-Shape getestet.
Sicherheitsmodell (ehrlich)
Secrets außerhalb des Baums schützen vor dem Einchecken. Sie schützen auch davor, dass ein Wert in einer Datei steht, die der Agent bei normaler Arbeit liest, oder in einer Ausgabe von wikitool auftaucht. Sie schützen nicht vor einem Agenten mit Shell-Zugriff, der es darauf anlegt.
Ist 1Password im Terminal entsperrt, kann der Agent op read selbst aufrufen.
Die Secret-Datei kann er ebenfalls lesen.
Was der Prozess von wikitool zur Laufzeit lesen kann, kann der Agent im selben Benutzerkontext grundsätzlich auch.
Das begrenzt man, ohne es zu verhindern:
ein eigener 1Password-Tresor nur für die Einträge dieser Instanz;
die Freigabe-Abfrage der 1Password-Desktop-App. Sie gilt je Terminal-Sitzung, nicht je Wert, hält also nur eine Sitzung auf, die noch niemand freigegeben hat;
in der CI ein Service-Account, der nur diesen Tresor sieht.
Die Doku sagt das so (docs/explanation/configuration-tiers.md), und der Stack verspricht nichts darüber hinaus.
neu: tools/chemenu/settings.py; tools/chemenu/commands/config_cmd.py mit Record, Gruppe "Configuration" in cli_contract.GROUPS; _util.load_settings/setting_value
tools/chemenu/commands/doctor.py, tools/chemenu/commands/docs_verify.py (Kanarien .wikitool-local.json ignoriert / wikitool.json getrackt; check_instance_settings: nur Platzierung in wikitool.json, keine Pflichtfelder, die im lokalen File stehen dürfen)
.gitignore, tools/chemenu/tests/conftest.py (WIKITOOL_SECRET_* per Präfix gelöscht)
dist_cmd.py unverändert: wikitool.json steht nicht in ROOT_FILES, wird also nicht ausgeliefert und von dist upgrade nie berührt (Test test_plan_ships_neither_settings_file)
.gitea/workflows/ci.yml
AGENTS.md § Settings (neu) und § File naming (sieben statt sechs Erklärseiten), instructions/dev/doc-pull-through.md, instructions/dev/testing-conventions.md, tools/README.md
docs/explanation/configuration-tiers.md, docs/how-to/use-1password-for-settings.md (beide in der Schlussphase nachgezogen, e085a8b), docs/reference/configuration.md § Tiered settings, docs/reference/commands/configuration.md (generiert)
Ein Field mit Stufe instance, das einen Befehl benennt, lässt sich nicht deklarieren (Test). - test_a_field_that_names_a_program_or_a_gate_cannot_be_declared_instance
Ein Wert in der falschen Stufe ergibt beim Lesen exit 1 mit Datei, Schlüssel und richtiger Stufe. - test_a_value_in_the_wrong_tier_fails_naming_file_key_and_tier
Ein Klartext-Wert in einem secret-Feld (beide Dateien) oder in einem private-Feld in wikitool.json ergibt exit 1. Der Wert erscheint in keiner Ausgabe. - test_a_plain_secret_or_committed_private_value_fails_without_showing_it (Kommando, doctor), test_docs_verify_flags_a_plain_secret_in_the_committed_file_only
{"ref": "<name>"} löst über WIKITOOL_SECRET_<NAME> auf. Ohne die Variable löst es über die Secret-Datei im Nutzerverzeichnis auf, mit dem Test-Home.
{"ref": "op://…"} löst über das falsche op auf. Ein gesperrtes op (Testskript mit entsprechendem Exit) ergibt exit 42, ein fehlendes op exit 1 mit dem Preflight-Hinweis. Dazu: Timeout → exit 42, fehlendes Element → exit 1 mit Verweis.
Ohne wikitool.json und .wikitool-local.json verhält sich jedes bestehende Kommando byte-identisch zum Stand davor. Bau: Ausnahme ist doctor mit seinen drei neuen Zeilen (nächstes Kriterium). Geprüft gegen einen Worktree von HEAD: lint, search, version show, docs verify, instructions verify, types list, sources coverage byte-identisch.
doctor zeigt für jede Stufe vorhanden/fehlt/fehlerhaft und für Verweise nur auflösbar/nicht auflösbar.
config set setzt einen instance-Wert in wikitool.json und verweigert einen Secret-Wert im Klartext.
pytest, docs verify, instructions verify grün; CI grün, mit einem echten 1Password-Wert in der CI. Die Action löst op://CI-CD/gitea-package-token/username auf, die Einstellung verweist per Namen darauf (Entwurf 6). CI-Run 644 grün, Smoke-Test 1 passed; nach dem Doku-Nachzug erneut in Run 646. Ein op://-Verweis in den Einstellungen selbst ist in der CI nicht getestet, nur mit dem falschen op im Test (voriges Kriterium). Nicht blockierend, siehe Entwurf 6.
Versionsteil
--minor - gebaut als 9.0.1-beta.2 → 9.1.0-beta.1. Neue, optionale Dateien und ein neues Kommando, die eine ältere Version ignoriert. Ohne sie ändert sich kein Verhalten außer drei OK-Zeilen in doctor. Neue Umgebungsvariablen sind additiv, der optionale Eintrag in .wikitool-tools.json ebenfalls (geprüft, Entwurf 5). Drop-in in beide Richtungen. Der Bruch kommt erst mit #208.
> Angelegt am 2026-10-09 in der Design-Sitzung zu #87/#200 (Stand `9.0.0`, `7cfafd7`). Entscheidungen des Betreibers vom 2026-10-10 sind eingearbeitet (§ Entscheidungen). Dieses Paket baut den Mechanismus **nur für neue Einstellungen**. Die bestehenden Dateien zieht #208 um, und erst dort verschwinden die Altlasten.
>
> **Abgeschlossen (2026-10-10).** Publiziert als `9.1.0-beta.1`, Commit `f6aaadc` (nach Freigabe des Mass-Update Gate, 40 Dateien). **Verifiziert durch CI-Run 644** (https://gitea.nehmer.net/torben/chemenu/actions/runs/644): `verify` grün (2762 passed, Coverage 91,7 %; die 1Password-Action hat `WIKITOOL_SECRET_CI_SMOKE` geladen, der Smoke-Test lief mit `1 passed`, nicht übersprungen), `pwsh` grün; Release-Run 645 grün. **Schlussphase:** Doku-Nachzug `e085a8b` (nur `docs/`, außerhalb des Version-Gates, kein Bump): Das How-to nennt jetzt auch den Pfad der Secret-Datei unter Windows und mit `$XDG_CONFIG_HOME`; die Erklärseite sagt, dass die Freigabe-Abfrage von 1Password je Terminal-Sitzung gilt und nicht je Wert. Verifiziert durch CI-Run 646 (https://gitea.nehmer.net/torben/chemenu/actions/runs/646), `verify` und `pwsh` grün, Smoke-Test erneut `1 passed`. Die übrigen neuen und berührten Dokumente (`AGENTS.md` § Settings, `docs/reference/configuration.md` § Tiered settings, `tools/CONTRACT.md` mit den Records zu `config set`, `doctor` und `docs verify`, `INSTALL.md`, `instructions/preflight.md`, `tools/README.md`) habe ich gegen den Code gelesen. Sie stimmen. Die CI-Boilerplate des Betreibers: `torben/gitea-mcp`, Branch `ci-binford`, `.gitea/workflows/binford-release.yaml`. Abweichungen vom Entwurf, die der Bau ergeben hat, stehen jeweils am Punkt selbst und sind mit **Bau:** markiert.
## Befund
- Bis zu diesem Paket lag jede Einstellung von `wikitool` in einer eigenen, gitignorierten Datei pro Feature: `.wikitool-remotes.json`, `.wikitool-telemetry.json`, `.wikitool-upload.json`, `.wikitool-tasks.json` (dazu `.wikitool-tasks.d/`) und `.wikitool-tools.json`. Eingecheckt ist nur `.wikitool-kb.json`, und die beschreibt die Form des Korpus, ist also keine Einstellung.
- Jede neue Datei kostet etwa fünf Stellen: Konstante in `tools/chemenu/config.py`, Absatz in `.gitignore`, Ignore-Kanarie in `docs verify`, Zeile in `doctor`, Doku.
- Die Formprüfung ist schon zentral (`tools/chemenu/config_shapes.py`: `Shape`/`Field`/`check`, benutzt von `upload.py`, `telemetry/policy.py`, `git_publish.py`, `tasks/*.py`). Jeder Leser liest seine Datei aber selbst.
- **Drei Arten von Daten liegen dort gemischt:**
- was zur Instanz gehört (Schwellen der Aufgaben-Schicht);
- was zu einem Checkout gehört (Werkzeugpfade, Remotes-Allowlist, Telemetrie-Zustimmung);
- Secrets (`api_token` in `superproductivity`, `app_password` in `caldav`), im Klartext im Arbeitsbaum und nur durch `.gitignore` geschützt.
Die Altdateien bleiben bis #208 bestehen. Dieses Paket stellt nur das Ziel bereit.
## Ziel
| Stufe | Inhalt | Ablage |
|---|---|---|
| `instance`, **eingecheckt** | Was zum Korpus gehört und in jedem Klon gleich sein soll | `wikitool.json` im Instanz-Root |
| `checkout`, lokal | Was nur auf diesem Rechner oder in diesem Klon stimmt | `.wikitool-local.json`, gitignored |
| `secret` | Tokens, Passwörter, Sessions | außerhalb des Arbeitsbaums. Die beiden Dateien verweisen nur darauf |
## Entscheidungen des Betreibers (2026-10-10)
1. Eingecheckte Datei `wikitool.json`, lokale Datei `.wikitool-local.json`.
2. Secrets über eine Umgebungsvariable oder eine Datei im Nutzerverzeichnis (Entwurf 4), ohne OS-Keyring.
3. Geschrieben wird über `wikitool config set` (Entwurf 7).
4. **Zusätzlich die 1Password-CLI (`op`) als Secret-Quelle** (Entwurf 5): für Desktop-Installationen die bevorzugte Variante, in der CI wie bei anderen Action-Runnern. `op` kann auch Nicht-Secrets liefern (URLs, Connection-Strings), was die Konfiguration über Rechner hinweg portabel macht.
5. Freigabe des Publish mit 40 Dateien über das Mass-Update Gate (Token `1da42d56b1be`), samt der Bau-Entscheidungen unten (CI-Element, `gate`-Felder nur durch den Nutzer, `WARN` bei gesperrtem 1Password).
## Entwurf (gebaut)
1. **Jedes Feld gehört genau einer Stufe**, deklariert im `Field` von `config_shapes.py` (`tier="instance" | "checkout" | "secret"`). Ein Wert in der falschen Stufe ist ein Fehler, keine Überschreibung; derselbe Schlüssel in beiden Dateien ebenso. Die Abschnitte stehen in `config_shapes.SETTINGS_SECTIONS`. Nach diesem Paket ist das Tupel leer, Abschnitte bringen #208 und die Verbraucher #200/#169. **Bau:** Ein Abschnitt ist flach - keine verschachtelten Felder, keine Varianten -, damit die Stufe am Feld allein ablesbar ist.
2. **Harte Regel: Was ein Programm zum Ausführen benennt (`names_command`) oder ein Gate betrifft (`gate`), ist nie `instance`.** `Field.__post_init__` wirft beim Deklarieren. Auch als Verweis steht so ein Feld nie in `wikitool.json`. Die Regel steht für Agenten genau einmal: `AGENTS.md` § Settings.
3. **Verweise statt Werte.** Ein `secret`-Feld nimmt nur einen Verweis, ein `private`-Feld (private Infrastruktur) darf einen nehmen, alle anderen keinen. Zwei Formen: `{"ref": "<name>"}` (Kleinbuchstaben, Ziffern, einzelne `_`) und `{"ref": "op://<vault>/<item>/<field>"}`. **Bau:** Ein `private`-Feld ist immer Stufe `checkout` (beim Deklarieren erzwungen): Klartext nur in `.wikitool-local.json`, als Verweis in beiden Dateien.
4. **Quelle Name:** zuerst `WIKITOOL_SECRET_<NAME>`, sonst `~/.config/chemenu/<instanz-id>/secrets.json` (Windows: `%APPDATA%\chemenu\<instanz-id>\secrets.json`). Die `<instanz-id>` (UUID) erzeugt das erste `config set` in `wikitool.json`. **Bau:** `$XDG_CONFIG_HOME` wird statt `~/.config` beachtet, wenn gesetzt. "Nur für den Nutzer lesbar" wird erzwungen: außerhalb Windows wird eine Datei mit Rechten für Gruppe oder andere abgelehnt (exit 1, Hinweis `chmod 600`).
5. **Quelle 1Password:** `op read --no-newline <ref>` ohne Shell, stdin `/dev/null`, Timeout 60 s, Wert nur im Speicher. Fehlt `op` → exit 1 mit Preflight-Hinweis. Element/Feld/Tresor fehlt (op-Meldung "isn't an item/a vault/a field", "does not have a field" …) → exit 1 mit dem Verweis. Jeder andere Fehler und ein Timeout gelten als gesperrt/nicht angemeldet → exit 42, ohne den Verweis. **Bau:** `op` steht als neue Zeilenart `optional|op|…` in `tools/prerequisites.txt`; beide Preflights erfassen es, wenn vorhanden (`ABSENT` sonst, nie ein Problem), `--set op=` geht. Geprüft: Der Launcher liest aus `.wikitool-tools.json` nur `"complete": true`, `toolpaths` nur benannte Schlüssel - ein zusätzlicher Schlüssel stört keine ältere Version. Neu: `toolpaths.optional()`.
6. **CI.** **Bau, nach der Boilerplate des Betreibers:** Der Weg ist die Action. `1password/load-secrets-action@v2` lädt `op://CI-CD/gitea-package-token/username` (das am wenigsten sensible Feld, das der Service-Account sieht) nach `WIKITOOL_SECRET_CI_SMOKE`; der Test `test_live_secret_reference_resolves_from_ci` löst `{"ref": "ci_smoke"}` darüber auf und läuft mit `CHEMENU_LIVE_SECRET_REQUIRE=1`, damit "kein Wert" rot statt übersprungen ist. Dazu `curl unzip` in den Systemabhängigkeiten, wie in der Boilerplate. In Run 644 und 646 bestätigt. **Einschränkung, die der Bau gezeigt hat:** Der Action-Weg bedient Namensverweise. Eine Konfiguration mit `op://`-Verweisen braucht in der CI den anderen Weg (`op` im Job plus `OP_SERVICE_ACCOUNT_TOKEN`). Der Code kann das, diese CI testet es nicht. "Dieselbe Konfiguration auf beiden Wegen" gilt also nur je Verweisform, und so steht es im How-to. Nicht blockierend: Braucht ein Verbraucher (#200, #169) `op://` in der CI, kommt der zweite Weg dort dazu.
7. **`wikitool config set <schlüssel> <wert|--ref …>`** prüft Stufe und Form. Klartext `instance` → `wikitool.json`, Klartext `checkout`/`private` → `.wikitool-local.json`, Verweis → `wikitool.json`; derselbe Schlüssel in der anderen Datei wird entfernt und gemeldet. Ein Secret-Wert wird abgelehnt (exit 1, Wert nicht ausgegeben). **Bau:** "Nur der Nutzer setzt" gilt für `names_command` **und** `gate` - wie bei der Allowlist des Publish-Remote Gate; `config set` endet dort mit exit 42 und nennt die Datei zum Selbst-Editieren. Vor dem Schreiben werden beide Dateien geprüft, aber ohne Pflichtfelder, sonst ließe sich der erste Wert eines Abschnitts nie schreiben (`check_files(..., complete=False)`).
8. **Leseschicht `tools/chemenu/settings.py`:** liest beide Dateien, prüft Platzierung und Form, löst Verweise erst beim Zugriff auf, gibt einem Leser seinen Abschnitt. **Bau:** Für Kommandos gibt es `_util.load_settings()` und `_util.setting_value()` (exit 1 bzw. 42) - darüber testen die Kriterien die Exit-Codes, darüber lesen #200/#169. `doctor`: Zeilen `settings-instance`, `settings-checkout`, `settings-secrets`; ein nicht auflösbarer Verweis ist `FAIL`, ein gesperrtes 1Password `WARN` (sonst wäre `doctor` bei gesperrter App rot), ein unbekannter Abschnitt `WARN`.
9. **Erste Verbraucher:** #200 (Site-Handler) und #169 (Abruf mit Session). Hier wird mit einem Test-Shape getestet.
## Sicherheitsmodell (ehrlich)
Secrets außerhalb des Baums schützen vor dem Einchecken. Sie schützen auch davor, dass ein Wert in einer Datei steht, die der Agent bei normaler Arbeit liest, oder in einer Ausgabe von `wikitool` auftaucht. **Sie schützen nicht vor einem Agenten mit Shell-Zugriff, der es darauf anlegt.**
- Ist 1Password im Terminal entsperrt, kann der Agent `op read` selbst aufrufen.
- Die Secret-Datei kann er ebenfalls lesen.
- Was der Prozess von `wikitool` zur Laufzeit lesen kann, kann der Agent im selben Benutzerkontext grundsätzlich auch.
Das begrenzt man, ohne es zu verhindern:
- ein eigener 1Password-Tresor nur für die Einträge dieser Instanz;
- die Freigabe-Abfrage der 1Password-Desktop-App. Sie gilt je Terminal-Sitzung, nicht je Wert, hält also nur eine Sitzung auf, die noch niemand freigegeben hat;
- in der CI ein Service-Account, der nur diesen Tresor sieht.
Die Doku sagt das so (`docs/explanation/configuration-tiers.md`), und der Stack verspricht nichts darüber hinaus.
## Betroffene Dateien (gebaut)
- `tools/chemenu/config_shapes.py` (`tier`, `private`, `names_command`, `gate`, `SETTINGS_SECTIONS`), `tools/chemenu/config.py` (Dateinamen, `ENV_SECRET_PREFIX`, `secrets_file()`), `tools/chemenu/toolpaths.py` (`optional()`)
- neu: `tools/chemenu/settings.py`; `tools/chemenu/commands/config_cmd.py` mit Record, Gruppe "Configuration" in `cli_contract.GROUPS`; `_util.load_settings/setting_value`
- `tools/chemenu/commands/doctor.py`, `tools/chemenu/commands/docs_verify.py` (Kanarien `.wikitool-local.json` ignoriert / `wikitool.json` getrackt; `check_instance_settings`: nur Platzierung in `wikitool.json`, keine Pflichtfelder, die im lokalen File stehen dürfen)
- `tools/prerequisites.txt`, `tools/chemenu/prerequisites.py`, `tools/preflight.sh`, `tools/preflight.ps1`, `instructions/preflight.md`, `INSTALL.md`
- `.gitignore`, `tools/chemenu/tests/conftest.py` (`WIKITOOL_SECRET_*` per Präfix gelöscht)
- `dist_cmd.py` unverändert: `wikitool.json` steht nicht in `ROOT_FILES`, wird also nicht ausgeliefert und von `dist upgrade` nie berührt (Test `test_plan_ships_neither_settings_file`)
- `.gitea/workflows/ci.yml`
- `AGENTS.md` § Settings (neu) und § File naming (sieben statt sechs Erklärseiten), `instructions/dev/doc-pull-through.md`, `instructions/dev/testing-conventions.md`, `tools/README.md`
- `docs/explanation/configuration-tiers.md`, `docs/how-to/use-1password-for-settings.md` (beide in der Schlussphase nachgezogen, `e085a8b`), `docs/reference/configuration.md` § Tiered settings, `docs/reference/commands/configuration.md` (generiert)
- Tests: `test_settings.py` (neu), `test_preflight.py`, `test_preflight_pwsh.py`, `test_dist_cmd.py`
## Akzeptanzkriterien
- [x] Ein `Field` mit Stufe `instance`, das einen Befehl benennt, lässt sich nicht deklarieren (Test). - `test_a_field_that_names_a_program_or_a_gate_cannot_be_declared_instance`
- [x] Ein Wert in der falschen Stufe ergibt beim Lesen exit 1 mit Datei, Schlüssel und richtiger Stufe. - `test_a_value_in_the_wrong_tier_fails_naming_file_key_and_tier`
- [x] Ein Klartext-Wert in einem `secret`-Feld (beide Dateien) oder in einem `private`-Feld in `wikitool.json` ergibt exit 1. Der Wert erscheint in keiner Ausgabe. - `test_a_plain_secret_or_committed_private_value_fails_without_showing_it` (Kommando, `doctor`), `test_docs_verify_flags_a_plain_secret_in_the_committed_file_only`
- [x] `{"ref": "<name>"}` löst über `WIKITOOL_SECRET_<NAME>` auf. Ohne die Variable löst es über die Secret-Datei im Nutzerverzeichnis auf, mit dem Test-Home.
- [x] `{"ref": "op://…"}` löst über das falsche `op` auf. Ein gesperrtes `op` (Testskript mit entsprechendem Exit) ergibt exit 42, ein fehlendes `op` exit 1 mit dem Preflight-Hinweis. Dazu: Timeout → exit 42, fehlendes Element → exit 1 mit Verweis.
- [x] Ohne `wikitool.json` und `.wikitool-local.json` verhält sich jedes bestehende Kommando byte-identisch zum Stand davor. **Bau:** Ausnahme ist `doctor` mit seinen drei neuen Zeilen (nächstes Kriterium). Geprüft gegen einen Worktree von `HEAD`: `lint`, `search`, `version show`, `docs verify`, `instructions verify`, `types list`, `sources coverage` byte-identisch.
- [x] `doctor` zeigt für jede Stufe vorhanden/fehlt/fehlerhaft und für Verweise nur auflösbar/nicht auflösbar.
- [x] `config set` setzt einen `instance`-Wert in `wikitool.json` und verweigert einen Secret-Wert im Klartext.
- [x] `pytest`, `docs verify`, `instructions verify` grün; CI grün, mit einem echten 1Password-Wert in der CI. Die Action löst `op://CI-CD/gitea-package-token/username` auf, die Einstellung verweist per Namen darauf (Entwurf 6). CI-Run 644 grün, Smoke-Test `1 passed`; nach dem Doku-Nachzug erneut in Run 646. Ein `op://`-Verweis *in den Einstellungen selbst* ist in der CI nicht getestet, nur mit dem falschen `op` im Test (voriges Kriterium). Nicht blockierend, siehe Entwurf 6.
## Versionsteil
**`--minor`** - gebaut als `9.0.1-beta.2` → `9.1.0-beta.1`. Neue, optionale Dateien und ein neues Kommando, die eine ältere Version ignoriert. Ohne sie ändert sich kein Verhalten außer drei `OK`-Zeilen in `doctor`. Neue Umgebungsvariablen sind additiv, der optionale Eintrag in `.wikitool-tools.json` ebenfalls (geprüft, Entwurf 5). Drop-in in beide Richtungen. Der Bruch kommt erst mit #208.
## Kette
Kette „Beschaffung und Konfiguration“
- Vorgänger: #206
- Nachfolger: #208
torben
changed title from Konfiguration in drei Stufen: eingecheckt (Instanz), lokal (Checkout), Secrets außerhalb des Baums to Konfiguration in drei Stufen: eingecheckt (Instanz), lokal (Checkout), Secrets außerhalb des Baums - mit 1Password-CLI2026-10-10 06:15:36 +00:00
Changelog: Die vier offenen Fragen sind entschieden (2026-10-10): Dateinamen, Secrets über Umgebungsvariable oder Nutzerverzeichnis, config set. Neu ist die 1Password-CLI als Secret-Quelle mit op://-Verweisen, auch für private Nicht-Secrets wie URLs. Damit dürfen Verweise auf private Werte in die eingecheckte Datei. Neu ist auch ein ehrlicher Abschnitt zum Sicherheitsmodell: Ein Agent mit Shell erreicht, was das Werkzeug erreicht. Die CI-Anbindung wartet auf die Boilerplate des Betreibers zum Start des Baus. kind/decision → kind/build. Die Kettenzeile listet nicht mehr alle Glieder (Konvention aus #205).
**Changelog:** Die vier offenen Fragen sind entschieden (2026-10-10): Dateinamen, Secrets über Umgebungsvariable oder Nutzerverzeichnis, `config set`. Neu ist die 1Password-CLI als Secret-Quelle mit `op://`-Verweisen, auch für private Nicht-Secrets wie URLs. Damit dürfen Verweise auf private Werte in die eingecheckte Datei. Neu ist auch ein ehrlicher Abschnitt zum Sicherheitsmodell: Ein Agent mit Shell erreicht, was das Werkzeug erreicht. Die CI-Anbindung wartet auf die Boilerplate des Betreibers zum Start des Baus. `kind/decision` → `kind/build`. Die Kettenzeile listet nicht mehr alle Glieder (Konvention aus #205).
Changelog: Gebaut und publiziert als 9.1.0-beta.1 (f6aaadc), CI-Run 644 grün, inklusive des echten 1Password-Smoke-Tests. Die CI folgt der Boilerplate des Betreibers (gitea-mcp@ci-binford, Weg über die Action). Neu im Body an den jeweiligen Punkten (Bau:):
Der Action-Weg bedient nur Namensverweise. op:// in der CI braucht op plus Token und ist nicht getestet (nicht blockierend).
Auch gate-Felder setzt nur der Nutzer (exit 42).
private ist immer checkout.
config set prüft ohne Pflichtfelder.
doctor meldet WARN bei gesperrtem 1Password.
op steht als optional|-Zeile im Manifest.
Die Secret-Datei muss 0600 sein.
doctor ist die benannte Ausnahme vom Byte-identisch-Kriterium.
Alle Kriterien sind abgehakt. Offen bleibt nur die Schlussphase.
**Changelog:** Gebaut und publiziert als `9.1.0-beta.1` (`f6aaadc`), CI-Run 644 grün, inklusive des echten 1Password-Smoke-Tests. Die CI folgt der Boilerplate des Betreibers (`gitea-mcp@ci-binford`, Weg über die Action). Neu im Body an den jeweiligen Punkten (**Bau:**):
- Der Action-Weg bedient nur Namensverweise. `op://` in der CI braucht `op` plus Token und ist nicht getestet (nicht blockierend).
- Auch `gate`-Felder setzt nur der Nutzer (exit 42).
- `private` ist immer `checkout`.
- `config set` prüft ohne Pflichtfelder.
- `doctor` meldet `WARN` bei gesperrtem 1Password.
- `op` steht als `optional|`-Zeile im Manifest.
- Die Secret-Datei muss `0600` sein.
- `doctor` ist die benannte Ausnahme vom Byte-identisch-Kriterium.
Alle Kriterien sind abgehakt. Offen bleibt nur die Schlussphase.
Changelog: Abgeschlossen. Einstellungen gibt es jetzt in drei Stufen: wikitool.json (eingecheckt), .wikitool-local.json (lokal) und Secrets nur als Verweis, aufgelöst über WIKITOOL_SECRET_<NAME>, eine Secret-Datei im Nutzerverzeichnis oder die 1Password-CLI. Geschrieben wird mit dem neuen Kommando config set, ausgeliefert in 9.1.0-beta.1 (f6aaadc, CI-Run 644). In der Schlussphase wurden zwei Stellen der neuen Doku nachgezogen (e085a8b, CI-Run 646): der Pfad der Secret-Datei unter Windows und mit XDG im How-to, und dass die Freigabe-Abfrage von 1Password je Terminal-Sitzung gilt, nicht je Wert. Weiter mit #208.
**Changelog:** Abgeschlossen. Einstellungen gibt es jetzt in drei Stufen: `wikitool.json` (eingecheckt), `.wikitool-local.json` (lokal) und Secrets nur als Verweis, aufgelöst über `WIKITOOL_SECRET_<NAME>`, eine Secret-Datei im Nutzerverzeichnis oder die 1Password-CLI. Geschrieben wird mit dem neuen Kommando `config set`, ausgeliefert in `9.1.0-beta.1` (`f6aaadc`, CI-Run 644). In der Schlussphase wurden zwei Stellen der neuen Doku nachgezogen (`e085a8b`, CI-Run 646): der Pfad der Secret-Datei unter Windows und mit XDG im How-to, und dass die Freigabe-Abfrage von 1Password je Terminal-Sitzung gilt, nicht je Wert. Weiter mit #208.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Befund
wikitoolin einer eigenen, gitignorierten Datei pro Feature:.wikitool-remotes.json,.wikitool-telemetry.json,.wikitool-upload.json,.wikitool-tasks.json(dazu.wikitool-tasks.d/) und.wikitool-tools.json. Eingecheckt ist nur.wikitool-kb.json, und die beschreibt die Form des Korpus, ist also keine Einstellung.tools/chemenu/config.py, Absatz in.gitignore, Ignore-Kanarie indocs verify, Zeile indoctor, Doku.tools/chemenu/config_shapes.py:Shape/Field/check, benutzt vonupload.py,telemetry/policy.py,git_publish.py,tasks/*.py). Jeder Leser liest seine Datei aber selbst.api_tokeninsuperproductivity,app_passwordincaldav), im Klartext im Arbeitsbaum und nur durch.gitignoregeschützt.Die Altdateien bleiben bis #208 bestehen. Dieses Paket stellt nur das Ziel bereit.
Ziel
instance, eingechecktwikitool.jsonim Instanz-Rootcheckout, lokal.wikitool-local.json, gitignoredsecretEntscheidungen des Betreibers (2026-10-10)
wikitool.json, lokale Datei.wikitool-local.json.wikitool config set(Entwurf 7).op) als Secret-Quelle (Entwurf 5): für Desktop-Installationen die bevorzugte Variante, in der CI wie bei anderen Action-Runnern.opkann auch Nicht-Secrets liefern (URLs, Connection-Strings), was die Konfiguration über Rechner hinweg portabel macht.1da42d56b1be), samt der Bau-Entscheidungen unten (CI-Element,gate-Felder nur durch den Nutzer,WARNbei gesperrtem 1Password).Entwurf (gebaut)
Fieldvonconfig_shapes.py(tier="instance" | "checkout" | "secret"). Ein Wert in der falschen Stufe ist ein Fehler, keine Überschreibung; derselbe Schlüssel in beiden Dateien ebenso. Die Abschnitte stehen inconfig_shapes.SETTINGS_SECTIONS. Nach diesem Paket ist das Tupel leer, Abschnitte bringen #208 und die Verbraucher #200/#169. Bau: Ein Abschnitt ist flach - keine verschachtelten Felder, keine Varianten -, damit die Stufe am Feld allein ablesbar ist.names_command) oder ein Gate betrifft (gate), ist nieinstance.Field.__post_init__wirft beim Deklarieren. Auch als Verweis steht so ein Feld nie inwikitool.json. Die Regel steht für Agenten genau einmal:AGENTS.md§ Settings.secret-Feld nimmt nur einen Verweis, einprivate-Feld (private Infrastruktur) darf einen nehmen, alle anderen keinen. Zwei Formen:{"ref": "<name>"}(Kleinbuchstaben, Ziffern, einzelne_) und{"ref": "op://<vault>/<item>/<field>"}. Bau: Einprivate-Feld ist immer Stufecheckout(beim Deklarieren erzwungen): Klartext nur in.wikitool-local.json, als Verweis in beiden Dateien.WIKITOOL_SECRET_<NAME>, sonst~/.config/chemenu/<instanz-id>/secrets.json(Windows:%APPDATA%\chemenu\<instanz-id>\secrets.json). Die<instanz-id>(UUID) erzeugt das ersteconfig setinwikitool.json. Bau:$XDG_CONFIG_HOMEwird statt~/.configbeachtet, wenn gesetzt. "Nur für den Nutzer lesbar" wird erzwungen: außerhalb Windows wird eine Datei mit Rechten für Gruppe oder andere abgelehnt (exit 1, Hinweischmod 600).op read --no-newline <ref>ohne Shell, stdin/dev/null, Timeout 60 s, Wert nur im Speicher. Fehltop→ exit 1 mit Preflight-Hinweis. Element/Feld/Tresor fehlt (op-Meldung "isn't an item/a vault/a field", "does not have a field" …) → exit 1 mit dem Verweis. Jeder andere Fehler und ein Timeout gelten als gesperrt/nicht angemeldet → exit 42, ohne den Verweis. Bau:opsteht als neue Zeilenartoptional|op|…intools/prerequisites.txt; beide Preflights erfassen es, wenn vorhanden (ABSENTsonst, nie ein Problem),--set op=geht. Geprüft: Der Launcher liest aus.wikitool-tools.jsonnur"complete": true,toolpathsnur benannte Schlüssel - ein zusätzlicher Schlüssel stört keine ältere Version. Neu:toolpaths.optional().1password/load-secrets-action@v2lädtop://CI-CD/gitea-package-token/username(das am wenigsten sensible Feld, das der Service-Account sieht) nachWIKITOOL_SECRET_CI_SMOKE; der Testtest_live_secret_reference_resolves_from_cilöst{"ref": "ci_smoke"}darüber auf und läuft mitCHEMENU_LIVE_SECRET_REQUIRE=1, damit "kein Wert" rot statt übersprungen ist. Dazucurl unzipin den Systemabhängigkeiten, wie in der Boilerplate. In Run 644 und 646 bestätigt. Einschränkung, die der Bau gezeigt hat: Der Action-Weg bedient Namensverweise. Eine Konfiguration mitop://-Verweisen braucht in der CI den anderen Weg (opim Job plusOP_SERVICE_ACCOUNT_TOKEN). Der Code kann das, diese CI testet es nicht. "Dieselbe Konfiguration auf beiden Wegen" gilt also nur je Verweisform, und so steht es im How-to. Nicht blockierend: Braucht ein Verbraucher (#200, #169)op://in der CI, kommt der zweite Weg dort dazu.wikitool config set <schlüssel> <wert|--ref …>prüft Stufe und Form. Klartextinstance→wikitool.json, Klartextcheckout/private→.wikitool-local.json, Verweis →wikitool.json; derselbe Schlüssel in der anderen Datei wird entfernt und gemeldet. Ein Secret-Wert wird abgelehnt (exit 1, Wert nicht ausgegeben). Bau: "Nur der Nutzer setzt" gilt fürnames_commandundgate- wie bei der Allowlist des Publish-Remote Gate;config setendet dort mit exit 42 und nennt die Datei zum Selbst-Editieren. Vor dem Schreiben werden beide Dateien geprüft, aber ohne Pflichtfelder, sonst ließe sich der erste Wert eines Abschnitts nie schreiben (check_files(..., complete=False)).tools/chemenu/settings.py: liest beide Dateien, prüft Platzierung und Form, löst Verweise erst beim Zugriff auf, gibt einem Leser seinen Abschnitt. Bau: Für Kommandos gibt es_util.load_settings()und_util.setting_value()(exit 1 bzw. 42) - darüber testen die Kriterien die Exit-Codes, darüber lesen #200/#169.doctor: Zeilensettings-instance,settings-checkout,settings-secrets; ein nicht auflösbarer Verweis istFAIL, ein gesperrtes 1PasswordWARN(sonst wäredoctorbei gesperrter App rot), ein unbekannter AbschnittWARN.Sicherheitsmodell (ehrlich)
Secrets außerhalb des Baums schützen vor dem Einchecken. Sie schützen auch davor, dass ein Wert in einer Datei steht, die der Agent bei normaler Arbeit liest, oder in einer Ausgabe von
wikitoolauftaucht. Sie schützen nicht vor einem Agenten mit Shell-Zugriff, der es darauf anlegt.op readselbst aufrufen.wikitoolzur Laufzeit lesen kann, kann der Agent im selben Benutzerkontext grundsätzlich auch.Das begrenzt man, ohne es zu verhindern:
Die Doku sagt das so (
docs/explanation/configuration-tiers.md), und der Stack verspricht nichts darüber hinaus.Betroffene Dateien (gebaut)
tools/chemenu/config_shapes.py(tier,private,names_command,gate,SETTINGS_SECTIONS),tools/chemenu/config.py(Dateinamen,ENV_SECRET_PREFIX,secrets_file()),tools/chemenu/toolpaths.py(optional())tools/chemenu/settings.py;tools/chemenu/commands/config_cmd.pymit Record, Gruppe "Configuration" incli_contract.GROUPS;_util.load_settings/setting_valuetools/chemenu/commands/doctor.py,tools/chemenu/commands/docs_verify.py(Kanarien.wikitool-local.jsonignoriert /wikitool.jsongetrackt;check_instance_settings: nur Platzierung inwikitool.json, keine Pflichtfelder, die im lokalen File stehen dürfen)tools/prerequisites.txt,tools/chemenu/prerequisites.py,tools/preflight.sh,tools/preflight.ps1,instructions/preflight.md,INSTALL.md.gitignore,tools/chemenu/tests/conftest.py(WIKITOOL_SECRET_*per Präfix gelöscht)dist_cmd.pyunverändert:wikitool.jsonsteht nicht inROOT_FILES, wird also nicht ausgeliefert und vondist upgradenie berührt (Testtest_plan_ships_neither_settings_file).gitea/workflows/ci.ymlAGENTS.md§ Settings (neu) und § File naming (sieben statt sechs Erklärseiten),instructions/dev/doc-pull-through.md,instructions/dev/testing-conventions.md,tools/README.mddocs/explanation/configuration-tiers.md,docs/how-to/use-1password-for-settings.md(beide in der Schlussphase nachgezogen,e085a8b),docs/reference/configuration.md§ Tiered settings,docs/reference/commands/configuration.md(generiert)test_settings.py(neu),test_preflight.py,test_preflight_pwsh.py,test_dist_cmd.pyAkzeptanzkriterien
Fieldmit Stufeinstance, das einen Befehl benennt, lässt sich nicht deklarieren (Test). -test_a_field_that_names_a_program_or_a_gate_cannot_be_declared_instancetest_a_value_in_the_wrong_tier_fails_naming_file_key_and_tiersecret-Feld (beide Dateien) oder in einemprivate-Feld inwikitool.jsonergibt exit 1. Der Wert erscheint in keiner Ausgabe. -test_a_plain_secret_or_committed_private_value_fails_without_showing_it(Kommando,doctor),test_docs_verify_flags_a_plain_secret_in_the_committed_file_only{"ref": "<name>"}löst überWIKITOOL_SECRET_<NAME>auf. Ohne die Variable löst es über die Secret-Datei im Nutzerverzeichnis auf, mit dem Test-Home.{"ref": "op://…"}löst über das falscheopauf. Ein gesperrtesop(Testskript mit entsprechendem Exit) ergibt exit 42, ein fehlendesopexit 1 mit dem Preflight-Hinweis. Dazu: Timeout → exit 42, fehlendes Element → exit 1 mit Verweis.wikitool.jsonund.wikitool-local.jsonverhält sich jedes bestehende Kommando byte-identisch zum Stand davor. Bau: Ausnahme istdoctormit seinen drei neuen Zeilen (nächstes Kriterium). Geprüft gegen einen Worktree vonHEAD:lint,search,version show,docs verify,instructions verify,types list,sources coveragebyte-identisch.doctorzeigt für jede Stufe vorhanden/fehlt/fehlerhaft und für Verweise nur auflösbar/nicht auflösbar.config setsetzt eineninstance-Wert inwikitool.jsonund verweigert einen Secret-Wert im Klartext.pytest,docs verify,instructions verifygrün; CI grün, mit einem echten 1Password-Wert in der CI. Die Action löstop://CI-CD/gitea-package-token/usernameauf, die Einstellung verweist per Namen darauf (Entwurf 6). CI-Run 644 grün, Smoke-Test1 passed; nach dem Doku-Nachzug erneut in Run 646. Einop://-Verweis in den Einstellungen selbst ist in der CI nicht getestet, nur mit dem falschenopim Test (voriges Kriterium). Nicht blockierend, siehe Entwurf 6.Versionsteil
--minor- gebaut als9.0.1-beta.2→9.1.0-beta.1. Neue, optionale Dateien und ein neues Kommando, die eine ältere Version ignoriert. Ohne sie ändert sich kein Verhalten außer dreiOK-Zeilen indoctor. Neue Umgebungsvariablen sind additiv, der optionale Eintrag in.wikitool-tools.jsonebenfalls (geprüft, Entwurf 5). Drop-in in beide Richtungen. Der Bruch kommt erst mit #208.Kette
Kette „Beschaffung und Konfiguration“
torben referenced this issue2026-10-09 21:41:18 +00:00
Konfiguration in drei Stufen: eingecheckt (Instanz), lokal (Checkout), Secrets außerhalb des Baumsto Konfiguration in drei Stufen: eingecheckt (Instanz), lokal (Checkout), Secrets außerhalb des Baums - mit 1Password-CLIChangelog: Die vier offenen Fragen sind entschieden (2026-10-10): Dateinamen, Secrets über Umgebungsvariable oder Nutzerverzeichnis,
config set. Neu ist die 1Password-CLI als Secret-Quelle mitop://-Verweisen, auch für private Nicht-Secrets wie URLs. Damit dürfen Verweise auf private Werte in die eingecheckte Datei. Neu ist auch ein ehrlicher Abschnitt zum Sicherheitsmodell: Ein Agent mit Shell erreicht, was das Werkzeug erreicht. Die CI-Anbindung wartet auf die Boilerplate des Betreibers zum Start des Baus.kind/decision→kind/build. Die Kettenzeile listet nicht mehr alle Glieder (Konvention aus #205).Changelog: Gebaut und publiziert als
9.1.0-beta.1(f6aaadc), CI-Run 644 grün, inklusive des echten 1Password-Smoke-Tests. Die CI folgt der Boilerplate des Betreibers (gitea-mcp@ci-binford, Weg über die Action). Neu im Body an den jeweiligen Punkten (Bau:):op://in der CI brauchtopplus Token und ist nicht getestet (nicht blockierend).gate-Felder setzt nur der Nutzer (exit 42).privateist immercheckout.config setprüft ohne Pflichtfelder.doctormeldetWARNbei gesperrtem 1Password.opsteht alsoptional|-Zeile im Manifest.0600sein.doctorist die benannte Ausnahme vom Byte-identisch-Kriterium.Alle Kriterien sind abgehakt. Offen bleibt nur die Schlussphase.
Changelog: Abgeschlossen. Einstellungen gibt es jetzt in drei Stufen:
wikitool.json(eingecheckt),.wikitool-local.json(lokal) und Secrets nur als Verweis, aufgelöst überWIKITOOL_SECRET_<NAME>, eine Secret-Datei im Nutzerverzeichnis oder die 1Password-CLI. Geschrieben wird mit dem neuen Kommandoconfig set, ausgeliefert in9.1.0-beta.1(f6aaadc, CI-Run 644). In der Schlussphase wurden zwei Stellen der neuen Doku nachgezogen (e085a8b, CI-Run 646): der Pfad der Secret-Datei unter Windows und mit XDG im How-to, und dass die Freigabe-Abfrage von 1Password je Terminal-Sitzung gilt, nicht je Wert. Weiter mit #208.