@sema-agent/settings-schema 1.7.0 → 1.7.2

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 CHANGED
@@ -6,6 +6,24 @@
6
6
  > `@sema-agent/registry-core`(更早还曾是 `@sema-ai/registry-core`)。本档 `0.19.0` 以下各节里的
7
7
  > 包名是**历史记录**,如实保留不追改。
8
8
 
9
+ ## 1.7.2 — 2026-09-06 — `source` 改**解析透明**(`z.unknown()`;patch)
10
+
11
+ - 1.7.1 的 `z.string()` 对 `source: null`(或数字/数组/对象)仍在解析处拒 ⇒ 整域 all-or-nothing 下**一个**非串标签让整套
12
+ `mcp.servers` 默认为空——而 1.6.0 之前该键被 default-strip 剥掉、无害,故这是 1.7.x 引入的**升级回归**(消费方 codex
13
+ 对抗复审 [high],`buildEffective` 与 `readEffectiveWire` 两腿复现)。1.7.2 起 `source: z.unknown().optional()`:
14
+ 任何 JSON 值原样到消费方,规则(非空 ≤80 字符串)与坏形处置(丢键留 server + 留痕)**只**在消费方一处。
15
+ - 红先:`test/mcp-source-label.test.ts` ③ 改「七形全过、原样」+ ③b「坏标签兄弟不拖累好 server」。
16
+ - 类病(任一字段解析拒 ⇒ 整域默认)仍归消费方 S-144 另车。
17
+
18
+ ## 1.7.1 — 2026-09-06 — `source` 改**只管类型**(撤回 1.7.0 的 min/max 解析拒;patch)
19
+
20
+ - 1.7.0 把标签规则(非空 ≤80)写进 zod ⇒ 本域整域 all-or-nothing 解析下,**一个**空/超长标签让整套 `mcp.servers`
21
+ 在解析处整域默认(每台 server 消失),消费方 boot 期还容忍空目录——一个显示标签不该有这种爆炸半径
22
+ (消费方 codex 对抗复审 [high],真库复现:一坏一好两条 server 双双消失)。1.7.1 起 `source: z.string().optional()`,
23
+ 规则单点留在消费方投影层(坏形丢键留 server、留痕)。非字符串仍在解析处拒(那是 JSON 类型错,与任何字段同类)。
24
+ - 顺带如实记:本域 all-or-nothing 解析 + 消费方 boot 容忍空目录,对 `contentOrigin` 闭表等一切解析拒的键**早已**是
25
+ 同一爆炸半径(类病,先于本键存在)——归消费方与本包另立单据处置(逐条目拒而不是整域拒),不在本 patch 射程。
26
+
9
27
  ## 1.7.0 — 2026-09-06 — `mcp.servers[].source` 分组标签(sema-server B-036 / S-143 源头修的声明面半场;新键=minor)
10
28
 
11
29
  - **`McpServerSpec.source?: string`**(非空、≤80 字;`.optional()` 无默认):声明方自述的层级标签,1:1 对应引擎
package/dist/types.d.ts CHANGED
@@ -7322,12 +7322,18 @@ export declare const McpServerSpec: z.ZodObject<{
7322
7322
  * consumer can group servers by where they were declared). An OPEN set: CC's `plugin` / `user` /
7323
7323
  * `project` / `local` are conventions, not a vocabulary — a deployment's own word is equally legal, so
7324
7324
  * no closed table here (a closed table would reject the operator's grouping word at parse). ABSENT =
7325
- * no label (`.optional()`, no default — a label has no default tier). Empty / over-cap / non-string is
7326
- * REJECTED at parse: a malformed label must not enter the ledger silently. Display-only: no gate /
7327
- * policy / trust effect (the trust axis is `contentOrigin` above, which stays a closed table).
7328
- * Before this key existed both legs stripped it (default-strip object); this is the declaration half of
7329
- * the consumer-side fix (ticket B-036 / S-143), the projection half lives in the consumer. */
7330
- source: z.ZodOptional<z.ZodString>;
7325
+ * no label (`.optional()`, no default — a label has no default tier). 🔴 ZERO rules here (`z.unknown()`):
7326
+ * the label RULE (string, non-empty, ≤80 chars) lives in ONE place — the consumer's projection helper,
7327
+ * which drops a malformed label's KEY, keeps the server and records the drop. Nothing may live here:
7328
+ * this domain parses all-or-nothing, so ANY rejection at parse (1.7.0 `min/max`, 1.7.1 `z.string()`
7329
+ * against a `null`) lets one bad label default the ENTIRE mcp domain — every server gone, silently when
7330
+ * no onWarning is wired — a blast radius a display label must never have. 1.7.2 makes the key
7331
+ * parse-transparent: whatever JSON value the file carries reaches the consumer verbatim. Display-only:
7332
+ * no gate / policy / trust
7333
+ * effect (the trust axis is `contentOrigin` above, which stays a closed table). Before this key existed
7334
+ * both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
7335
+ * (ticket B-036 / S-143), the projection half lives in the consumer. */
7336
+ source: z.ZodOptional<z.ZodUnknown>;
7331
7337
  notes: z.ZodOptional<z.ZodString>;
7332
7338
  }, "strip", z.ZodTypeAny, {
7333
7339
  name: string;
@@ -7349,7 +7355,7 @@ export declare const McpServerSpec: z.ZodObject<{
7349
7355
  notes?: string | undefined;
7350
7356
  allowTools?: string[] | undefined;
7351
7357
  contentOrigin?: "local" | "execution" | "external" | undefined;
7352
- source?: string | undefined;
7358
+ source?: unknown;
7353
7359
  }, {
7354
7360
  name: string;
7355
7361
  transport: {
@@ -7370,7 +7376,7 @@ export declare const McpServerSpec: z.ZodObject<{
7370
7376
  allowTools?: string[] | undefined;
7371
7377
  elicitation?: boolean | undefined;
7372
7378
  contentOrigin?: "local" | "execution" | "external" | undefined;
7373
- source?: string | undefined;
7379
+ source?: unknown;
7374
7380
  }>;
7375
7381
  export type McpServerSpec = z.infer<typeof McpServerSpec>;
7376
7382
  export declare const McpConfig: z.ZodEffects<z.ZodObject<{
@@ -7447,12 +7453,18 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
7447
7453
  * consumer can group servers by where they were declared). An OPEN set: CC's `plugin` / `user` /
7448
7454
  * `project` / `local` are conventions, not a vocabulary — a deployment's own word is equally legal, so
7449
7455
  * no closed table here (a closed table would reject the operator's grouping word at parse). ABSENT =
7450
- * no label (`.optional()`, no default — a label has no default tier). Empty / over-cap / non-string is
7451
- * REJECTED at parse: a malformed label must not enter the ledger silently. Display-only: no gate /
7452
- * policy / trust effect (the trust axis is `contentOrigin` above, which stays a closed table).
7453
- * Before this key existed both legs stripped it (default-strip object); this is the declaration half of
7454
- * the consumer-side fix (ticket B-036 / S-143), the projection half lives in the consumer. */
7455
- source: z.ZodOptional<z.ZodString>;
7456
+ * no label (`.optional()`, no default — a label has no default tier). 🔴 ZERO rules here (`z.unknown()`):
7457
+ * the label RULE (string, non-empty, ≤80 chars) lives in ONE place — the consumer's projection helper,
7458
+ * which drops a malformed label's KEY, keeps the server and records the drop. Nothing may live here:
7459
+ * this domain parses all-or-nothing, so ANY rejection at parse (1.7.0 `min/max`, 1.7.1 `z.string()`
7460
+ * against a `null`) lets one bad label default the ENTIRE mcp domain — every server gone, silently when
7461
+ * no onWarning is wired — a blast radius a display label must never have. 1.7.2 makes the key
7462
+ * parse-transparent: whatever JSON value the file carries reaches the consumer verbatim. Display-only:
7463
+ * no gate / policy / trust
7464
+ * effect (the trust axis is `contentOrigin` above, which stays a closed table). Before this key existed
7465
+ * both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
7466
+ * (ticket B-036 / S-143), the projection half lives in the consumer. */
7467
+ source: z.ZodOptional<z.ZodUnknown>;
7456
7468
  notes: z.ZodOptional<z.ZodString>;
7457
7469
  }, "strip", z.ZodTypeAny, {
7458
7470
  name: string;
@@ -7474,7 +7486,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
7474
7486
  notes?: string | undefined;
7475
7487
  allowTools?: string[] | undefined;
7476
7488
  contentOrigin?: "local" | "execution" | "external" | undefined;
7477
- source?: string | undefined;
7489
+ source?: unknown;
7478
7490
  }, {
7479
7491
  name: string;
7480
7492
  transport: {
@@ -7495,7 +7507,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
7495
7507
  allowTools?: string[] | undefined;
7496
7508
  elicitation?: boolean | undefined;
7497
7509
  contentOrigin?: "local" | "execution" | "external" | undefined;
7498
- source?: string | undefined;
7510
+ source?: unknown;
7499
7511
  }>, "many">>;
7500
7512
  }, "strip", z.ZodTypeAny, {
7501
7513
  servers: {
@@ -7518,7 +7530,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
7518
7530
  notes?: string | undefined;
7519
7531
  allowTools?: string[] | undefined;
7520
7532
  contentOrigin?: "local" | "execution" | "external" | undefined;
7521
- source?: string | undefined;
7533
+ source?: unknown;
7522
7534
  }[];
7523
7535
  }, {
7524
7536
  servers?: {
@@ -7541,7 +7553,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
7541
7553
  allowTools?: string[] | undefined;
7542
7554
  elicitation?: boolean | undefined;
7543
7555
  contentOrigin?: "local" | "execution" | "external" | undefined;
7544
- source?: string | undefined;
7556
+ source?: unknown;
7545
7557
  }[] | undefined;
7546
7558
  }>, {
7547
7559
  servers: {
@@ -7564,7 +7576,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
7564
7576
  notes?: string | undefined;
7565
7577
  allowTools?: string[] | undefined;
7566
7578
  contentOrigin?: "local" | "execution" | "external" | undefined;
7567
- source?: string | undefined;
7579
+ source?: unknown;
7568
7580
  }[];
7569
7581
  }, {
7570
7582
  servers?: {
@@ -7587,7 +7599,7 @@ export declare const McpConfig: z.ZodEffects<z.ZodObject<{
7587
7599
  allowTools?: string[] | undefined;
7588
7600
  elicitation?: boolean | undefined;
7589
7601
  contentOrigin?: "local" | "execution" | "external" | undefined;
7590
- source?: string | undefined;
7602
+ source?: unknown;
7591
7603
  }[] | undefined;
7592
7604
  }>;
7593
7605
  export type McpConfig = z.infer<typeof McpConfig>;
@@ -10114,12 +10126,18 @@ export declare const DOMAIN_SCHEMAS: {
10114
10126
  * consumer can group servers by where they were declared). An OPEN set: CC's `plugin` / `user` /
10115
10127
  * `project` / `local` are conventions, not a vocabulary — a deployment's own word is equally legal, so
10116
10128
  * no closed table here (a closed table would reject the operator's grouping word at parse). ABSENT =
10117
- * no label (`.optional()`, no default — a label has no default tier). Empty / over-cap / non-string is
10118
- * REJECTED at parse: a malformed label must not enter the ledger silently. Display-only: no gate /
10119
- * policy / trust effect (the trust axis is `contentOrigin` above, which stays a closed table).
10120
- * Before this key existed both legs stripped it (default-strip object); this is the declaration half of
10121
- * the consumer-side fix (ticket B-036 / S-143), the projection half lives in the consumer. */
10122
- source: z.ZodOptional<z.ZodString>;
10129
+ * no label (`.optional()`, no default — a label has no default tier). 🔴 ZERO rules here (`z.unknown()`):
10130
+ * the label RULE (string, non-empty, ≤80 chars) lives in ONE place — the consumer's projection helper,
10131
+ * which drops a malformed label's KEY, keeps the server and records the drop. Nothing may live here:
10132
+ * this domain parses all-or-nothing, so ANY rejection at parse (1.7.0 `min/max`, 1.7.1 `z.string()`
10133
+ * against a `null`) lets one bad label default the ENTIRE mcp domain — every server gone, silently when
10134
+ * no onWarning is wired — a blast radius a display label must never have. 1.7.2 makes the key
10135
+ * parse-transparent: whatever JSON value the file carries reaches the consumer verbatim. Display-only:
10136
+ * no gate / policy / trust
10137
+ * effect (the trust axis is `contentOrigin` above, which stays a closed table). Before this key existed
10138
+ * both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
10139
+ * (ticket B-036 / S-143), the projection half lives in the consumer. */
10140
+ source: z.ZodOptional<z.ZodUnknown>;
10123
10141
  notes: z.ZodOptional<z.ZodString>;
10124
10142
  }, "strip", z.ZodTypeAny, {
10125
10143
  name: string;
@@ -10141,7 +10159,7 @@ export declare const DOMAIN_SCHEMAS: {
10141
10159
  notes?: string | undefined;
10142
10160
  allowTools?: string[] | undefined;
10143
10161
  contentOrigin?: "local" | "execution" | "external" | undefined;
10144
- source?: string | undefined;
10162
+ source?: unknown;
10145
10163
  }, {
10146
10164
  name: string;
10147
10165
  transport: {
@@ -10162,7 +10180,7 @@ export declare const DOMAIN_SCHEMAS: {
10162
10180
  allowTools?: string[] | undefined;
10163
10181
  elicitation?: boolean | undefined;
10164
10182
  contentOrigin?: "local" | "execution" | "external" | undefined;
10165
- source?: string | undefined;
10183
+ source?: unknown;
10166
10184
  }>, "many">>;
10167
10185
  }, "strip", z.ZodTypeAny, {
10168
10186
  servers: {
@@ -10185,7 +10203,7 @@ export declare const DOMAIN_SCHEMAS: {
10185
10203
  notes?: string | undefined;
10186
10204
  allowTools?: string[] | undefined;
10187
10205
  contentOrigin?: "local" | "execution" | "external" | undefined;
10188
- source?: string | undefined;
10206
+ source?: unknown;
10189
10207
  }[];
10190
10208
  }, {
10191
10209
  servers?: {
@@ -10208,7 +10226,7 @@ export declare const DOMAIN_SCHEMAS: {
10208
10226
  allowTools?: string[] | undefined;
10209
10227
  elicitation?: boolean | undefined;
10210
10228
  contentOrigin?: "local" | "execution" | "external" | undefined;
10211
- source?: string | undefined;
10229
+ source?: unknown;
10212
10230
  }[] | undefined;
10213
10231
  }>, {
10214
10232
  servers: {
@@ -10231,7 +10249,7 @@ export declare const DOMAIN_SCHEMAS: {
10231
10249
  notes?: string | undefined;
10232
10250
  allowTools?: string[] | undefined;
10233
10251
  contentOrigin?: "local" | "execution" | "external" | undefined;
10234
- source?: string | undefined;
10252
+ source?: unknown;
10235
10253
  }[];
10236
10254
  }, {
10237
10255
  servers?: {
@@ -10254,7 +10272,7 @@ export declare const DOMAIN_SCHEMAS: {
10254
10272
  allowTools?: string[] | undefined;
10255
10273
  elicitation?: boolean | undefined;
10256
10274
  contentOrigin?: "local" | "execution" | "external" | undefined;
10257
- source?: string | undefined;
10275
+ source?: unknown;
10258
10276
  }[] | undefined;
10259
10277
  }>;
10260
10278
  readonly plugins: z.ZodEffects<z.ZodObject<{
package/dist/types.js CHANGED
@@ -1893,12 +1893,18 @@ export const McpServerSpec = z.object({
1893
1893
  * consumer can group servers by where they were declared). An OPEN set: CC's `plugin` / `user` /
1894
1894
  * `project` / `local` are conventions, not a vocabulary — a deployment's own word is equally legal, so
1895
1895
  * no closed table here (a closed table would reject the operator's grouping word at parse). ABSENT =
1896
- * no label (`.optional()`, no default — a label has no default tier). Empty / over-cap / non-string is
1897
- * REJECTED at parse: a malformed label must not enter the ledger silently. Display-only: no gate /
1898
- * policy / trust effect (the trust axis is `contentOrigin` above, which stays a closed table).
1899
- * Before this key existed both legs stripped it (default-strip object); this is the declaration half of
1900
- * the consumer-side fix (ticket B-036 / S-143), the projection half lives in the consumer. */
1901
- source: z.string().min(1).max(80).optional(),
1896
+ * no label (`.optional()`, no default — a label has no default tier). 🔴 ZERO rules here (`z.unknown()`):
1897
+ * the label RULE (string, non-empty, ≤80 chars) lives in ONE place — the consumer's projection helper,
1898
+ * which drops a malformed label's KEY, keeps the server and records the drop. Nothing may live here:
1899
+ * this domain parses all-or-nothing, so ANY rejection at parse (1.7.0 `min/max`, 1.7.1 `z.string()`
1900
+ * against a `null`) lets one bad label default the ENTIRE mcp domain — every server gone, silently when
1901
+ * no onWarning is wired — a blast radius a display label must never have. 1.7.2 makes the key
1902
+ * parse-transparent: whatever JSON value the file carries reaches the consumer verbatim. Display-only:
1903
+ * no gate / policy / trust
1904
+ * effect (the trust axis is `contentOrigin` above, which stays a closed table). Before this key existed
1905
+ * both legs stripped it (default-strip object); this is the declaration half of the consumer-side fix
1906
+ * (ticket B-036 / S-143), the projection half lives in the consumer. */
1907
+ source: z.unknown().optional(),
1902
1908
  notes: z.string().optional(),
1903
1909
  });
1904
1910
  export const McpConfig = z
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/settings-schema",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "Sema settings schema — pure config contract (zod domains + effective-config + roster resolution + ref-integrity + remoteExec) shared by sema-registry, sema-server, and the TOC desktop/CLI. One source of truth. (Renamed at 1.0.0 from @sema-agent/registry-core — name and docs only, no behavior change; note the range moves 0.19.0 -> 1.0.0, so a dependency must become ^1.0.0. The old names @sema-agent/registry-core <=0.19.0 and @sema-ai/registry-core remain published, frozen, for migration.)",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",