feat(claude): emit userConfig manifest options (#187 slice 1) - #287
Conversation
Validate Claude enable-time options before adding them to native and unified plugin manifests, with pinned schema and host evidence.
🦋 Changeset detectedLatest commit: e3172ec The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3172ecde3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "if": { "properties": { "type": { "const": "number" } }, "required": ["type"] }, | ||
| "then": { "properties": { "default": { "type": "number" } } }, | ||
| "else": { "not": { "anyOf": [{ "required": ["min"] }, { "required": ["max"] }] } } |
There was a problem hiding this comment.
Validate numeric defaults against their declared bounds
When validating an independently assembled or rehashed artifact, this schema only verifies that a number option's default is numeric; it accepts contradictory declarations such as min: 10, max: 5 or default: 11, max: 10. The planner explicitly rejects both cases, but validateArtifact relies on this schema and therefore reports such artifacts as valid. Add equivalent relational validation to the artifact-validation contract so externally supplied manifests cannot bypass the planner's numeric-bound guarantees.
Useful? React with 👍 / 👎.
* fix(claude): validate numeric config bounds in artifacts (#287 r3911238592) * fix(claude): reject marketplace backslash traversal (#314 r3918535243) * fix(claude): validate authority-only archive hosts (#314 r3918535249) * fix(replay): preserve invocation provenance in renderers (#322 r3919341927) * fix(replay): derive workspace from cursor roots (#322 r3919341940) * fix(dev): invalidate watcher on chmod changes (#329 r3919499846) * chore: add framework review fixes changeset
Summary
claude.userConfigconfig surface: typed enable-time options (string/number/boolean/directory/file) validated at plan time and allowlist-copied into the generated.claude-plugin/plugin.jsonuserConfigfield, wired throughadditionalPluginSourceInputs.claude.userConfig.*diagnostics with recovery text, including two recorded tightenings beyond the documented text (in PROVENANCE notes): option keys pinned to^[A-Za-z_][A-Za-z0-9_]*$with rejection of keys that collide after uppercasing (both would export as the sameCLAUDE_PLUGIN_OPTION_<KEY>env var), and rejection ofsensitive: truecombined withdefault(a baked-in secure-storage default would ship a secret in the manifest). Type-directed default validation (string/array-with-multiple, bounded numbers, booleans) andmultiple/min/maxper-type constraints.userConfigOptiondefinition added to the pinned plugin schema (rehashed in PROVENANCE + adapter-metadata pins); option-declaration validation kept factored for the laterchannelsslice. Doc comments carry the sensitive-storage semantics (~2 KB Keychain budget shared with OAuth tokens) and the shell-substitution prohibition.userConfigdriven by a new pinnedplugin.userConfigfacts block with six dated 2026-09-01 evidence lines (option contract,${user_config.KEY}substitution surfaces +CLAUDE_PLUGIN_OPTION_export, shell-substitution rejections with documented alternatives and the v2.1.207 boundary, storage/precedence incl. project-settings-ignored,claude plugin install --config, and the local 2.1.257 host proof); honestunavailablemirror on the unified bundle. Substitution/rejection enforcement inside hook/MCP planning is deliberately out of scope (hooks-fidelity slice) and recorded as evidence only.Part of #187 slice 1 (systematic Claude host-parity pass).
Test plan
pnpm typecheckpnpm lint(0 errors, 0 warnings, 977 files)