From 918f8f709d9bee78bc67c20327fe9ab35c8e3b21 Mon Sep 17 00:00:00 2001 From: Yeachan-Heo Date: Thu, 21 May 2026 00:00:53 +0000 Subject: [PATCH] docs(roadmap): add config env type validation gap --- ROADMAP.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index 3f1072a1..b97ee65e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6587,3 +6587,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed) 515. **Config `model` values are parsed with `JsonValue::as_str` and otherwise silently ignored, so non-string model config falls back to defaults with no error or warning** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 23:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@07a12d4`, following Jobdori's config-loader diagnostic sweep. Code inspection: after validation/merge, `ConfigLoader::load` builds `RuntimeFeatureConfig { model: parse_optional_model(&merged_value), ... }`. `parse_optional_model` is `root.as_object().and_then(|object| object.get("model")).and_then(JsonValue::as_str).map(ToOwned::to_owned)`. If a config file contains `{"model": 123}`, `{"model": null}`, `{"model": ["opus"]}`, or an object, `parse_optional_model` returns `None` exactly as if no model key existed. Other config fields use typed helpers that return `ConfigError::Parse` on wrong types (`permissions.defaultMode`, plugin fields, hooks, etc.), so `model` is an outlier. **Required fix shape:** (a) replace `parse_optional_model -> Option` with `Result, ConfigError>`; (b) when `model` exists but is not a non-empty string, emit `ConfigError::Parse` or a structured warning with path/key/type; (c) run the same model-syntax validator used for `--model` and env model values so config, env, and CLI flag agree; (d) expose `model_source`, `model_raw`, and validation diagnostics in status/config JSON; (e) add regressions for numeric/null/array/object model values proving they are not silently treated as missing. **Why this matters:** model selection is control-plane state. A typo like `model: ["opus"]` should not silently revert to the default model while status appears healthy; that creates prompt misdelivery and cost surprises that are hard to attribute back to config. Source: gaebal-gajae dogfood response to Clawhip message `1506793682257580144` on 2026-05-20. 516. **`config env --output-format json` prints raw environment secret values from config files, including API-key-shaped entries, instead of redacting sensitive keys** — dogfooded 2026-05-20 from the `#clawcode-building-in-public` 23:30 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@fbd2f01` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Reproduction in a clean temp workspace: create `.claw.json` with `{"env":{"ANTHROPIC_API_KEY":"sk-SECRET-should-not-print","SAFE":"ok"}}`, then run `claw config env --output-format json`. The command exits 0 and emits `section_value` containing the raw `ANTHROPIC_API_KEY` value unchanged while also showing benign keys like `SAFE`. This makes the config-inspection surface unsafe to paste into issue reports, Discord, CI logs, or support threads. **Required fix shape:** (a) redact values for sensitive key patterns (`*_API_KEY`, `*_TOKEN`, `*_SECRET`, `PASSWORD`, `AUTH`, etc.) in both JSON and text config inspection output; (b) preserve enough metadata for debugging (`redacted:true`, maybe `value_present:true`, source file, key name) without exposing bytes; (c) keep non-sensitive env values visible; (d) add a `--show-secrets`/`--unsafe-show-secrets` escape hatch only if explicitly confirmed and never enabled by default; (e) add regression coverage for `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, token/password variants, and safe keys. **Why this matters:** `config env` is exactly the surface operators use when debugging configuration. If it dumps credentials by default, the first support/debug paste can leak provider keys. Automation-friendly JSON must be safer than prose, not a secret exfiltration footgun. Source: gaebal-gajae dogfood response to Clawhip message `1506801223465046210` on 2026-05-20. + +517. **`config env --output-format json` accepts and reports non-string env values instead of validating that environment variables are strings** — dogfooded 2026-05-21 from the `#clawcode-building-in-public` 00:00 UTC nudge on `/home/bellman/Workspace/claw-code-pr2967` with branch/origin `docs/roadmap-workdir-provenance@0bbe19e` and binary `./rust/target/debug/claw` built from source SHA `25d663d`. Reproduction in a clean temp workspace: create `.claw.json` with `{"env":{"SAFE":123}}`, then run `claw config env --output-format json`. The command exits 0 and emits `section_value:{"SAFE":123}`. Runtime environment variables cannot be numeric/array/object/null values; any later application step must stringify, ignore, or fail elsewhere. This is inconsistent with the stricter config helpers for hooks/plugins/provider fallbacks and with the model-type gap recorded in #515. **Required fix shape:** (a) validate `env` config as a string map during config load/section inspection; (b) for non-string values, return a typed parse/config diagnostic naming the file/key/type, or preserve partial success with `invalid_env:[{key, reason}]` while excluding the bad key from resolved env; (c) keep `config env` JSON machine-usable by returning only string values plus explicit invalid-entry metadata; (d) combine with #516 secret redaction so valid secret strings are redacted and invalid secret-shaped keys do not leak values; (e) add regressions for numeric, boolean, null, array, and object env values. **Why this matters:** config inspection should reflect values that can actually be exported. Accepting JSON-native non-string values as env config makes status/config look healthy while leaving the eventual runtime behavior ambiguous and brittle for automation. Source: gaebal-gajae dogfood response to Clawhip message `1506808785480454194` on 2026-05-21.