Skip to content

Commit c9b2993

Browse files
author
SqlRush
committed
Validate marketplace source settings
1 parent dfb98a5 commit c9b2993

5 files changed

Lines changed: 309 additions & 4 deletions

File tree

docs/cc-100-roadmap.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ M7 补充:prompt history `LogEntry` 读取现在接受 `sessionID`/`session`/`
731731
本轮补充:`cmd/claude --help` 现在沿用 Go flag usage 输出并成功退出;`cmd/claude --cwd` 现在会设置 bootstrap working directory,影响 scaffold 输出、project settings、tool cwd 和 transcript path;`cmd/claude --print/-p` 现在接入真实 `conversation.Runner.RunTurn` 单轮 headless 路径,可从参数或 stdin 读取 prompt,读取 `ANTHROPIC_API_KEY`/`ANTHROPIC_BASE_URL`/`ANTHROPIC_MODEL`/`CLAUDE_MODEL`/settings model,解析模型别名,装配 builtin tools、settings-derived permission engine、settings-derived MCP config,并把最终 assistant text 写到 stdout;`--mcp-config`/`--mcpConfig` 现在会把指定 JSON 文件中的 `mcpServers` 合入 headless MCP local settings;`--input-format`/`--inputFormat` text/json/stream-json 现在有基础输入解析,支持 JSON prompt/user message 和 NDJSON user event;`--max-turns`/`--maxTurns` 现在会限制 headless tool-use loop 轮数,`--max-tokens`/`--maxTokens` 和 `--max-turns`/`--maxTurns` 都会拒绝负值;`--output-format`/`--outputFormat` json 现在会输出基础 result envelope,`stream-json` 会先输出基础 `system/init` 事件,再输出 NDJSON event stream 并以 result 行收尾,包含 result text、session id、assistant message、stop reason、model、usage 和 tool results;headless setup/resume/RunTurn 错误现在会在 JSON 模式输出 `subtype:error` result,在 stream-json 模式输出 `type:error` event;`--permission-mode`/`--permissionMode`、`--dangerously-skip-permissions`/`--dangerouslySkipPermissions`、`--system-prompt`/`--systemPrompt` 和 `--append-system-prompt`/`--appendSystemPrompt` 现在也有 CLI 接线或 camelCase alias;`--stream --output-format stream-json` 现在还会透出 raw Anthropic streaming events,包括 text delta;headless `--resume <session-id-or-jsonl>` 和 `--continue` 现在会加载当前项目 transcript chain 作为 history,并把新回合追加回同一个 transcript;`--allowedTools`/`--allowed-tools` 和 `--disallowedTools`/`--disallowed-tools` 现在会作为 CLI permission rules 合入 headless permission engine;`--add-dir`/`--addDir` 现在会作为 CLI additional working directory 合入 headless permission context。
732732
本轮补充:settings 文件读取现在有 path-keyed cache,按 size/mode/mtime 指纹复用内容并提供 cache reset;新增 settings change detector,可对 settings 文件快照区分 created/modified/deleted,并在检测到变化时清空 settings 文件缓存。
733733

734-
当前状态:bootstrap/config/auth/model 基础已完成;settings 已有 merge、managed policy、settings file cache/change detector、JSON Schema generation、`extraKnownMarketplaces` settings-source key/name validation 和 `strictPluginOnlyCustomization` 基础 enforcement;CLI 已有 `--version`、`--help` 成功退出、`--cwd` working directory override、scaffold settings 校验、基础 `--print` headless 单轮执行路径、基础 `--mcp-config`、基础 input-format text/json/stream-json、`--max-turns` tool loop 限制、基础 JSON result/error 输出、基础 stream-json init/event/error 输出、raw streaming event 透传、headless resume/continue transcript 接线、system prompt flags、dangerously-skip-permissions、常见 camelCase flag aliases、CLI allow/deny tool rules 和 CLI add-dir additional working directory context,但完整参数矩阵、交互 TUI 主循环、resume picker/UI、官方 SDK NDJSON/control protocol、settings live reload/app-state sync 和官方 stdout/stderr/exit-code parity 仍未完整兼容 CC。
734+
当前状态:bootstrap/config/auth/model 基础已完成;settings 已有 merge、managed policy、settings file cache/change detector、JSON Schema generation、marketplace source union 基础 validation 和 `strictPluginOnlyCustomization` 基础 enforcement;CLI 已有 `--version`、`--help` 成功退出、`--cwd` working directory override、scaffold settings 校验、基础 `--print` headless 单轮执行路径、基础 `--mcp-config`、基础 input-format text/json/stream-json、`--max-turns` tool loop 限制、基础 JSON result/error 输出、基础 stream-json init/event/error 输出、raw streaming event 透传、headless resume/continue transcript 接线、system prompt flags、dangerously-skip-permissions、常见 camelCase flag aliases、CLI allow/deny tool rules 和 CLI add-dir additional working directory context,但完整参数矩阵、交互 TUI 主循环、resume picker/UI、官方 SDK NDJSON/control protocol、settings live reload/app-state sync 和官方 stdout/stderr/exit-code parity 仍未完整兼容 CC。
735735

736736
### M3: API Client And Conversation Loop
737737

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ test/parity/ # golden tests against TS/official behavior
143143
- 本轮补充:`strictPluginOnlyCustomization` 已开始按 policy settings 生效,当前覆盖已实现的 `skills``mcp``hooks` surfaces:锁定后 user/project/local skills 与 legacy commands 不加载,manual MCP server sources 不加载但 plugin/admin policy 仍保留,settings hooks 只保留 policy hooks 且 plugin hooks 继续运行。agents 与更深 frontmatter/runtime edge cases 仍按缺口追踪。
144144
- 本轮补充:settings 文件读取现在有 path-keyed cache,按 size/mode/mtime 指纹复用内容并提供 `ResetSettingsCache`;新增 settings change detector,可对 settings 文件快照区分 created/modified/deleted,并在检测到变化时清空 settings 文件缓存。完整 watcher、remote managed refresh 和 app-state 同步仍按缺口追踪。
145145
- 本轮补充:新增 settings JSON Schema generation,`SettingsJSONSchema()` 会从 `contracts.Settings` 反射生成 draft 2020-12 schema,补强 `$schema` const、permission mode enum、`strictPluginOnlyCustomization` union 和 login method enum;`/config show schema` 现在可展示 schema ID、draft、字段数和生成大小,完整 Zod message parity 仍按缺口追踪。
146-
- 本轮补充:settings validation 现在覆盖官方 `extraKnownMarketplaces` settings-source key/name 一致性规则:当 inline marketplace `source.source=="settings"` 时,`source.name` 必须等于 `extraKnownMarketplaces` 的 map key;github/git/url 等 fetched sources 不做此约束。完整 marketplace source allow/block enforcement 仍按缺口追踪。
146+
- 本轮补充:settings validation 现在覆盖官方 marketplace source union 的基础语义,适用于 `extraKnownMarketplaces[].source``strictKnownMarketplaces[]``blockedMarketplaces[]`:校验 source discriminator、各 source 类型必填字段、URL source 绝对 URL、headers string record、github/git sparsePaths string array、settings-source plugins array、settings-source name 安全/保留名,并继续覆盖 inline marketplace key/name 一致性。运行时 marketplace source allow/block enforcement 仍按缺口追踪。
147147

148148
### M4: Tool framework、permissions、sandbox
149149

docs/first-second-parity-audit.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ Anthropic API 和 conversation:
8989
- A basic `Skill` tool wrapper is now registered with the default built-in tool set. It can invoke local project prompt skills through the command registry, returns the official-style `Launching skill: ...` result plus structured command metadata, and passes expanded meta user messages through `ToolResult.NewMessages`; the conversation runner now appends those new messages to transcripts and subsequent model requests.
9090
- Basic slash prompt command invocation is now wired for local project prompt skills: `/skill args` is parsed before the model request, converted into official-shaped command metadata plus expanded meta prompt messages, appended to transcript parent chains, and can override the turn model from skill frontmatter.
9191
- Local prompt-skill slash commands and the `Skill` tool now emit `command_permissions` attachments, parse `allowed-tools` into command-scoped permission rules, and merge those rules into the engine permission decider for the current turn so authorized follow-up tool calls can pass without leaking into later turns.
92-
- Settings schema coverage was expanded for major Claude Code settings keys: auth helpers, model allowlists/overrides, MCP policy, hooks policy, worktree, shell, output style, language, thinking/effort, plugins, remote, spinner, sandbox, and related flags. Settings parsing now also coerces `env` values to strings, filters invalid permission rules into warnings, validates key permission fields, applies WebSearch/WebFetch-specific permission-rule validation, warns when `extraKnownMarketplaces` settings-source entries have mismatched map key/source name, loads managed policy from macOS MDM plist / Windows HKLM, platform `managed-settings.json`, sorted `managed-settings.d/*.json` drop-ins, and Windows HKCU fallback, honors `allowManagedPermissionRulesOnly` for permission-rule merging, enforces `strictPluginOnlyCustomization` for the implemented `skills`, `mcp`, and `hooks` surfaces so user/project/local customizations are skipped while plugin/admin sources remain, includes a path-keyed settings file cache plus a snapshot-based settings change detector that classifies created/modified/deleted settings files and resets cached reads on change, and now generates a JSON Schema from `contracts.Settings` with `/config show schema` summary visibility.
92+
- Settings schema coverage was expanded for major Claude Code settings keys: auth helpers, model allowlists/overrides, MCP policy, hooks policy, worktree, shell, output style, language, thinking/effort, plugins, remote, spinner, sandbox, and related flags. Settings parsing now also coerces `env` values to strings, filters invalid permission rules into warnings, validates key permission fields, applies WebSearch/WebFetch-specific permission-rule validation, validates marketplace source union basics across `extraKnownMarketplaces`, `strictKnownMarketplaces`, and `blockedMarketplaces` including settings-source map key/source name consistency, loads managed policy from macOS MDM plist / Windows HKLM, platform `managed-settings.json`, sorted `managed-settings.d/*.json` drop-ins, and Windows HKCU fallback, honors `allowManagedPermissionRulesOnly` for permission-rule merging, enforces `strictPluginOnlyCustomization` for the implemented `skills`, `mcp`, and `hooks` surfaces so user/project/local customizations are skipped while plugin/admin sources remain, includes a path-keyed settings file cache plus a snapshot-based settings change detector that classifies created/modified/deleted settings files and resets cached reads on change, and now generates a JSON Schema from `contracts.Settings` with `/config show schema` summary visibility.
9393
- Model registry now uses current Claude model IDs and aliases from the source snapshot, including Sonnet 4.6, Opus 4.6, Haiku 4.5, canonical-name rendering, and `[1m]` context variants.
9494
- OAuth support now includes production OAuth config, scope parsing, Claude.ai scope detection, auth URL construction, PKCE verifier/challenge, state generation, and expiry checks.
9595
- Session/history support now includes CC-compatible prompt history references, pasted text/image placeholder parsing, paste-cache hashing and retrieval, `history.jsonl` append/load, current-session-first up-arrow ordering, ctrl+r-style deduped timestamped history, `CLAUDE_CODE_SKIP_PROMPT_HISTORY`, remote session event pagination helpers, lenient transcript loading, legacy progress parent-bridge recovery, compact-boundary pruning, snip removal/relink replay, metadata entry collection, leaf UUID calculation, conversation-chain reconstruction, orphaned parallel tool-result recovery, content-replacement record loading/reconstruction, tombstone metadata delete/relink replay, and tombstone-style transcript message removal with a size guard.
@@ -108,7 +108,7 @@ The following items remain incomplete and must not be treated as done:
108108
- Full tool execution parity gaps that remain: complete hook runtime policy beyond the current settings command hook path, MCP elicitation, complete SDK control event surface beyond current progress NDJSON, mid-call cancellation for concrete tools, background task behavior, telemetry, schema-not-sent hints, and concrete tool-specific semantics.
109109
- Complete Anthropic API parity gaps that remain: dynamic beta-header latching for any remaining provider-specific feature gates beyond prompt-cache/cache-editing/strict-output/1M-context requests, ant-only dump gating and remote `/issue` submission integration beyond the current local context summary, full official cost tracker/session restore lifecycle beyond current transcript usage restore, post-handshake streaming failure semantics, deeper gateway/proxy auth and routing behavior beyond static custom headers, first-party/Bedrock/Vertex/Foundry client setup, deeper OAuth account/profile lifecycle beyond request-time refresh retry, fast-mode retry/cooldown semantics, persistent unattended retry heartbeats, full prompt-cache editing lifecycle, and provider-specific cache behavior.
110110
- Full conversation/query loop: stop hooks, compact/auto-compact, token budget escalation, resume, SDK JSON/NDJSON control events, status updates, rate-limit handling, model switch breadcrumbs, side questions.
111-
- Full settings parity gaps that remain: complete Zod-equivalent validation messages, remote managed-settings loading and refresh, remaining plugin-only customization enforcement for agents and deeper frontmatter/runtime edge cases, deeper strict marketplace source allow/block enforcement through marketplace install/load flows, and full live reload/app-state sync.
111+
- Full settings parity gaps that remain: complete Zod-equivalent validation messages, remote managed-settings loading and refresh, remaining plugin-only customization enforcement for agents and deeper frontmatter/runtime edge cases, runtime marketplace source allow/block enforcement through marketplace install/load flows, and full live reload/app-state sync.
112112
- Full session/history parity gaps that remain: large-file optimized transcript loading, preserved-segment edge cases beyond current relink/prune support, content-replacement feature-flag/runtime override and inherited subagent gap-fill details, complete async prompt-history lifecycle parity beyond current lock/buffer/undo paths, full pasted-image processing/runtime integration beyond current prompt image-cache/image-block/metadata path, remaining remote-history edge cases, sidechain/subagent transcript layout, and all session metadata entry types.
113113

114114
## Current Verification

internal/config/settings_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,66 @@ func TestValidateSettingsAllowsMatchingSettingsMarketplaceAndFetchedSources(t *t
257257
}
258258
}
259259

260+
func TestValidateSettingsWarnsForInvalidMarketplaceSources(t *testing.T) {
261+
_, warnings, err := ParseSettingsJSON([]byte(`{
262+
"extraKnownMarketplaces": {
263+
"bad-url": {
264+
"source": {
265+
"source": "url",
266+
"url": "not a url",
267+
"headers": {"Authorization": 42}
268+
}
269+
},
270+
"bad-settings": {
271+
"source": {
272+
"source": "settings",
273+
"name": "inline"
274+
}
275+
},
276+
"missing-repo": {
277+
"source": {
278+
"source": "github",
279+
"sparsePaths": [".claude-plugin", 12]
280+
}
281+
}
282+
},
283+
"strictKnownMarketplaces": [
284+
{"source": "git", "url": 42},
285+
{"source": "unknown"}
286+
],
287+
"blockedMarketplaces": [
288+
{"source": "file", "path": "/opt/marketplace.json"},
289+
"bad"
290+
]
291+
}`), "settings.json")
292+
if err != nil {
293+
t.Fatal(err)
294+
}
295+
paths := map[string]int{}
296+
for _, warning := range warnings {
297+
paths[warning.Path]++
298+
}
299+
for _, path := range []string{
300+
"extraKnownMarketplaces.bad-url.source.url",
301+
"extraKnownMarketplaces.bad-url.source.headers.Authorization",
302+
"extraKnownMarketplaces.bad-settings.source.plugins",
303+
"extraKnownMarketplaces.bad-settings.source.name",
304+
"extraKnownMarketplaces.bad-settings.source.name",
305+
"extraKnownMarketplaces.missing-repo.source.repo",
306+
"extraKnownMarketplaces.missing-repo.source.sparsePaths[1]",
307+
"strictKnownMarketplaces[0].url",
308+
"strictKnownMarketplaces[1].source",
309+
"blockedMarketplaces[1]",
310+
} {
311+
if paths[path] == 0 {
312+
t.Fatalf("missing warning path %q in %#v warnings=%#v", path, paths, warnings)
313+
}
314+
}
315+
if paths["blockedMarketplaces[0].path"] != 0 {
316+
t.Fatalf("valid blocked marketplace produced warning paths=%#v warnings=%#v", paths, warnings)
317+
}
318+
}
319+
260320
func TestMergeSettings(t *testing.T) {
261321
defaultWorktree := true
262322
overrideWorktree := false

0 commit comments

Comments
 (0)