Skip to content

feat(redact-text): declare config_schema and consume typed __config (template for #147) - #149

Draft
JordanTheJet wants to merge 1 commit into
mainfrom
feat/redact-text-config-schema
Draft

feat(redact-text): declare config_schema and consume typed __config (template for #147)#149
JordanTheJet wants to merge 1 commit into
mainfrom
feat/redact-text-config-schema

Conversation

@JordanTheJet

Copy link
Copy Markdown
Contributor

Summary

Template migration for #147: the canonical reference plugin (redact-text) gains its config_schema and consumes typed __config, ahead of the host enforcement landing in zeroclaw-labs/zeroclaw#9126. The other 30 packages should copy this PR's shape.

  • Schema: closed Draft 2020-12, all-optional (replacement string minLength=1, redact_emails boolean, patterns array of non-empty strings), additionalProperties = false. Validated against the real host validator (validate_manifest_config / resolve_plugin_config from the zeroclaw#9126 head) with per-constraint rejection probes and a withheld-grant {} acceptance check; an un-migrated manifest fails the same harness, so the check is not vacuous.
  • Guest change is REQUIRED, and skipping it is a hard break: with __config typed, the old HashMap<String, String> field fails the entire ExecuteArgs parse and every call returns "invalid arguments". RedactConfig now derives Deserialize with serde defaults; from_json replaces from_section; JSON null (host injected nothing) yields defaults; malformed config errors, never silently defaults.
  • Config errors cannot leak config values: from_json returns a pre-sanitized error string because serde_json::Error's Display quotes the offending value, and this plugin's patterns are exactly the strings an operator wants scrubbed. Mutation-checked: the naive version leaks the value verbatim into the ToolResult.
  • Version 0.3.0 in three files (manifest.toml, Cargo.toml, Cargo.lock — CI runs --locked). registry.json untouched; build-registry.py --check-metadata classifies the new version as pending unpublished source, and release CI publishes it.
  • README updated from the now-false comma-separated patterns documentation to the JSON-array encoding and instance-key flow.

Checks

cargo test --locked                               14 passed (baseline 7)
cargo clippy --locked --all-targets -- -D warnings clean (host + wasm32-wasip2)
cargo build --locked --target wasm32-wasip2 --release   ok (186,999 bytes)
cargo fmt --check                                 clean
tools/build-registry.py --check-metadata          11 matched + redact-text@0.3.0 pending
tools/ci tests                                    36 OK on a pristine tree

Mutation evidence: six guards disabled individually, each failing exactly its covering test (including the leak guard and the empty-pattern filter, whose removal rewrites entire inputs into replacement markers); all files restored byte-identical.

Template notes for the remaining 30 (also posted to #147)

  1. Version bump is three files; the lockfile is the one that gets forgotten.
  2. Assume a guest change is needed; grep for HashMap<String, String>, eq_ignore_ascii_case, .split(',').
  3. Never let a config error echo the config value.
  4. Keep guest-side normalization even where the schema duplicates it.
  5. Decide required per key deliberately: credential-bearing channel plugins should fail closed, unlike this one.
  6. Do not add deny_unknown_fields guest-side.

Adds the closed Draft 2020-12 config_schema (replacement string with
minLength, redact_emails boolean, patterns string array) and migrates the
guest off the string-map contract: RedactConfig derives Deserialize with
serde defaults, from_json replaces from_section, and a malformed object
reports a pre-sanitized error instead of echoing config values, which are
the very strings this plugin exists to scrub. Version 0.3.0 across
manifest, Cargo.toml, and Cargo.lock; README moves to the JSON-array
operator encoding and the instance-key flow.

The old contract is a hard break, not a degradation: with __config typed,
a HashMap-based ExecuteArgs fails the entire argument parse and every
call returns invalid arguments.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant