@sema-agent/settings-schema 12.1.1 → 12.2.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 +22 -0
- package/README.md +2 -1
- package/conformance/VERSION +1 -1
- package/dist/types.d.ts +13 -0
- package/dist/types.js +48 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,28 @@
|
|
|
6
6
|
> `@sema-agent/registry-core`(更早还曾是 `@sema-ai/registry-core`)。本档 `0.19.0` 以下各节里的
|
|
7
7
|
> 包名是**历史记录**,如实保留不追改。
|
|
8
8
|
|
|
9
|
+
## 12.2.0 — 2026-10-12 — minor:`mcp.servers[]` 条目三只解析透明可选键 `toolAxes` / `authForm` / `entryKind` · http 传输可选 `assertionHeader`(与 `principalHeader` 互斥)
|
|
10
|
+
|
|
11
|
+
> minor:`mcp.servers[]` 条目上多三只**解析透明**的可选键 `toolAxes` / `authForm` / `entryKind`;http 形传输上多一只可选键 `assertionHeader`(HTTP 头名),与 `principalHeader` 互斥。
|
|
12
|
+
> additive:零删、零改名、零改形;导出名不变(导出面登记表 0 行变化);四个键缺席时读数逐字不变。
|
|
13
|
+
|
|
14
|
+
### 新键:连接器条目的三只声明键 `toolAxes` / `authForm` / `entryKind`(解析透明)
|
|
15
|
+
|
|
16
|
+
此前这三个键写进 `config.d/mcp.json`(或由中心下发)时,在本地腿与 wire 腿都被剥掉并报 `unknown-keys-dropped`,消费方读到缺席。现在照 `toolFaces`(1.9.0)的先例:
|
|
17
|
+
`z.unknown().optional()`,**解析透明**,登记在 `PARSE_TRANSPARENT_KEYS`(三行,`since: "12.2.0"`,`validatedBy: "consumer"`)—— 本包只承载、原样过(对象 / 数组 / 标量 / `null` 一视同仁),
|
|
18
|
+
不判形、不判语义;词表与含义归读它的消费方(连接器的挂载读、服务器的投影)。缺席 ⇒ 键不铸(没有默认)。
|
|
19
|
+
三问 —— **谁需要**:连接器的 hosted / standalone 条目形(启动器写条目、消费方读条目);**谁受伤**:无 —— 四个键都缺席时读数逐字不变;三键在场时此前是被剥并告警、现在逐字保留(把「被剥」当契约的读法没有依据);**补偿**:缺省缺席,不写这三个键的条目逐字不变。
|
|
20
|
+
钉:`test/mcp-connector-keys-12.2.test.ts`(任意形原样过 · 缺席不铸 · 登记三行 · 本地腿 round-trip 与 `readEffectiveWire`)· `test/parse-transparent-keys.test.ts`(登记表与 schema 双向对拍,自动覆盖三行)。
|
|
21
|
+
|
|
22
|
+
### 新键:http 传输的 `assertionHeader`,与 `principalHeader` 互斥
|
|
23
|
+
|
|
24
|
+
`transport: { kind: "http", … }` 多一只可选键 `assertionHeader`:服务往这台(hosted 连接器)服务器的请求上用哪个头送**连接器断言**。头名过与 `principalHeader` / `headerRefs` 键**同一只**判官
|
|
25
|
+
(RFC 7230 token、不得是凭据形);本包只判形,断言怎么铸、怎么验归消费方。`principalHeader` 与 `assertionHeader` 回答同一个问题(「这台 http 服务器的请求上用哪个头送身份」)的两个答案,
|
|
26
|
+
所以**同在一条里 ⇒ 解析期拒**,拒句点名条目名与两个键;互斥只在条目层判一处,三道门(条目 / `McpConfig` / `validateDomain`)同一判,读路径上该条目按逐条容错被丢(`entry-dropped`),同域其余条目存活。
|
|
27
|
+
stdio 形传输上给它:与 `principalHeader` 在 stdio 上的既有处置**同判** —— 解析不拒、键被剥、读路径照常报 `unknown-keys-dropped`(不自造第二套)。
|
|
28
|
+
三问 —— **谁需要**:连接器的 hosted 条目形(断言头名在条目上声明,不靠约定俗成的暂定名);**谁受伤**:无 —— 新键,缺席时读数逐字不变;写过 `principalHeader` 的条目不受影响(只在两键同设时才拒,而 `assertionHeader` 此前不存在);**补偿**:缺省缺席;只想送终端用户主体的条目继续只设 `principalHeader`。
|
|
29
|
+
钉:`test/mcp-assertion-header-12.2.test.ts`(单独在场过且缺席不铸 · 同在拒且拒句点名条目与两键 · 头名形与 `principalHeader` 同表差分 · stdio 同判 · 本地腿逐条丢)。
|
|
30
|
+
|
|
9
31
|
## 12.1.1 — 2026-10-12 — patch:`isAbsoluteHostPath` 认三族绝对形(posix `/…` · Windows 盘符 `X:\\…` / `X:/…` · UNC `\\\\server\\share\\…`),同一条律(零 `..` 段、零 NUL、长度上界);拒句点名三族
|
|
10
32
|
|
|
11
33
|
- **行为修复(宿主路径形判)**。`isAbsoluteHostPath` / `AbsoluteHostPath` 此前只认 `/` 开头(posix 口径),Windows 壳按 CC 同形送 `C:\…` 的任务 `cwd` / `additionalDirectories` / `skill.baseDir` 全被判「非绝对」—— 读它的 server 7.125.0 据此把 Windows 宿主的**每一条提交** 400 掉。
|
package/README.md
CHANGED
|
@@ -482,7 +482,8 @@ therefore shows only `zod`. Node built-ins only (`node:crypto`, `node:fs`).
|
|
|
482
482
|
carries verbatim WITHOUT checking their shape, each row naming who does check it (the engine's ingest side or
|
|
483
483
|
a consumer's enforcement point). Today: `models[].compat` (1.10.0), `models[].headers` (6.4.0; the header-name
|
|
484
484
|
allowlist × lane is sema-server's, not restated here), `mcp.servers[].source` (1.7.2), `mcp.servers[].toolFaces`
|
|
485
|
-
(1.9.0),
|
|
485
|
+
(1.9.0), `mcp.servers[].toolAxes` / `authForm` / `entryKind` (12.2.0; connector-entry declarations, semantics are the consumer's),
|
|
486
|
+
and an entitlement override's `value`. `models[].extraBody` is NOT one of them — it has its own shape
|
|
486
487
|
gate (a plain JSON object); what it leaves open is the key vocabulary inside. `compat` / `headers` / `extraBody`
|
|
487
488
|
still clear the one free-form safety judgment (secret-shaped key/value, accessor, cycle, non-JSON, too deep ⇒ rejected).
|
|
488
489
|
- **Extension namespaces** (`EXTENSION_NAMESPACES`, 1.5.0): keys another writer puts in a domain document by
|
package/conformance/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
12.
|
|
1
|
+
12.2.0
|
package/dist/types.d.ts
CHANGED
|
@@ -1841,6 +1841,7 @@ export declare const McpTransport: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1841
1841
|
url: z.ZodString;
|
|
1842
1842
|
headerRefs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1843
1843
|
principalHeader: z.ZodOptional<z.ZodString>;
|
|
1844
|
+
assertionHeader: z.ZodOptional<z.ZodString>;
|
|
1844
1845
|
}, z.core.$strip>], "kind">;
|
|
1845
1846
|
export type McpTransport = z.infer<typeof McpTransport>;
|
|
1846
1847
|
/** The closed word table for {@link McpServerSpec}.contentOrigin — a MIRROR literal of the engine's
|
|
@@ -1862,6 +1863,7 @@ export declare const McpServerSpec: z.ZodObject<{
|
|
|
1862
1863
|
url: z.ZodString;
|
|
1863
1864
|
headerRefs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1864
1865
|
principalHeader: z.ZodOptional<z.ZodString>;
|
|
1866
|
+
assertionHeader: z.ZodOptional<z.ZodString>;
|
|
1865
1867
|
}, z.core.$strip>], "kind">;
|
|
1866
1868
|
allowTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1867
1869
|
scenarios: z.ZodPrefault<z.ZodArray<z.ZodString>>;
|
|
@@ -1875,6 +1877,9 @@ export declare const McpServerSpec: z.ZodObject<{
|
|
|
1875
1877
|
}>>;
|
|
1876
1878
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
1877
1879
|
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
1880
|
+
toolAxes: z.ZodOptional<z.ZodUnknown>;
|
|
1881
|
+
authForm: z.ZodOptional<z.ZodUnknown>;
|
|
1882
|
+
entryKind: z.ZodOptional<z.ZodUnknown>;
|
|
1878
1883
|
notes: z.ZodOptional<z.ZodString>;
|
|
1879
1884
|
}, z.core.$strip>;
|
|
1880
1885
|
export type McpServerSpec = z.infer<typeof McpServerSpec>;
|
|
@@ -1891,6 +1896,7 @@ export declare const McpConfig: z.ZodObject<{
|
|
|
1891
1896
|
url: z.ZodString;
|
|
1892
1897
|
headerRefs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1893
1898
|
principalHeader: z.ZodOptional<z.ZodString>;
|
|
1899
|
+
assertionHeader: z.ZodOptional<z.ZodString>;
|
|
1894
1900
|
}, z.core.$strip>], "kind">;
|
|
1895
1901
|
allowTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1896
1902
|
scenarios: z.ZodPrefault<z.ZodArray<z.ZodString>>;
|
|
@@ -1904,6 +1910,9 @@ export declare const McpConfig: z.ZodObject<{
|
|
|
1904
1910
|
}>>;
|
|
1905
1911
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
1906
1912
|
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
1913
|
+
toolAxes: z.ZodOptional<z.ZodUnknown>;
|
|
1914
|
+
authForm: z.ZodOptional<z.ZodUnknown>;
|
|
1915
|
+
entryKind: z.ZodOptional<z.ZodUnknown>;
|
|
1907
1916
|
notes: z.ZodOptional<z.ZodString>;
|
|
1908
1917
|
}, z.core.$strip>>>;
|
|
1909
1918
|
}, z.core.$strip>;
|
|
@@ -2439,6 +2448,7 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
2439
2448
|
url: z.ZodString;
|
|
2440
2449
|
headerRefs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
2441
2450
|
principalHeader: z.ZodOptional<z.ZodString>;
|
|
2451
|
+
assertionHeader: z.ZodOptional<z.ZodString>;
|
|
2442
2452
|
}, z.core.$strip>], "kind">;
|
|
2443
2453
|
allowTools: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2444
2454
|
scenarios: z.ZodPrefault<z.ZodArray<z.ZodString>>;
|
|
@@ -2452,6 +2462,9 @@ export declare const DOMAIN_SCHEMAS: {
|
|
|
2452
2462
|
}>>;
|
|
2453
2463
|
source: z.ZodOptional<z.ZodUnknown>;
|
|
2454
2464
|
toolFaces: z.ZodOptional<z.ZodUnknown>;
|
|
2465
|
+
toolAxes: z.ZodOptional<z.ZodUnknown>;
|
|
2466
|
+
authForm: z.ZodOptional<z.ZodUnknown>;
|
|
2467
|
+
entryKind: z.ZodOptional<z.ZodUnknown>;
|
|
2455
2468
|
notes: z.ZodOptional<z.ZodString>;
|
|
2456
2469
|
}, z.core.$strip>>>;
|
|
2457
2470
|
}, z.core.$strip>;
|
package/dist/types.js
CHANGED
|
@@ -418,6 +418,27 @@ export const PARSE_TRANSPARENT_KEYS = [
|
|
|
418
418
|
validatedBy: "engine-ingest",
|
|
419
419
|
why: "按远端工具名 key 的 face 覆盖层,形归引擎摄入侧(不合 schema 的工具不挂并通告一次);本包复述那张表必漂。",
|
|
420
420
|
},
|
|
421
|
+
{
|
|
422
|
+
domain: "mcp",
|
|
423
|
+
path: "servers[].toolAxes",
|
|
424
|
+
since: "12.2.0",
|
|
425
|
+
validatedBy: "consumer",
|
|
426
|
+
why: "连接器条目声明的按工具轴覆盖层;轴的词表与形归投影它的消费方(server 两腿进 core spec)与写它的连接器,本包只承载,复述那张表必漂。",
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
domain: "mcp",
|
|
430
|
+
path: "servers[].authForm",
|
|
431
|
+
since: "12.2.0",
|
|
432
|
+
validatedBy: "consumer",
|
|
433
|
+
why: "连接器条目声明的认证形;词表与语义归读它的消费方(connectors 挂载读 / server 投影),本包只承载、不判语义。",
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
domain: "mcp",
|
|
437
|
+
path: "servers[].entryKind",
|
|
438
|
+
since: "12.2.0",
|
|
439
|
+
validatedBy: "consumer",
|
|
440
|
+
why: "连接器条目声明的条目种类;词表与语义归读它的消费方(connectors 挂载读 / server 投影),本包只承载、不判语义。",
|
|
441
|
+
},
|
|
421
442
|
{
|
|
422
443
|
domain: "entitlement",
|
|
423
444
|
path: "subjects[].overrides[].value",
|
|
@@ -2346,7 +2367,8 @@ const McpEnvRefs = z.record(ENV_NAME, ENV_NAME); // target ENV key → ENV_NAME
|
|
|
2346
2367
|
// (a headerRefs key `sk-live-…`, or principalHeader `ghp_…`) is stored + shipped verbatim on /effective — the
|
|
2347
2368
|
// SAME invariant-① gap as worker.env / model.extraBody / mcp stdio command+args (credentials belong on the
|
|
2348
2369
|
// VALUE side = an env-NAME ref, never the name). The token charset includes `%`, so an encoded secret could ride
|
|
2349
|
-
// the name — containsSecretToken percent-decodes, catching it too. ONE shared schema for
|
|
2370
|
+
// the name — containsSecretToken percent-decodes, catching it too. ONE shared schema for every header-name field
|
|
2371
|
+
// (headerRefs keys, principalHeader, assertionHeader). R19.
|
|
2350
2372
|
const HTTP_HEADER_NAME = z
|
|
2351
2373
|
.string()
|
|
2352
2374
|
.regex(/^[A-Za-z0-9!#$%&'*+.^_`|~-]+$/, "must be an HTTP header NAME")
|
|
@@ -2384,6 +2406,14 @@ export const McpTransport = z.discriminatedUnion("kind", [
|
|
|
2384
2406
|
* this is dynamic — the caller's principal, set per-request by the worker — so it's a header NAME, not an
|
|
2385
2407
|
* env-NAME ref (no secret). Empty → the worker forwards no principal (server sees an anonymous call). */
|
|
2386
2408
|
principalHeader: HTTP_HEADER_NAME.optional(),
|
|
2409
|
+
/** 12.2.0 —— Header NAME the SERVICE fills with the CONNECTOR ASSERTION when proxying a tool call to this (hosted connector)
|
|
2410
|
+
* server. Like `principalHeader` it is a header NAME, not an env-NAME ref (no secret), and it answers the same question
|
|
2411
|
+
* — "which header carries the identity on this request" — with a different answer, so the two are MUTUALLY EXCLUSIVE:
|
|
2412
|
+
* the entry-level check on {@link McpServerSpec} rejects both set. The name goes through the same judge
|
|
2413
|
+
* ({@link HTTP_HEADER_NAME}) as `principalHeader` / `headerRefs` keys. This package judges only the SHAPE: how the assertion
|
|
2414
|
+
* is minted and verified is the consumers' (connectors / server). Absent = no assertion header. On a stdio transport the key
|
|
2415
|
+
* is stripped exactly as `principalHeader` is (the stdio member has no such key). */
|
|
2416
|
+
assertionHeader: HTTP_HEADER_NAME.optional(),
|
|
2387
2417
|
}),
|
|
2388
2418
|
]);
|
|
2389
2419
|
/** The closed word table for {@link McpServerSpec}.contentOrigin — a MIRROR literal of the engine's
|
|
@@ -2443,7 +2473,24 @@ export const McpServerSpec = z.object({
|
|
|
2443
2473
|
*
|
|
2444
2474
|
* **解析透明** —— 形归谁校验、为什么不放这里:{@link PARSE_TRANSPARENT_KEYS}(`mcp.servers[].toolFaces`)。 */
|
|
2445
2475
|
toolFaces: z.unknown().optional(),
|
|
2476
|
+
/** 12.2.0 —— 连接器条目的按工具轴覆盖层声明。缺席 = 不铸键;语义归消费方(server 两腿投影进引擎 spec),本包只承载。
|
|
2477
|
+
*
|
|
2478
|
+
* **解析透明** —— 形归谁校验、为什么不放这里:{@link PARSE_TRANSPARENT_KEYS}(`mcp.servers[].toolAxes`)。 */
|
|
2479
|
+
toolAxes: z.unknown().optional(),
|
|
2480
|
+
/** 12.2.0 —— 连接器条目的认证形声明。缺席 = 不铸键;语义归消费方,本包只承载。
|
|
2481
|
+
*
|
|
2482
|
+
* **解析透明** —— 形归谁校验、为什么不放这里:{@link PARSE_TRANSPARENT_KEYS}(`mcp.servers[].authForm`)。 */
|
|
2483
|
+
authForm: z.unknown().optional(),
|
|
2484
|
+
/** 12.2.0 —— 连接器条目的种类声明。缺席 = 不铸键;语义归消费方,本包只承载。
|
|
2485
|
+
*
|
|
2486
|
+
* **解析透明** —— 形归谁校验、为什么不放这里:{@link PARSE_TRANSPARENT_KEYS}(`mcp.servers[].entryKind`)。 */
|
|
2487
|
+
entryKind: z.unknown().optional(),
|
|
2446
2488
|
notes: z.string().optional(),
|
|
2489
|
+
}).superRefine((s, ctx) => {
|
|
2490
|
+
// 身份头二选一(12.2.0):`principalHeader` 与 `assertionHeader` 回答同一个问题「这台 http 服务器的请求上用哪个头送身份」—— 同设 = 两个答案。
|
|
2491
|
+
// 互斥只在这一处判(拒句点名条目名,所以住条目层,不住传输层:传输层看不见 `name`)。
|
|
2492
|
+
if (s.transport.kind === "http" && s.transport.principalHeader !== undefined && s.transport.assertionHeader !== undefined)
|
|
2493
|
+
ctx.addIssue({ code: "custom", ...buildQuotedIssue `mcp server "${s.name}" sets both principalHeader and assertionHeader — an http entry names ONE header for the identity it sends: keep principalHeader (the end-user principal) or assertionHeader (the connector assertion), not both`, path: ["transport", "assertionHeader"] });
|
|
2447
2494
|
});
|
|
2448
2495
|
export const McpConfig = z
|
|
2449
2496
|
.object({ servers: z.array(McpServerSpec).prefault([]) })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/settings-schema",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.2.0",
|
|
4
4
|
"description": "Sema settings schema — pure config contract (zod domains + effective-config + roster resolution + ref-integrity + remoteExec) shared by sema-web-admin, 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",
|