@sema-agent/settings-schema 12.2.1 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +223 -0
- package/README.md +41 -6
- package/conformance/VERSION +1 -1
- package/conformance/cases/c01-entry-salvage-then-typo/expected.json +1 -3
- package/conformance/cases/c03-literal-dotted-top-key/expected.json +4 -12
- package/conformance/cases/c10-record-key-secret-redacted-twice/expected.json +1 -3
- package/conformance/cases/c23-mixed-validity-models/expected.json +2 -6
- package/conformance/cases/c24-valid-entries-with-unknown-keys/expected.json +2 -6
- package/conformance/cases/c25-published-roundtrip-zero-warnings/expected.json +2 -6
- package/conformance/cases/c30-version-triple-a-first/expected.json +2 -6
- package/conformance/cases/c31-version-triple-b-changed/expected.json +2 -6
- package/conformance/cases/c32-version-triple-a-restored/expected.json +2 -6
- package/conformance/cases/c40-s712-identity-only-what-reads-out/expected.json +1 -3
- package/conformance/cases/c41-s792-encoded-pem-identity/expected.json +1 -3
- package/conformance/cases/c42-s792-unknown-key-secret-redacted/expected.json +2 -6
- package/conformance/cases/c43-s792-form-and-deep-encoded-pem/expected.json +1 -3
- package/conformance/cases/c44-s792-utf8-escape-glued-token/expected.json +1 -3
- package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/expected.json +1 -3
- package/conformance/cases/c47-s811-roles-key-url-userinfo-withheld/expected.json +1 -3
- package/conformance/cases/c48-s935-model-headers-transported/expected.json +6 -18
- package/conformance/cases/c49-s935-model-headers-secret-entry-dropped/expected.json +1 -3
- package/conformance/cases/c69-deep-encoded-token-past-every-reading/expected.json +1 -3
- package/conformance/cases/c70-rewritten-token-in-front-of-encoded-pem-header/expected.json +1 -3
- package/conformance/cases/c72-dangling-reference-write-seat-refuses/expected.json +1 -3
- package/conformance/cases/c76-projects-entry-salvage-nested/expected.json +142 -0
- package/conformance/cases/c76-projects-entry-salvage-nested/input.json +54 -0
- package/conformance/cases/c76-projects-entry-salvage-nested/meta.json +6 -0
- package/conformance/cases/cc03-model-compat-unknown-subkey/expected.json +2 -6
- package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +1 -3
- package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +1 -3
- package/conformance/cases/cli05-long-and-prefix-colliding-names/expected.json +6 -18
- package/conformance/cases/t01-absent-domain-key-not-null/expected.json +1 -3
- package/conformance/cases/t03-prototype-name-key-not-swallowed/expected.json +2 -6
- package/conformance/cases/t04-secret-literal-never-in-warning-value/expected.json +1 -3
- package/dist/config-fns.d.ts +94 -8
- package/dist/config-fns.js +254 -116
- package/dist/hooks-config.d.ts +235 -0
- package/dist/hooks-config.js +458 -0
- package/dist/hooks.d.ts +16 -154
- package/dist/hooks.js +17 -111
- package/dist/http-hook-allowlists.d.ts +63 -0
- package/dist/http-hook-allowlists.js +73 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +6 -1
- package/dist/mcp-server-policy.d.ts +75 -0
- package/dist/mcp-server-policy.js +84 -0
- package/dist/safety-merge-spec.d.ts +13 -3
- package/dist/safety-merge-spec.js +10 -3
- package/dist/settings-sources.d.ts +91 -0
- package/dist/settings-sources.js +107 -0
- package/dist/types.d.ts +6 -6
- package/dist/types.js +9 -5
- package/dist/ui-language.d.ts +40 -0
- package/dist/ui-language.js +37 -0
- package/dist/url-pattern.d.ts +33 -0
- package/dist/url-pattern.js +239 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,229 @@
|
|
|
6
6
|
> `@sema-agent/registry-core`(更早还曾是 `@sema-ai/registry-core`)。本档 `0.19.0` 以下各节里的
|
|
7
7
|
> 包名是**历史记录**,如实保留不追改。
|
|
8
8
|
|
|
9
|
+
## 13.0.0 — 2026-10-16 — major:hooks 坏形一只读者 `classifyHooksConfig` · 设置源表 + 层准入 `layerAdmission`(层档只有源表一个读者)· URL 名单判官两出口 · 新类目 `httpHookAllowlists` + http hook 两张名单跨层取交 · MCP 名单判决 `mcpServerPolicyVerdict` · 界面语言设置片段 · 模型能力位三态(major)
|
|
10
|
+
|
|
11
|
+
> 档位:**major**。按「发版纪律」三处是破坏性(B1 `HooksConfig` 族受理面收紧且读数变 · B2 八只 hooks zod 面改形 · B3 `ModelEntry.reasoning` / `vision`
|
|
12
|
+
> 去缺省值),逐条见下「BREAKING 清单」;另两处是词表尾插(P1 hook 条目 type `mcp_tool` · P2 `SafetyMergeCategory` 加 `httpHookAllowlists`),按发版纪律的裁定例外
|
|
13
|
+
> 算提货成本、不单独构成 major,但同样逐条写了下游动作。
|
|
14
|
+
> 导出面(`docs/API-SURFACE.md`):主 barrel 588 → 638(+50:hooks 分类器与设置源表 22 · URL / http hook / MCP / 界面语言 27 · 源表查口 `settingsSourceContract` 1),
|
|
15
|
+
> `./hooks` 81 → 94(+13);零删、零改名。登记表看不见的变化:八只 hooks zod 面的 schema 形(B2)、`ModelEntry` 两键型面加 `undefined`(B3)。
|
|
16
|
+
> 一致性语料 28 例重录(B3;差只在没写这两键的条目)。
|
|
17
|
+
|
|
18
|
+
### BREAKING 清单(逐条三问 + 下游动作)
|
|
19
|
+
|
|
20
|
+
**B1 · `HooksConfig` / `HookMatcherEntry` / `HookEntry` / 逐 type 五只的受理面收紧、读数变**(校验收紧 + 同一份配置解析出不同结果)。
|
|
21
|
+
差分门(冻结 12.3.0 定义对新面,>500 条语料)量出的差:① 本会被剥掉的未知字段里藏着守卫迹象 ⇒ 拒(旧:剥掉照受理);② JSON 里写出来的 `__proto__` 事件键不再被跳过
|
|
22
|
+
(未知事件:剔 ⇒ 面上拒;装着守卫:拒);③ http `headers` 里字面叫 `__proto__` 的键留作自有键(旧:被记录型赋值丢掉);④ issue 从 zod 句子变成「码 + 坐标 + 坏字段名」。
|
|
23
|
+
(差分的第四类 `mcp_tool` 受理是 P1。)
|
|
24
|
+
**谁需要**:收 `settings.hooks` 的服务端与读设置文件的宿主 —— 守卫不再能藏进被剥掉的字段里无声消失,坏形只有一个读者。
|
|
25
|
+
**谁受伤**:server `parseHooksConfig`(`HooksConfig.safeParse`)对 ①② 从受理变 400,400 句的 `message` 变成码形(`settings.hooks: Stop.0.hooks.0.command: entry-invalid`),
|
|
26
|
+
不再说「空串 / 类型不对」;断言 zod 句子原文的消费方测试。**补偿**:码 + 坐标 + 坏字段名点名坏在哪一块哪个字段;好配置的受理与读数逐字节不变。
|
|
27
|
+
**下游**:server 提货批按码铸 400 句(句子归消费方);cli / client-core 改读 `classifyHooksConfig`(不再各自判);web-admin 零读点。
|
|
28
|
+
|
|
29
|
+
**B2 · 八只 hooks zod 面改形**:`HooksConfig` / `HookMatcherEntry` / `HookEntry` / `CommandHookEntry` / `PromptHookEntry` / `AgentHookEntry` / `HttpHookEntry` / `McpToolHookEntry`
|
|
30
|
+
从 `ZodObject` / 判别联合 / 记录 schema 变成 `z.ZodType<T>`(transform 管道)。
|
|
31
|
+
**谁需要**:「条目合不合法」只留一个读者(分类器);保留结构化 schema 就是第二个判官。
|
|
32
|
+
**谁受伤**:用 `.shape` / `.extend` / `.pick` / `.options`,或把它们拼进 `z.discriminatedUnion(…)` / `z.object({ … })`、喂 `z.toJSONSchema(…)` 的消费方编译红或运行期抛
|
|
33
|
+
(普查 server / cli / client-core / web-admin / core / sdk / test:零处)。**补偿**:`safeParse` / `parse` / `z.infer` 照旧;型面由字段表派生,四种旧型与 12.3.0 编译期逐字同。
|
|
34
|
+
**下游**:无已知读点;提货时 tsc 红即通知。
|
|
35
|
+
|
|
36
|
+
**B3 · `ModelEntry.reasoning` / `vision` 去 `.default(false)`(三态)**(默认值变更;型面 `boolean` → `boolean | undefined`)—— 详见本节末小节。
|
|
37
|
+
**谁需要**:能力位的裁定读者(引擎座一只谓词)与 web-admin 表单的「未知」档。**谁受伤**:按 `boolean` 读这两键的消费方(tsc 红);把读出的 `false` 当「不支持」用的点,
|
|
38
|
+
缺席条目现在读到 `undefined`;server 若提货而不同拍退役 env 腿 `MODEL_REASONING` / `MODEL_VISION` 的 true 缺省,没写 `vision` 的条目会被当成支持图片。
|
|
39
|
+
**补偿**:存量显式 `false` 原样保留;缺席的读法由读者自己定。**下游**:server 同拍退役两处本地缺省、改读引擎谓词;web-admin 表单三态落库即生效;一致性语料 28 例,
|
|
40
|
+
server 适配器 release 模式提货前会差。
|
|
41
|
+
|
|
42
|
+
### 提货成本(词表尾插:不构成 major,下游动作照写)
|
|
43
|
+
|
|
44
|
+
**P1 · hook 条目 `type` 尾插第 5 种 `mcp_tool`**(`HOOK_ENTRY_TYPES`;`HookEntry` 联合加宽)。**谁需要**:照 CC 2.1.296 写了 `mcp_tool` 条目的设置不再整份被拒。
|
|
45
|
+
**谁受伤**:持穷举 `switch` 的消费方编译红;执行方 —— server hook-runner 今天对不认识的 type 只记运维日志 `hook_entries_skipped` 并跳过,提货后**守卫事件里的 `mcp_tool`
|
|
46
|
+
条目从「提交被拒(400)」变成「受理但不跑」**(守卫无声失效;它的 switch 吃 `RunnableHookEntry`,不一定编译红)。**补偿 / 要求**:提货的执行方须在受理面拒它或真跑它,不许只记日志。
|
|
47
|
+
|
|
48
|
+
**P2 · `SafetyMergeCategory` 尾插 `httpHookAllowlists`**。**谁需要**:两张 http hook 名单的合并律与准入地板有一行。**谁受伤**:持 `Record<SafetyMergeCategory, …>` /
|
|
49
|
+
穷举 `switch` 的消费方(壳 / client-core / web-admin)编译红。**补偿**:加一行即可;1.1.0 各行逐字节不变、在表头按 1.1.0 序,新类目只许尾插(冻结钉改述成这条律)。
|
|
50
|
+
|
|
51
|
+
### hooks 坏形只有一个读者:`classifyHooksConfig(settingsDoc)`
|
|
52
|
+
|
|
53
|
+
此前「这份设置文档里的 hooks 能不能装、哪几块要剔」包里没有口:只有 zod `HooksConfig`(闭集记录,任何一处坏 ⇒ 整份拒),壳、桌面、client-core 各自判。
|
|
54
|
+
现在一只纯函数,入参是**整份设置文档**(守卫可能写在 `hooks` 之外),答三样:结局(`loaded` / `loaded-partial` / `rejected`)、剔掉的块(`dropped`)、
|
|
55
|
+
拒的理由(`rejections`),外加装上的那一份(`hooks`:剔掉坏块、条目只带契约字段)。每块带 `ConfigPath` 段坐标(原样键名 —— 出门前过 `outgoingPath`)与码;
|
|
56
|
+
条目 / 匹配器的坏块另带坏字段名 `field`;零值回显、零句子(句子归消费方)。
|
|
57
|
+
|
|
58
|
+
粒度照 CC 2.1.296(四级:`hooks` 键 / 事件 / 匹配器 / 条目):
|
|
59
|
+
- **非守卫事件**里的坏块逐个剔(`hooks-not-object` / `unknown-event` / `event-not-array` / `matcher-invalid` / `entry-invalid`),同文件其余照装 —— `permissions.deny`、`env` 不再被一条坏 hook 连坐。
|
|
60
|
+
- **守卫事件**(`PreToolUse` / `PermissionRequest`)任何坏处 ⇒ 整份不装(`guard-matcher-invalid` / `guard-entry-invalid` / `guard-event-not-array`);守卫事件的值是 `null` ⇒ 剔(不是拒)。
|
|
61
|
+
- **守卫迹象**(以守卫事件名为键、值非空的对象成员,或不在合法位置上的匹配器形对象;字串值不算)出现在 `hooks` 之外、未知事件名下、非数组的事件值里、
|
|
62
|
+
匹配器或条目的字段里(含契约不认识、本会被剥掉的字段)⇒ 整份不装(`guard-outside-hooks` / `guard-under-unknown-event` / …);`hooks` 是装对象 / 数组的数组、
|
|
63
|
+
一只匹配器或一只条目 ⇒ `hooks-is-matcher`。迹象扫**整棵子树**(CC 只看 3 层)—— 比 CC 严的七处(H1–H7)登在 `docs/CC-DIVERGENCE.md`。
|
|
64
|
+
- 分类器**自含**:函数体与它用到的同模块私有件只引用 `HOOK_EVENTS` 与 JS 内建(零 zod),可被消费方整函数抄走(client-core 生成器的前提;门格 + 对 `dist` 实跑生成器两只判官)。
|
|
65
|
+
|
|
66
|
+
**zod 面改读投影**(一个问题一个读者):`HooksConfig.safeParse(v)` 受理 ⇔ `classifyHooksConfig({ hooks: v })` 为 `loaded`,`data` = 它装上的那一份;
|
|
67
|
+
`HookMatcherEntry` / `HookEntry` / `CommandHookEntry` … 同法(把那一块放进 `Stop` 事件下判)。条目字段表只有一张(运行期分类器读、条目类型由它派生),此前 zod 条目 schema 那份规则不再另存。
|
|
68
|
+
差分门(冻结 12.3.0 定义对新面,>500 条语料)量出的差只有四类:① `mcp_tool` 条目受理;② 本会被剥掉的未知字段里藏着守卫迹象 ⇒ 拒;
|
|
69
|
+
③ JSON 里写出来的 `__proto__` 事件键 ⇒ 不再被跳过(未知事件:剔 / 装着守卫:拒);④ http `headers` 里字面叫 `__proto__` 的键留作自有键(此前被记录型赋值丢掉)。
|
|
70
|
+
|
|
71
|
+
**硬破坏(类型面 / schema 形)**:`HooksConfig` / `HookMatcherEntry` / `HookEntry` / `CommandHookEntry` / `PromptHookEntry` / `AgentHookEntry` / `HttpHookEntry` /
|
|
72
|
+
`McpToolHookEntry` 的值从 `ZodObject` / 判别联合 / 记录 schema 变成 `z.ZodType<T>`(transform 管道):`.shape` / `.extend` / `.pick` / `.options` 没有了,
|
|
73
|
+
拿它们拼 `z.discriminatedUnion(…)` / `z.object({ … })` 的组合与 `z.toJSONSchema(…)` 会抛;`safeParse` / `parse` / `z.infer` 照旧。不保留结构化 schema:
|
|
74
|
+
那等于再留一个「条目合不合法」的读者。消费方普查(server / cli / client-core / web-admin / core / sdk / test 各仓 grep):零处用这几只的 schema 形或拿它们生成 JSON Schema。
|
|
75
|
+
|
|
76
|
+
**hook 条目 `type` 五种**:加 `mcp_tool`(`server` / `tool` / `input?` + 通用四字段)。此前守卫事件里写一条 `mcp_tool` ⇒ 整份设置不装。
|
|
77
|
+
上游漂移门加 ①b:`HOOK_ENTRY_TYPES` 对拍锚定快照里机器抽出的 type 闭集(快照按 CC 2.1.296 重抽;事件 33 员与 2.1.291 逐字同)。
|
|
78
|
+
|
|
79
|
+
三问 —— **谁需要**:读本地设置文件的宿主(壳 / 桌面)与收 `settings.hooks` 的服务端:一条坏 hook 不再让同文件的拒读规则失效,守卫坏形照拦;
|
|
80
|
+
**谁受伤**:① 宿主改读分类器后,非守卫事件里一只坏匹配器 / 坏条目从「整份不装」变成「只剔那一块」(放宽到 CC 粒度);合形非守卫事件的匹配器 / 条目未知字段里藏守卫迹象
|
|
81
|
+
从「剥掉照装」变成「整份不装」(收紧);② 服务端 `parseHooksConfig`(`HooksConfig.safeParse`)对上面 ②③ 两类坏形从受理变 400,400 句的 `message` 从 zod 句子变成码
|
|
82
|
+
(`settings.hooks: Stop.0.hooks.0.command: entry-invalid`);③ 收 `mcp_tool` 条目的执行方(服务端 hook-runner、壳执行器):这一型此前到不了它们手里,
|
|
83
|
+
现在过得了 wire 面 —— 服务端 hook-runner 今天对不认识的 type 只记一条运维日志 `hook_entries_skipped` 并跳过,于是提货后**守卫事件里的 `mcp_tool` 条目从「提交被拒(400)」变成「受理但不跑」**;
|
|
84
|
+
提货的执行方须在受理面拒它或真跑它,不许只记日志;④ 用这八只 zod 面的 schema 形(组合 / 扩展 / 生成 JSON Schema)的消费方编译红或运行期抛(普查零处);**补偿**:码 + 坐标点名坏在哪一块哪个字段;守卫类坏形仍整份拒(放宽只在非守卫事件)。
|
|
85
|
+
钉:`test/hooks-classify-13.0.0.test.ts`(剔 5 码 / 拒 6 码各一格 · codex 两条限定 · 深于 3 层 · 差分门 · 自含)· `test/upstream-drift.test.ts` ①b。
|
|
86
|
+
|
|
87
|
+
### 设置源表 + 层准入一只函数:`layerAdmission`;本地层与项目层同档
|
|
88
|
+
|
|
89
|
+
`SETTINGS_SOURCES`(声明序 = 合并序 user < project < local < flag < policy)、`SETTINGS_SOURCE_CONTRACT`(每层的信任档与是否仓库可控)、
|
|
90
|
+
`WORKSPACE_TRUST_STATES`(`accepted` / `declined` / `no_trust_step`;宿主读口抛或闭集外按 `declined` 交)、
|
|
91
|
+
`layerAdmission(source, workspace, category, member?, value?)` → `admitted` / `trust_withheld` / `below_trust_floor`。律一条:
|
|
92
|
+
层档先过地板(`isAtLeast(档, 地板)`,不过 ⇒ `below_trust_floor`,受信也进不来);仓库可控层(`projectSettings` / `localSettings`)在读数不是 `accepted` 时
|
|
93
|
+
只收 `direction: "tighten"` 的成员,其余 `trust_withheld`。不给 `SAFETY_MERGE_SPEC` 加列(`direction` 已经答了「未受信时哪些还能进」)。
|
|
94
|
+
`localSettings` 取 `project` 档(CC 2.1.296:project / local 同为「仓库可控」;本地文件被 gitignore、克隆带不进来)—— 在源表上改,
|
|
95
|
+
`hooks` / `env` / `mcpServers` / `rulesInstructions` 四行 `minTrust: "project"` 与 `trustRank` 数值一字不动;`flagSettings` 取 `global` 档(启动时交入的设置 = 启动者自己的动作,与 CC 运维档同)。
|
|
96
|
+
hooks 执行门那句契约(`declined` ⇒ 所有层的 hooks 都不跑;`no_trust_step` 只在这一门与 `declined` 不同)写进 `./hooks` 头注,执行在 client-core 一处,不在本包。
|
|
97
|
+
|
|
98
|
+
三问 —— **谁需要**:每个设置解析器(壳 resolver、client-core 装配入口)—— 层档 / 仓库可控 / 未受信律此前各宿主一张表;
|
|
99
|
+
**谁受伤**:本地层(`settings.local.json`)的 hooks / env / mcpServers / rulesInstructions 在读上游表的宿主里开始准入 —— 个人本地设置里的 MCP 服务器与规则开始生效;
|
|
100
|
+
**补偿**:未受信工作区里本地层与项目层同样 `trust_withheld`;本地层 `permissions.allow` 仍不准入(地板 `global`,不在本件)。
|
|
101
|
+
下游:cli resolver 那句「settings rejected key 'hooks' from local-trust」随改读本表消失;client-core 的 AS-4(「本地层 hooks 不再生效」)可撤;
|
|
102
|
+
test [10504] 本地层格翻成与 CC 同形。
|
|
103
|
+
钉:`test/settings-sources-13.0.0.test.ts`。
|
|
104
|
+
|
|
105
|
+
### URL 名单一条模式的判法:一条律、两只出口(`src/url-pattern.ts`)
|
|
106
|
+
|
|
107
|
+
管理员写的 URL 名单(http hook `allowedHttpHookUrls`;MCP `allowedMcpServers` / `deniedMcpServers` 的 `serverUrl` 条目)只读这一只判官。律:**名单读不准的地方一律判向「拦」**——
|
|
108
|
+
`urlAllowPatternMatches(url, pattern)` 命中面 ⊆ CC 2.1.296 `g9`,`urlDenyPatternMatches(url, pattern)` 命中面 ⊇ `g9`。组件判法与上游同形(协议同或整段 `*`、主机名内 glob、
|
|
109
|
+
端口、路径 + 查询串 glob;`*` 不跨主机边界)。放行出口补上游四洞:写明的缺省端口照判(`https://*.x:443/*` 不再放行 :8443)、`*` 协议只通配 http / https / ws / wss
|
|
110
|
+
(`ws+unix:` 套接字段只认逐字,空 / 含 `..` 不放)、解析不出 URL 形的模式不放行、`%2a` / 全角 `*` 解码出的字面 `*` 不当通配;拒绝出口另按整串 glob 判一次,既有写法不失效。
|
|
111
|
+
偏离逐条登 `docs/CC-DIVERGENCE.md`(SS-CCD-01 … 05)。占位记号按输入确定选取(纯函数,全局只用 `URL`,零随机)。
|
|
112
|
+
**谁需要**:壳(cli 现有一份同形叶子,退役条件 = 本包判法 ⊇ 它的放行收紧,语料逐格同答)与任何要判这几张名单的宿主。**谁受伤**:放行名单里依赖上游宽读法的写法
|
|
113
|
+
(无协议写法 `*.corp.example`、端口位部分通配、主机名 `%2a`)从「能放」变「不放」。**补偿**:改写成能解析的 URL 形即放(`https://*.corp.example/*`)。
|
|
114
|
+
|
|
115
|
+
### 新类目 `httpHookAllowlists`:两张 http hook 名单跨层取交、只认准入层(`src/http-hook-allowlists.ts`)
|
|
116
|
+
|
|
117
|
+
`SAFETY_MERGE_SPEC.httpHookAllowlists = { mergeShape: "denyFirst", minTrust: "global", tighten: { rule: "setNarrower" }, enforcement: "resolver", fail: "closed" }`(尾插)。
|
|
118
|
+
层 = `{ source: SettingsSource, 两张名单? }`(只带源名);读法 `readHttpHookAllowlistLayer(source, settings)`(坏形名单读成 `[]` 并点名坏键 —— CC 同向「no HTTP hooks may run」);
|
|
119
|
+
判决 `httpHookUrlVerdict(url, layers, workspace)` → `undefined` 或 `HttpHookUrlBlock{ list, rule: "empty" | "url", sources }`(零 URL 回显,判官出结构不出句);
|
|
120
|
+
`httpHookEnvVarsAllowed(hookVars, layers, workspace)` = hook 自己的 `allowedEnvVars` 与每张准入名单取交。准入 ⇔ `layerAdmission(源, 工作区读数, "httpHookAllowlists") === "admitted"`
|
|
121
|
+
(见下「合流收口」)。片段形门 `HttpHookAllowlistSettings`。与 CC 两处差(SS-CCD-06 / 07):CC 各层**拼接** ⇒ 本包**取交**(下层不能往托管名单里加 URL);
|
|
122
|
+
CC 任意层可设 ⇒ 本包只认准入层(地板 global:用户 / flag / 托管;仓库可控层的一个 `[]` 会让用户自己的 http 守卫 hook 不发出)。
|
|
123
|
+
**谁需要**:托管管理员(名单不再能被下层绕过)、壳的 http hook 执行器与请求体出门筛、server 引擎属事件 hook 的变量名单(同一只展开法的变量来源)。
|
|
124
|
+
**谁受伤**:靠用户层名单**扩**托管名单的部署(取交后不扩);在项目 / 本地层写名单期望生效的仓库(不再进判决)。**补偿**:把名单写进用户层或托管层;判决的 `sources` 点名是哪一层拦的。
|
|
125
|
+
**提货成本**:`SafetyMergeCategory` 加宽 = 上文 P2。
|
|
126
|
+
|
|
127
|
+
### MCP 名单判决 `mcpServerPolicyVerdict`(`src/mcp-server-policy.ts`)
|
|
128
|
+
|
|
129
|
+
`mcpServerPolicyVerdict(server, layers)` → `undefined` 或 `McpPolicyBlock{ name, list, rule, target, written, sources }`(闭集 `MCP_SERVER_LIST_KEYS` / `MCP_POLICY_RULES`):
|
|
130
|
+
拒绝名单绝对优先、各层都算(名字 → 命令 → URL 拒绝出口);允许名单各层拼接(CC 形),托管层(源表档 `managed` 的源,层只带源名)`allowManagedMcpServersOnly: true` ⇒ 只读托管层;没有一层写 = 不限、空 = 一台都不许;
|
|
131
|
+
stdio 遇命令条目须命中其一、远端遇 URL 条目须命中其一(放行出口),否则按名字。**目标零展开**:判按宿主展开后的连接目标(`server.target`,不回显),回显只按展开前写法
|
|
132
|
+
(`server.written`;stdio 只给可执行名与参数个数)。壳 / server / web-admin 只渲这份结构,不各自造句。
|
|
133
|
+
**server 读不读**:server 今天不读 `allowedMcpServers` / `deniedMcpServers`(它们是壳 / CC 的设置层键,server 的 MCP 装配不经过它们);将来 server 受理面若要给被拦条目同一句,
|
|
134
|
+
按这只判官读,不另长读法。本版不改 server。
|
|
135
|
+
|
|
136
|
+
### 界面语言设置片段(`src/ui-language.ts`)
|
|
137
|
+
|
|
138
|
+
`UI_LANGUAGE_SETTING = { key: "semaUiLanguage", values: ["en", "zh"], category: "ui", source: "userSettings" }`(键沿用终端已写的,已存值零迁移)· 形门 `UiLanguageSetting` /
|
|
139
|
+
片段 `UiLanguageSettings` · 读器 `readUiLanguage(raw)` → `SettingLayerRead`:合法 ⇒ 值;缺席 / `null` ⇒ 未设;词表外 ⇒ `{ ok: false }`。两种「无值」消费方都落到宿主 locale;
|
|
140
|
+
读器不猜(不把 `zh-CN` 折成 `zh`)。界面语言 ≠ 模型回答的语言(CC `language` 键),两件事不共用一个键。
|
|
141
|
+
|
|
142
|
+
### 注释改真
|
|
143
|
+
|
|
144
|
+
- `HostEntry.approved`:「既有 worker 不受影响(reconciler 仍按具体 host 认领)」在中心 host 出现后不再成立;改为:批准只管自动排布,`placement.auto` 判 `host` 是钉还是提示。
|
|
145
|
+
- 「目录的缺省模型是哪一条」仍只有 `resolveCatalogDefaultModel` 一只(11.0.0 起;server 与壳的两份手写已删、两端改调本口);本版加一格对拍:冻结两份手写的最后原文,
|
|
146
|
+
在 11.0.0 之后的输入空间里 18 个输入三方逐输入零差异。端点缺省地址与 provider 车道推断不进本口(它们是引擎装配的运行期事实,不是目录格式),路由键归引擎。
|
|
147
|
+
|
|
148
|
+
### 合流收口:层档只有源表一个读者 · 分类器抄本注入 `HOOK_EVENTS`
|
|
149
|
+
|
|
150
|
+
两片并行时各长了一个读者,合流时收成一条律:**本包任何函数要「这一层是几档」都经 `settingsSourceContract(源)` 查 `SETTINGS_SOURCE_CONTRACT`,不收调用方给的档;层只带源名。**
|
|
151
|
+
- 此前 http hook 名单判官按层对象上调用方填的 `trust` 自己 `isAtLeast`,MCP 名单判决按层上 `trust === "managed"` 认托管层,而 `layerAdmission` 按源表判 ——
|
|
152
|
+
同一个问题两个读者:调用方把项目层填成 `global`,仓库里一个 `allowedHttpHookUrls: []` 就让用户自己的 http 守卫 hook 停发。
|
|
153
|
+
- 现在:新导出 `settingsSourceContract(source)`(源表一行;闭集外 / 原型链名 ⇒ RangeError,与 `layerAdmission` 同一句、同一只铸点);http hook 名单准入 ⇔
|
|
154
|
+
`layerAdmission(源, 工作区读数, "httpHookAllowlists") === "admitted"`(两只判官多一个 `workspace` 入参,与 `layerAdmission` 同词表);MCP 托管层 = 源表档 `managed` 的源;
|
|
155
|
+
`UI_LANGUAGE_SETTING.source` 受 `SettingsSource` 约束。今天这一类目的地板(global)在任何工作区读数下都把项目 / 本地层挡在外面,`workspace` 不改变读数;
|
|
156
|
+
它在签名上是因为准入问的就是这一只函数 —— 类目地板哪天下调,判官跟着表走,不另长读法。
|
|
157
|
+
- 对 12.3.0 这些都是新导出(两片未发版形之间的改动,不另计 BREAKING)。**谁需要**:每个设置解析器 / 宿主(层几档只问一处)。**谁受伤**:按片 B 未发版形接线的下游
|
|
158
|
+
(层对象带 `trust`、判官两参)提货时 tsc 红。**补偿**:删掉层上的 `trust`、`source` 用源表的词、判官补 `workspace`(宿主读口抛或闭集外按 `declined` 交)。
|
|
159
|
+
- 分类器自含的前提写进 `classifyHooksConfig` 函数头注与 llms:闭包里 JS 内建之外只有一个自由名 `HOOK_EVENTS`;整函数抄走的生成器(client-core)须把本包运行期导出
|
|
160
|
+
`HOOK_EVENTS`(上游常量)注入抄本作用域,不在抄本里贴字面事件表(那是第二张事件表,上游漂移门看不见)。本包不复制事件表。
|
|
161
|
+
钉:`test/http-hook-allowlists-13.0.0.test.ts`「准入只有一个读者」六格 · `test/mcp-server-policy-13.0.0.test.ts` 托管档四格 · `test/settings-sources-13.0.0.test.ts` ⑥。
|
|
162
|
+
|
|
163
|
+
### ⚠️ BREAKING(默认值变更):`ModelEntry.reasoning` / `vision` 去 `.default(false)`(三态)
|
|
164
|
+
|
|
165
|
+
> 档位:按本包「发版纪律」属**默认值变更** = major(同一份配置解析出不同结果;型面 `boolean` → `boolean | undefined`)。须与 server 侧消费同拍发:
|
|
166
|
+
> server env 腿 `MODEL_REASONING` / `MODEL_VISION` 的 true 缺省与中心腿两键回落要在同一拍退役,否则没写 `vision` 的条目会被当成支持图片。
|
|
167
|
+
|
|
168
|
+
同一事实「模型行没写 reasoning / vision 时算不算支持」此前三种读法(本包填 false、server env 腿缺省 true、server 中心腿两键各回落一种)。声明层改**三态**:`true` / `false` /
|
|
169
|
+
缺席 = 未声明,读者按自己的缺省(引擎座一只谓词读);本包不再替任何读者把「没写」读成「不支持」。型面 `reasoning?: boolean` / `vision?: boolean`。
|
|
170
|
+
一致性语料 28 例重录(差 = 每条没写这两键的条目少 `"reasoning": false` / `"vision": false`,别无他差)。
|
|
171
|
+
**谁需要**:声明层三态的裁定方与读者(引擎座的能力谓词;web-admin 表单的「未知」档,落库即生效)。**谁受伤**:按 `boolean` 读这两键的消费方(tsc 红 = 通知);把读出的
|
|
172
|
+
`false` 当「不支持」用的点,缺席条目现在读到 `undefined`。**补偿**:缺席的读法由读者自己定(server env 腿 / 中心腿的本地缺省同拍退役、改读引擎谓词);
|
|
173
|
+
存量显式 `false` 行本包原样保留、不自动改值。上下文窗口 `contextWindow` 未知时的保守回落与通告不在本包。
|
|
174
|
+
|
|
175
|
+
### 登记面订正
|
|
176
|
+
|
|
177
|
+
- 透明键表 `PARSE_TRANSPARENT_KEYS` 的 `mcp.servers[].toolAxes` 行属主从 `consumer` 改 `engine-ingest`,行文点名唯一判官 = 引擎根导出 `readMcpToolAxes`(12.2.0 写「归消费方」是当时事实;引擎 7.51.2 起消费方两腿都调它)。只改归属句与两份 llms / README 同句,**不加 zod**(再写一份就是第二只判官)。读数零变。
|
|
178
|
+
|
|
179
|
+
## 12.3.0 — 2026-10-12 — minor:域读策略两张闭集表(新导出 `DOMAIN_ENTRY_SALVAGE`)· 域读分文档面 / 视图面两函数(新导出 `parseDomainSalvaged`)· 抢救按 schema 递归到嵌套集合 · `projects` 起逐条抢救
|
|
180
|
+
|
|
181
|
+
> minor:域读策略拆成两张闭集表 —— 新导出 `DOMAIN_ENTRY_SALVAGE`(读时能否逐条丢坏条目,`"salvage" | "none"`),`DOMAIN_READ_FALLBACK` 名 / 值 / 义不变(只答「整域读不进」);
|
|
182
|
+
> 域读分两面两函数 —— 文档面 `parseDomainLoud`(读数与 12.2.x 逐字同,永不抢救)与新导出的视图面 `parseDomainSalvaged`(按表逐条抢救,递归到嵌套集合);`projects` 起逐条抢救。
|
|
183
|
+
> additive:零删、零改名;导出面新增两行(`DOMAIN_ENTRY_SALVAGE` / `parseDomainSalvaged`);好配置的读数逐字不变;写路径、写入席、`getDomain` / `exportBundle` 的读数逐字不变。
|
|
184
|
+
|
|
185
|
+
### 两张表各答一个问题:`DOMAIN_ENTRY_SALVAGE` 与 `DOMAIN_READ_FALLBACK`
|
|
186
|
+
|
|
187
|
+
此前「能否逐条丢一条坏条目」挂在 `DOMAIN_READ_FALLBACK` 的 `"default"` 档上 —— 与「整域读不进时能否退默认」被同一张表回答。`projects` 两件事的答案相反
|
|
188
|
+
(丢一条登记 = 那个项目认领被拒,fail-closed;整域退默认 = 身份台账蒸发,放权),于是只能整域抛:一条存量登记被后来收紧的 schema 拒,**整个 scope 的项目**一起停摆。
|
|
189
|
+
现在两张表:`DOMAIN_ENTRY_SALVAGE`(`as const satisfies Record<DomainName, "salvage" | "none">`,新域不表态 = 编译红,头注逐域理由)只管逐条丢;
|
|
190
|
+
`DOMAIN_READ_FALLBACK` 只管整域读不进之后默认化还是抛。逐域:`projects` = `salvage`(整域档位仍 `"throw"`);闸域 `rosters` / `workers` / `governance` / `entitlement` /
|
|
191
|
+
`execution` / `limits` = `none`(丢一条规则行 = 静默放权;`workers` 的逐行容错仍是 `readWorkersRows` 的扣留);其余目录 / 内容域 = `salvage`(与 12.2.x 同)。
|
|
192
|
+
|
|
193
|
+
### 两面两函数:文档面 `parseDomainLoud` 永不抢救,视图面 `parseDomainSalvaged` 按表抢救
|
|
194
|
+
|
|
195
|
+
文档面(`parseDomain` / `parseDomainLoud`:写入席、导出、`getDomain`)永不抢救;视图面(`parseDomainSalvaged` / `buildEffective`)按表抢救。
|
|
196
|
+
两个读函数共用**同一只内部体**(严 parse + 未知键两条告警),只差「整域读不进」那一臂:文档面抛原错(与 12.2.x 逐字同 —— `FileConfigStore.getDomain`、
|
|
197
|
+
`exportBundle`、`createSiblingResolver`、一致性门写入席 `strictWrite` 腿零改);视图面 `parseDomainSalvaged(domain, raw, onWarning?)` 按 `DOMAIN_ENTRY_SALVAGE`
|
|
198
|
+
走 `salvageEntries` → 丢了东西就拿压缩后的文档再 parse;过 ⇒ 每条被丢条目一条 `entry-dropped`,其余告警的坐标经 `rebaseWarningPaths` 回写成原文档坐标;救不活 ⇒
|
|
199
|
+
抛整域 parse 的原错、零告警。同一份**好**文档上两函数逐字同值、同告警。`buildEffective` 十六个域一处调视图面,整域读不进时只看 `DOMAIN_READ_FALLBACK`(此前 gate 域的行
|
|
200
|
+
与其余域的行各调一只函数 —— 同一张表的第二份手抄,删了)。管理面要显示「生效配置里这个域是什么」时读视图面;读存量、改、整份写回的「现状」读文档面
|
|
201
|
+
(经抢救读出再写回,被丢的条目就成了删除)。
|
|
202
|
+
|
|
203
|
+
### 抢救递归到嵌套集合
|
|
204
|
+
|
|
205
|
+
`salvageEntries`:集合里每一条,若它的 schema 是带集合字段的对象,先对它按**同一个函数**抢救,再拿抢救后的那一条判整条(从 schema 派生,没有任何域专用分支)。
|
|
206
|
+
体内丢的子条目以父坐标为前缀上账(`["projects", <id>, "contextItems", 1]`),按文档序;整条最终仍判不过 ⇒ 整条丢、体内的半路账作废,记账行的判决取原文的(拒句坐标是原文档的)。
|
|
207
|
+
零幸存者律在每一层成立(体内集合全坏 ⇒ 不压成空集合 —— 「空 = 不设限」的字段不会被抢救成全开)。
|
|
208
|
+
`EntryKeptIndex` 的键 = 被压缩数组的原文档全路径(`formatConfigPath` 出门形;顶层数组的全路径就是字段名,12.2.x 的表形与义不变);`rebaseWarningPaths` 逐段回写
|
|
209
|
+
每一层被压缩的数组(两层都压缩时两层各回写一次)。
|
|
210
|
+
|
|
211
|
+
目录 / 内容域因此也变:条目体内某个子条目坏了,此前整条丢,现在只丢那个子条目、整条留下。被递归够到的嵌套集合(逐个,`salvage` 档域里条目体内的全部集合字段):
|
|
212
|
+
|
|
213
|
+
| 域 | 嵌套集合 | 少一条的语义 |
|
|
214
|
+
|---|---|---|
|
|
215
|
+
| models | `models[].promptGuidance[]` | 少一条提示指引 |
|
|
216
|
+
| skills | `skills[].scenarios[]` · `skills[].rosters[]` | 适用范围收窄(两者「空 = 全部」,零幸存者律不压成空) |
|
|
217
|
+
| mcp | `servers[].allowTools[]` · `servers[].scenarios[]` · `servers[].rosters[]` | 暴露的工具 / 挂载范围收窄(三者「空 / 缺席 = 全部」,同上) |
|
|
218
|
+
| systems | `systems[].callsWorkers[]` | 少给一个 worker 下发调用凭据 |
|
|
219
|
+
| collab | `templates[].slots[]` → `slots[].members[]` · `slots[].tools[]` | slot / member 少一个:模板级判据(拓扑、重名)仍过时,这是「换了一个更小的模板在跑」而不是收权 —— **推断,无逐域钉**;`tools[]` 收窄 |
|
|
220
|
+
| hosts | `hosts[].labels[]` | 少一个调度标签:匹配 `placement.requires` 的机器变少 |
|
|
221
|
+
| prompts | `bindings[].declarations[]` | 少下发一条声明 |
|
|
222
|
+
| projects | `projects.<id>.gitRemotes[]` · `.defaultScopes[]` · `.contextItems[]` | 少一条 remote 映射 / 默认记忆 scope / 上下文条目 |
|
|
223
|
+
|
|
224
|
+
三问 —— **谁需要**:任何一次收紧持久化 schema 的版本(12.2.1 的 UNC 判法已让存量登记 `\\?\C:\…` 整 scope 读抛)读存量文档的一方 —— 服务端拿 effective、管理面列项目;
|
|
225
|
+
**谁受伤**:无 —— 好配置读数逐字不变;文档面(写入席、导出、`getDomain`)读数逐字不变;视图面此前整域抛 / 整条丢的文档现在读出更多(只丢坏的那一格并点名);
|
|
226
|
+
**补偿**:闸域显式 `none`(两张表都说不);文档面永不抢救;读改写面读文档面。
|
|
227
|
+
钉:`test/projects-12.3.0.test.ts`(两表闭集 · 12.2.1 存量形黑盒读数 · 视图面与 `buildEffective` 同读数 · 文档面 / `getDomain` / `exportBundle` 与 12.2.x 逐字同 ·
|
|
228
|
+
两函数好文档同值同告警 · 整域档位不变 · 闸域负控 · 写路径与写入席拒 · 递归坐标 / 位移表 / 每层零幸存者 / 判决取原文)·
|
|
229
|
+
`test/entry-salvage-1.11.test.ts`(按新表分组;workers / entitlement / projects 三格空转修成真档位格)· `test/domain-completeness.test.ts` ⑤ ·
|
|
230
|
+
`test/conformance-coverage.test.ts` ⑥ · 语料 `c76-projects-entry-salvage-nested`(读腿抢救 + 嵌套坐标回写 · 严写腿拒)。
|
|
231
|
+
|
|
9
232
|
## 12.2.1 — 2026-10-12 — patch:`isAbsoluteHostPath` 的 UNC 首段按主机名形判(字母数字起头),Windows 设备命名空间前缀 `\\.\` 与长路径前缀 `\\?\` 一律拒(11.3.1 / 12.1.1 只排除 `?` / `*`,`\\.\C:\…` 曾被当 UNC 受理)
|
|
10
233
|
|
|
11
234
|
- **行为修复(宿主路径形判,UNC 臂)**。三族律不变;UNC 首段 = 主机名形(`[A-Za-z0-9][A-Za-z0-9._-]*`),所以 `\\.\C:\x`、`\\.\pipe\x`、`\\?\C:\x`、`\\*\share`、`\\-srv\share` 都不绝对;`\\srv\share\…` / `\\10.0.0.5\share` 照旧真。posix / 盘符两族逐字不变。
|
package/README.md
CHANGED
|
@@ -267,8 +267,9 @@ therefore shows only `zod`. Node built-ins only (`node:crypto`, `node:fs`).
|
|
|
267
267
|
`allow` (loosen @ `global`) / `deny` / `ask` (tighten @ `local`), a closed set; read it via `membersOf` /
|
|
268
268
|
`memberMinTrust` / `memberAdmission` (never a hardcoded allow/deny/ask table). The category-level `minTrust`
|
|
269
269
|
stays the default floor, so consumers that predate `members` behave exactly as before. This package publishes
|
|
270
|
-
the contract
|
|
271
|
-
step —
|
|
270
|
+
the contract and the pure per-layer reading of it (`layerAdmission`, next bullet); it performs no "degrade a
|
|
271
|
+
below-floor allow to a pending suggestion" step — that lives in the consumers (engine import door, shell resolver),
|
|
272
|
+
each on its own release schedule.
|
|
272
273
|
1.2.0 adds the **trust ordering primitives**: `trustRank(layer)` (v2-design §1 verbatim, `managed 6 > global 5 >
|
|
273
274
|
project 4 > local 3 > session 2 > task 1`) and `isAtLeast(layer, minTrust)` — the ladder every resolver is to
|
|
274
275
|
compare floors against; consumers retire their own rank tables onto it. **3.0.1 correction**: this used to say
|
|
@@ -282,6 +283,16 @@ therefore shows only `zod`. Node built-ins only (`node:crypto`, `node:fs`).
|
|
|
282
283
|
use `task`; the widened vocabulary is visible to consumers that hold a `Record<MinTrust, …>` / exhaustive
|
|
283
284
|
switch (compile error on upgrade — migrate to `trustRank`) or that validate external spec values with these
|
|
284
285
|
schemas (they now accept `task` and must rank it — again `trustRank`, never a five-word table of their own).
|
|
286
|
+
- **Settings sources + layer admission** (`settings-sources.ts`, main barrel): `SETTINGS_SOURCES` (declaration order =
|
|
287
|
+
merge order: user < project < local < flag < policy), `SETTINGS_SOURCE_CONTRACT` (each source's trust tier and whether a
|
|
288
|
+
repository controls it — `projectSettings` / `localSettings` are repository-controllable and share the `project` tier, as in
|
|
289
|
+
CC; `flagSettings` is `global` like `userSettings`; `policySettings` is `managed`), `WORKSPACE_TRUST_STATES`
|
|
290
|
+
(`accepted` / `declined` / `no_trust_step`) and `layerAdmission(source, workspace, category, member?, value?)` →
|
|
291
|
+
`admitted` / `trust_withheld` / `below_trust_floor`: the source's tier must reach the floor first; a repository-controllable
|
|
292
|
+
source in a workspace that is not `accepted` then admits only `direction: "tighten"` members. `settingsSourceContract(source)`
|
|
293
|
+
is the one lookup of the table (unknown source ⇒ RangeError): every function in this package that needs a layer's tier reads it
|
|
294
|
+
there and none takes a tier from its caller — a layer is named by its source only. The hooks execution gate
|
|
295
|
+
(`declined` ⇒ no hook from any layer runs) is contract text in `./hooks`, not layer admission.
|
|
285
296
|
- **Auth wire contract** (`api/auth.ts`, subpath `./api/auth`): the `/api/v1/auth/*` face — RFC 8628
|
|
286
297
|
device flow (code / token poll / approve consent) + rotating refresh + logout, the OAuth error envelope,
|
|
287
298
|
and the pure client helpers `normalizeUserCode` / `nextPollInterval`. Shipped M1 shapes frozen.
|
|
@@ -371,8 +382,15 @@ therefore shows only `zod`. Node built-ins only (`node:crypto`, `node:fs`).
|
|
|
371
382
|
primitive). **2.0.0** adds per-ENTRY
|
|
372
383
|
tolerance on the same read path: one malformed catalog entry is dropped on its own (named through
|
|
373
384
|
`onWarning` as `entry-dropped`) and its siblings survive, instead of the whole domain falling to
|
|
374
|
-
its schema default.
|
|
375
|
-
|
|
385
|
+
its schema default. **12.3.0**: where this applies is its OWN closed table, `DOMAIN_ENTRY_SALVAGE`
|
|
386
|
+
(`"salvage" | "none"`; until 12.2.x it rode on `DOMAIN_READ_FALLBACK`'s `"default"` tier, which now answers only
|
|
387
|
+
"the whole domain is unreadable — default or throw?") — gate domains (rosters / workers / governance / entitlement /
|
|
388
|
+
execution / limits) never drop a single entry, `projects` does (a missing registration = that project's claim is
|
|
389
|
+
refused; the domain stays `"throw"` when unreadable as a whole). Domain reading has two faces with two functions
|
|
390
|
+
sharing ONE body (strict parse + the unknown-key warnings): the DOCUMENT face (`parseDomain` / `parseDomainLoud` — the
|
|
391
|
+
write seat, export, `getDomain`) never salvages and reads exactly as 12.2.x; the VIEW face (`parseDomainSalvaged`, which
|
|
392
|
+
`buildEffective` calls for every domain) salvages per the table, recursing into a surviving entry's own collections
|
|
393
|
+
(coordinates carry the parent prefix, the zero-survivor law holds at every level). **S-712** (additive) lets each `entry-dropped` carry an
|
|
376
394
|
optional `identity?: { name?, id?, enabled? }` read from the dropped entry's OWN text (`DroppedEntryIdentity`):
|
|
377
395
|
a string `name` / `id` and a boolean `enabled`, own data properties only, each key present only when it
|
|
378
396
|
reads with that exact type and `isDisclosableIdentity` says it may ride out (not guessed, not coerced, not
|
|
@@ -410,9 +428,26 @@ therefore shows only `zod`. Node built-ins only (`node:crypto`, `node:fs`).
|
|
|
410
428
|
2.0.0, the model-switch pair `PreModelSwitch` / `PostModelSwitch`), the single-owner map
|
|
411
429
|
`HOOK_EVENT_OWNER` (engine | shell), the matcher-field table, a per-event input schema (`HookInput`),
|
|
412
430
|
the output/decision shapes (`SyncHookOutput` / `HookSpecificOutput` / `HookPermissionRequestDecision`),
|
|
413
|
-
|
|
431
|
+
the config surface (defined in `hooks-config.ts`, re-exported by `./hooks`): `HOOK_ENTRY_TYPES` (CC 2.1.296's five: command / prompt / agent / http /
|
|
432
|
+
`mcp_tool`) and the ONE classifier `classifyHooksConfig(settingsDoc)` — which pieces of a settings document's `hooks` drop
|
|
433
|
+
(`HOOKS_DROPPED_PIECE_CODES`), whether the whole document is rejected because a guard (`PreToolUse` / `PermissionRequest`) may be
|
|
434
|
+
in a bad piece (`HOOKS_REJECTION_CODES`), and what loads; codes + `ConfigPath` coordinates, no sentences, self-contained (no zod;
|
|
435
|
+
its one free name besides JS built-ins is `HOOK_EVENTS` — a generator that copies the function must inject this package's runtime
|
|
436
|
+
`HOOK_EVENTS` into the copy, never paste a literal event list).
|
|
437
|
+
`HooksConfig` / `HookMatcherEntry` / `HookEntry` (the `settings.json` `hooks` shape — event names a CLOSED set) are its zod
|
|
438
|
+
projections (accepted ⇔ it loads all of it; the parsed value is what loaded),
|
|
414
439
|
stop attribution (`StoppedBy` / `stopAttributionText`), and the one reading of `$VAR` / `${VAR}` in an `http` hook's header values
|
|
415
440
|
(`interpolateHookEnvVars` — allow-listed names expand, everything else is blanked and reported, credential variables are never released, CR / LF / NUL stripped).
|
|
441
|
+
- **URL-list pattern judge** (`url-pattern.ts`, 13.0.0): the ONE way an administrator's URL-list pattern is matched —
|
|
442
|
+
`urlAllowPatternMatches` (⊆ CC `g9`, four upstream holes closed) / `urlDenyPatternMatches` (⊇ `g9` ∪ whole-string glob);
|
|
443
|
+
divergences in `docs/CC-DIVERGENCE.md`.
|
|
444
|
+
- **HTTP hook allowlists** (`http-hook-allowlists.ts`, 13.0.0): category `SAFETY_MERGE_SPEC.httpHookAllowlists`; `readHttpHookAllowlistLayer(source, settings)`,
|
|
445
|
+
`httpHookUrlVerdict(url, layers, workspace)` (every admitted layer's list must pass — layers intersect) and `httpHookEnvVarsAllowed(hookVars, layers, workspace)`;
|
|
446
|
+
a layer is admitted ⇔ `layerAdmission(source, workspace, "httpHookAllowlists") === "admitted"` (user / flag / managed; project / local are below the floor).
|
|
447
|
+
- **MCP server list verdict** (`mcp-server-policy.ts`, 13.0.0): `mcpServerPolicyVerdict` → `McpPolicyBlock{name, list, rule, target,
|
|
448
|
+
written, sources}` — judged on the expanded target, echoed only as written; the managed layer (whose `allowManagedMcpServersOnly` counts)
|
|
449
|
+
is the source whose tier in `SETTINGS_SOURCE_CONTRACT` is `managed`.
|
|
450
|
+
- **UI language** (`ui-language.ts`, 13.0.0): `semaUiLanguage` (`en` / `zh`, category `ui`, user settings) + `readUiLanguage`.
|
|
416
451
|
- **Cross-session settings** (`cross-session.ts`): the two `settings.json` keys `crossSessionInbound`
|
|
417
452
|
(wake/next-turn/hold/refuse — the core 7.30.0 vocabulary, `accept` retired in 6.0.0; `default` = unset) and `dialogExpiry` (60s/5m/10m/never), each with a reader that
|
|
418
453
|
answers `ok:false` on a bad value instead of silently folding to the default.
|
|
@@ -482,7 +517,7 @@ therefore shows only `zod`. Node built-ins only (`node:crypto`, `node:fs`).
|
|
|
482
517
|
carries verbatim WITHOUT checking their shape, each row naming who does check it (the engine's ingest side or
|
|
483
518
|
a consumer's enforcement point). Today: `models[].compat` (1.10.0), `models[].headers` (6.4.0; the header-name
|
|
484
519
|
allowlist × lane is sema-server's, not restated here), `mcp.servers[].source` (1.7.2), `mcp.servers[].toolFaces`
|
|
485
|
-
(1.9.0), `mcp.servers[].toolAxes` / `authForm` / `entryKind` (12.2.0; connector-entry declarations, semantics are the consumer's),
|
|
520
|
+
(1.9.0), `mcp.servers[].toolAxes` / `authForm` / `entryKind` (12.2.0; connector-entry declarations — `toolAxes` has exactly one shape judge, the engine's root export `readMcpToolAxes`; the other two keys' semantics are the consumer's),
|
|
486
521
|
and an entitlement override's `value`. `models[].extraBody` is NOT one of them — it has its own shape
|
|
487
522
|
gate (a plain JSON object); what it leaves open is the key vocabulary inside. `compat` / `headers` / `extraBody`
|
|
488
523
|
still clear the one free-form safety judgment (secret-shaped key/value, accessor, cycle, non-JSON, too deep ⇒ rejected).
|
package/conformance/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
13.0.0
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
"name": "m0",
|
|
39
39
|
"provider": "openai",
|
|
40
40
|
"quotaWeight": 1,
|
|
41
|
-
"
|
|
42
|
-
"tier": "standard",
|
|
43
|
-
"vision": false
|
|
41
|
+
"tier": "standard"
|
|
44
42
|
},
|
|
45
43
|
{
|
|
46
44
|
"api": "openai-completions",
|
|
@@ -50,9 +48,7 @@
|
|
|
50
48
|
"name": "m1",
|
|
51
49
|
"provider": "openai",
|
|
52
50
|
"quotaWeight": 1,
|
|
53
|
-
"
|
|
54
|
-
"tier": "standard",
|
|
55
|
-
"vision": false
|
|
51
|
+
"tier": "standard"
|
|
56
52
|
}
|
|
57
53
|
],
|
|
58
54
|
"roles": {},
|
|
@@ -120,9 +116,7 @@
|
|
|
120
116
|
"name": "m0",
|
|
121
117
|
"provider": "openai",
|
|
122
118
|
"quotaWeight": 1,
|
|
123
|
-
"
|
|
124
|
-
"tier": "standard",
|
|
125
|
-
"vision": false
|
|
119
|
+
"tier": "standard"
|
|
126
120
|
},
|
|
127
121
|
{
|
|
128
122
|
"api": "openai-completions",
|
|
@@ -132,9 +126,7 @@
|
|
|
132
126
|
"name": "m1",
|
|
133
127
|
"provider": "openai",
|
|
134
128
|
"quotaWeight": 1,
|
|
135
|
-
"
|
|
136
|
-
"tier": "standard",
|
|
137
|
-
"vision": false
|
|
129
|
+
"tier": "standard"
|
|
138
130
|
}
|
|
139
131
|
],
|
|
140
132
|
"roles": {},
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
"name": "keep-a",
|
|
39
39
|
"provider": "openai",
|
|
40
40
|
"quotaWeight": 1,
|
|
41
|
-
"
|
|
42
|
-
"tier": "standard",
|
|
43
|
-
"vision": false
|
|
41
|
+
"tier": "standard"
|
|
44
42
|
},
|
|
45
43
|
{
|
|
46
44
|
"api": "openai-completions",
|
|
@@ -50,9 +48,7 @@
|
|
|
50
48
|
"name": "keep-b",
|
|
51
49
|
"provider": "openai",
|
|
52
50
|
"quotaWeight": 1,
|
|
53
|
-
"
|
|
54
|
-
"tier": "standard",
|
|
55
|
-
"vision": false
|
|
51
|
+
"tier": "standard"
|
|
56
52
|
}
|
|
57
53
|
],
|
|
58
54
|
"roles": {},
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
"name": "m0",
|
|
39
39
|
"provider": "openai",
|
|
40
40
|
"quotaWeight": 1,
|
|
41
|
-
"
|
|
42
|
-
"tier": "standard",
|
|
43
|
-
"vision": false
|
|
41
|
+
"tier": "standard"
|
|
44
42
|
}
|
|
45
43
|
],
|
|
46
44
|
"roles": {},
|
|
@@ -108,9 +106,7 @@
|
|
|
108
106
|
"name": "m0",
|
|
109
107
|
"provider": "openai",
|
|
110
108
|
"quotaWeight": 1,
|
|
111
|
-
"
|
|
112
|
-
"tier": "standard",
|
|
113
|
-
"vision": false
|
|
109
|
+
"tier": "standard"
|
|
114
110
|
}
|
|
115
111
|
],
|
|
116
112
|
"roles": {},
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
"name": "m0",
|
|
39
39
|
"provider": "openai",
|
|
40
40
|
"quotaWeight": 1,
|
|
41
|
-
"
|
|
42
|
-
"tier": "standard",
|
|
43
|
-
"vision": false
|
|
41
|
+
"tier": "standard"
|
|
44
42
|
}
|
|
45
43
|
],
|
|
46
44
|
"roles": {
|
|
@@ -97,9 +95,7 @@
|
|
|
97
95
|
"name": "m0",
|
|
98
96
|
"provider": "openai",
|
|
99
97
|
"quotaWeight": 1,
|
|
100
|
-
"
|
|
101
|
-
"tier": "standard",
|
|
102
|
-
"vision": false
|
|
98
|
+
"tier": "standard"
|
|
103
99
|
}
|
|
104
100
|
],
|
|
105
101
|
"roles": {
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
"name": "v-a",
|
|
39
39
|
"provider": "openai",
|
|
40
40
|
"quotaWeight": 1,
|
|
41
|
-
"
|
|
42
|
-
"tier": "standard",
|
|
43
|
-
"vision": false
|
|
41
|
+
"tier": "standard"
|
|
44
42
|
}
|
|
45
43
|
],
|
|
46
44
|
"roles": {},
|
|
@@ -93,9 +91,7 @@
|
|
|
93
91
|
"name": "v-a",
|
|
94
92
|
"provider": "openai",
|
|
95
93
|
"quotaWeight": 1,
|
|
96
|
-
"
|
|
97
|
-
"tier": "standard",
|
|
98
|
-
"vision": false
|
|
94
|
+
"tier": "standard"
|
|
99
95
|
}
|
|
100
96
|
],
|
|
101
97
|
"roles": {},
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
"name": "v-b",
|
|
39
39
|
"provider": "openai",
|
|
40
40
|
"quotaWeight": 1,
|
|
41
|
-
"
|
|
42
|
-
"tier": "standard",
|
|
43
|
-
"vision": false
|
|
41
|
+
"tier": "standard"
|
|
44
42
|
}
|
|
45
43
|
],
|
|
46
44
|
"roles": {},
|
|
@@ -93,9 +91,7 @@
|
|
|
93
91
|
"name": "v-b",
|
|
94
92
|
"provider": "openai",
|
|
95
93
|
"quotaWeight": 1,
|
|
96
|
-
"
|
|
97
|
-
"tier": "standard",
|
|
98
|
-
"vision": false
|
|
94
|
+
"tier": "standard"
|
|
99
95
|
}
|
|
100
96
|
],
|
|
101
97
|
"roles": {},
|
|
@@ -38,9 +38,7 @@
|
|
|
38
38
|
"name": "v-a",
|
|
39
39
|
"provider": "openai",
|
|
40
40
|
"quotaWeight": 1,
|
|
41
|
-
"
|
|
42
|
-
"tier": "standard",
|
|
43
|
-
"vision": false
|
|
41
|
+
"tier": "standard"
|
|
44
42
|
}
|
|
45
43
|
],
|
|
46
44
|
"roles": {},
|
|
@@ -93,9 +91,7 @@
|
|
|
93
91
|
"name": "v-a",
|
|
94
92
|
"provider": "openai",
|
|
95
93
|
"quotaWeight": 1,
|
|
96
|
-
"
|
|
97
|
-
"tier": "standard",
|
|
98
|
-
"vision": false
|
|
94
|
+
"tier": "standard"
|
|
99
95
|
}
|
|
100
96
|
],
|
|
101
97
|
"roles": {},
|
|
@@ -41,9 +41,7 @@
|
|
|
41
41
|
"name": "keep",
|
|
42
42
|
"provider": "openai",
|
|
43
43
|
"quotaWeight": 1,
|
|
44
|
-
"
|
|
45
|
-
"tier": "standard",
|
|
46
|
-
"vision": false
|
|
44
|
+
"tier": "standard"
|
|
47
45
|
}
|
|
48
46
|
],
|
|
49
47
|
"roles": {},
|
|
@@ -132,9 +130,7 @@
|
|
|
132
130
|
"name": "keep",
|
|
133
131
|
"provider": "openai",
|
|
134
132
|
"quotaWeight": 1,
|
|
135
|
-
"
|
|
136
|
-
"tier": "standard",
|
|
137
|
-
"vision": false
|
|
133
|
+
"tier": "standard"
|
|
138
134
|
}
|
|
139
135
|
],
|
|
140
136
|
"roles": {},
|