@sema-agent/settings-schema 14.6.0 → 14.7.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 +266 -0
- package/README.md +31 -3
- package/conformance/VERSION +1 -1
- package/conformance/cases/c84-sandbox-git-block-carried-verbatim/expected.json +153 -0
- package/conformance/cases/c84-sandbox-git-block-carried-verbatim/input.json +23 -0
- package/conformance/cases/c84-sandbox-git-block-carried-verbatim/meta.json +5 -0
- package/conformance/cases/c85-sandbox-git-refused-block-still-carried/expected.json +153 -0
- package/conformance/cases/c85-sandbox-git-refused-block-still-carried/input.json +23 -0
- package/conformance/cases/c85-sandbox-git-refused-block-still-carried/meta.json +5 -0
- package/dist/api/auth-bridge.d.ts +16 -2
- package/dist/api/auth-bridge.js +59 -24
- package/dist/api/credentials.d.ts +281 -0
- package/dist/api/credentials.js +149 -0
- package/dist/api/scopes.js +5 -1
- package/dist/config-d-file.js +33 -15
- package/dist/config-fns.js +142 -78
- package/dist/conformance/canonical.js +4 -4
- package/dist/conformance/contract-adapter.js +26 -1
- package/dist/conformance/corpus.js +4 -4
- package/dist/conformance/derive.js +2 -2
- package/dist/conformance/run.js +43 -6
- package/dist/cross-session.d.ts +4 -4
- package/dist/declared-capture.d.ts +41 -0
- package/dist/declared-capture.js +344 -0
- package/dist/file-edit.js +11 -15
- package/dist/fleet.d.ts +11 -0
- package/dist/fleet.js +59 -26
- package/dist/hash.d.ts +0 -9
- package/dist/hash.js +64 -7
- package/dist/hooks-config.js +18 -3
- package/dist/http-hook-allowlists.d.ts +22 -9
- package/dist/http-hook-allowlists.js +169 -91
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp-request-entry.d.ts +9 -7
- package/dist/mcp-request-entry.js +89 -82
- package/dist/one-time-migrations.js +207 -95
- package/dist/own-key-read.d.ts +247 -0
- package/dist/own-key-read.js +449 -0
- package/dist/plain-json-object.d.ts +11 -1
- package/dist/plain-json-object.js +37 -1
- package/dist/remote-exec.js +9 -1
- package/dist/safety-merge-spec.js +50 -37
- package/dist/sandbox-git.d.ts +64 -0
- package/dist/sandbox-git.js +89 -0
- package/dist/scheduler-store.js +19 -11
- package/dist/settings-units.js +14 -12
- package/dist/types.d.ts +6 -2
- package/dist/types.js +11 -6
- package/dist/url-shape.d.ts +16 -0
- package/dist/url-shape.js +18 -0
- package/dist/web-admin-credential.js +5 -2
- package/dist/web-admin-session-url.js +2 -2
- package/dist/worker-row-verdict.d.ts +11 -0
- package/dist/worker-row-verdict.js +51 -1
- package/dist/workers-rows.js +38 -10
- package/dist/zod-unwrap.d.ts +6 -0
- package/dist/zod-unwrap.js +14 -7
- package/docs/API-SURFACE.md +35 -4
- package/docs/CONSUMER-INTEGRATION.md +178 -0
- package/llms-full.txt +23 -4
- package/llms.txt +3 -2
- package/package.json +1 -1
- package/dist/definition-copy.d.ts +0 -23
- package/dist/definition-copy.js +0 -52
|
@@ -8,19 +8,69 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { formatConfigPath, outgoingPath } from "./config-fns.js";
|
|
10
10
|
import { issuePath } from "./issue-path.js";
|
|
11
|
+
import { guardedSafeParse } from "./own-key-read.js";
|
|
12
|
+
import { jsonShapeOf } from "./plain-json-object.js";
|
|
11
13
|
import { WorkersConfig } from "./types.js";
|
|
12
14
|
/** 每一形的拒句主语 —— 穷举映射型:加一形不补这里即编译红。 */
|
|
13
15
|
const SUBJECT = {
|
|
14
16
|
stored: "the stored worker",
|
|
15
17
|
migrated: "after migration the worker",
|
|
16
18
|
};
|
|
19
|
+
/** 输入的「类型名」(zod 的 `invalid_type` 句子里 `received` 后面那个词):typeof / array / null,**从不读 `constructor`**。形状只问座位;数恒答 `number`
|
|
20
|
+
* (非有限的数到不了这里:{@link safeIssueMessage} 把它交还 zod 自己的句子)。 */
|
|
21
|
+
function receivedWord(input) {
|
|
22
|
+
switch (typeof input) {
|
|
23
|
+
case "number":
|
|
24
|
+
return "number";
|
|
25
|
+
case "object": {
|
|
26
|
+
const shape = jsonShapeOf(input);
|
|
27
|
+
switch (shape) {
|
|
28
|
+
case "null":
|
|
29
|
+
return "null";
|
|
30
|
+
case "array":
|
|
31
|
+
return "array";
|
|
32
|
+
case "plain":
|
|
33
|
+
case "non_plain_object":
|
|
34
|
+
case "uninspectable":
|
|
35
|
+
case "primitive":
|
|
36
|
+
return "object";
|
|
37
|
+
default: {
|
|
38
|
+
const unhandled = shape;
|
|
39
|
+
throw new Error(`receivedWord: unhandled shape ${String(unhandled)}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
default:
|
|
44
|
+
return typeof input;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* zod 的 `invalid_type` 句子(`Invalid input: expected <类型>, received <类型>`)—— 与 zod 自己的话**逐字同**(对每种 JSON 值;`test/migration-row-verdict-14.7.0` 逐值对着 zod 的原句核,升级 zod 改措辞即红),
|
|
49
|
+
* 区别只有一处:zod 对「原型不是 Object.prototype 的对象」读 `input.constructor.name` 当类型名 —— 原型不是 `Object.prototype` 的(隔离原型)行快照上,用户写的**自有 `constructor` 键**就成了类型名:
|
|
50
|
+
* 整次调用抛(`constructor.name` 是个对象)、用户文本进拒因(`received hello world`)、句子变样。这里不读 constructor。别的 issue 不管(返回 `undefined` ⇒ 沿用 zod 的 / 包自己写的句子)。
|
|
51
|
+
* 只给本文件的终判调用(`safeParse` 的 `error` 参数);它在 schema 自带的句子之后、zod 内置句子之前生效。
|
|
52
|
+
*/
|
|
53
|
+
export function safeIssueMessage(issue) {
|
|
54
|
+
if (issue.code !== "invalid_type")
|
|
55
|
+
return undefined;
|
|
56
|
+
// 非有限的数(`NaN` / `±Infinity` —— JSON 写不出 `NaN`;`±Infinity` 只由溢出的数字字面量如 `1e400` 解析出来)的类型名 zod 自己怎么说各版本不同:不抢,交还 zod 自己的句子(它不读 constructor)
|
|
57
|
+
if (typeof issue.input === "number" && !Number.isFinite(issue.input))
|
|
58
|
+
return undefined;
|
|
59
|
+
const expected = issue.expected === "nan" ? "NaN" : String(issue.expected);
|
|
60
|
+
return `Invalid input: expected ${expected}, received ${receivedWord(issue.input)}`;
|
|
61
|
+
}
|
|
17
62
|
/** 一只单行域里的 issue 路径 → 相对那一行(去掉 `["workers", 0]` 前缀;不在那一行下的 issue 原样)。 */
|
|
18
63
|
function rowRelative(path) {
|
|
19
64
|
return path[0] === "workers" && path[1] === 0 ? path.slice(2) : path;
|
|
20
65
|
}
|
|
21
66
|
/** 一行的终判:读得进 ⇒ `undefined`;读不进 ⇒ 第一条 issue 的路径(相对该行)+ 拒句(见文件头)。 */
|
|
22
67
|
export function workerRowVerdict(row, form) {
|
|
23
|
-
|
|
68
|
+
// 校验过程抛(会抛的 getter / 陷阱:读侧交进来的是调用方的活对象;zod 4.6 首读 `error` 时拼句子抛 —— 被污染的运行时、另一 realm 的怪形值)⇒ 这一行判「读不出」
|
|
69
|
+
// (定句,不含任何用户文本),不抛出调用。首读 `error` 与 `safeParse` 同在一只守护里(`guardedSafeParse`),两版 zod 同答
|
|
70
|
+
const judged = guardedSafeParse(() => WorkersConfig.safeParse({ workers: [row] }, { error: (iss) => safeIssueMessage(iss) }));
|
|
71
|
+
if (!judged.ok)
|
|
72
|
+
return { field: [], reason: `${SUBJECT[form]} is not a valid WorkerSpec — a value could not be read during validation` };
|
|
73
|
+
const verdict = judged.value;
|
|
24
74
|
if (verdict.success)
|
|
25
75
|
return undefined;
|
|
26
76
|
const issues = verdict.error.issues;
|
package/dist/workers-rows.js
CHANGED
|
@@ -15,29 +15,57 @@
|
|
|
15
15
|
* web-admin 在列表里标红点名 `field` / `reason`。拒因只点名字段、不回显值。
|
|
16
16
|
*/
|
|
17
17
|
import { outgoingPath, redactSecrets } from "./config-fns.js";
|
|
18
|
+
import { appendOwn, dataDescriptor, ownDeclaredValueOf, ownElementsOf, ownEntriesOf } from "./own-key-read.js";
|
|
18
19
|
import { isJsonArray, isPlainJsonObject } from "./plain-json-object.js";
|
|
19
20
|
import { workerRowVerdict } from "./worker-row-verdict.js";
|
|
21
|
+
/**
|
|
22
|
+
* 扣下坏行后的文档:调用方文档的其余自有键 + 换掉的 `workers`。**不对调用方的整份文档做展开**(`{ ...raw }` 会对它做 `[[OwnPropertyKeys]]` + 逐键 `[[Get]]`:无关键上会抛的 getter / `ownKeys` 陷阱
|
|
23
|
+
* 把嵌入方自己抛的值带出调用)—— 其余键经内核的 `ownEntriesOf` 读(整容器律:每个自有串键一份描述符、只从描述符取值,全或无):**其余键里只要有一个读不成纯数据**(访问器 / 隐藏键)
|
|
24
|
+
* 或整份读不出(`ownKeys` / `getOwnPropertyDescriptor` 陷阱抛)⇒ 其余键**一个都不带出**,只剩 `workers`;符号键从不带出(内核只认串键)。workers 域只有 `workers` 一个键,
|
|
25
|
+
* 其余键本来就是未知键(读侧剥掉、只进未知键告警),所以这一答只影响那条告警点名哪些键。交出的是寻常对象。
|
|
26
|
+
*/
|
|
27
|
+
function withWorkers(raw, kept) {
|
|
28
|
+
const doc = {};
|
|
29
|
+
const entries = ownEntriesOf(raw);
|
|
30
|
+
// 键序同展开(`{ ...raw, workers: kept }`):`workers` 留在它原来的位置
|
|
31
|
+
if (entries.ok)
|
|
32
|
+
for (const [key, value] of entries.value)
|
|
33
|
+
Object.defineProperty(doc, key, dataDescriptor(key === "workers" ? kept : value));
|
|
34
|
+
if (!Object.hasOwn(doc, "workers"))
|
|
35
|
+
Object.defineProperty(doc, "workers", dataDescriptor(kept));
|
|
36
|
+
return doc;
|
|
37
|
+
}
|
|
20
38
|
/**
|
|
21
39
|
* 逐行读一份 workers 域**原始**文档(`{ workers: [...] }`)。不是这个形 ⇒ 原样返回、零扣下(判形是 `parseDomain` 的事)。
|
|
22
40
|
* 规则见文件头。
|
|
23
41
|
*/
|
|
24
42
|
export function readWorkersRows(raw) {
|
|
25
|
-
|
|
43
|
+
// 读调用方的对象一律经内核(一份描述符里取值,不问 `get` 陷阱;原型链上被污染的 `workers` / `name` 不是文档里写着的):
|
|
44
|
+
// · `workers` 键与每行的 `name` —— 严归类(逐键一次描述符,键缺席时再问一次 `has`;访问器 / 隐藏键 ⇒ 读不成纯数据);
|
|
45
|
+
// · `workers` 数组的元素 —— 按校验器解析数组的读法(内核的 `ownElementsOf`:只看下标键,数据下标取值、隐藏下标照读、访问器下标调它自己的 getter 一次;挂在数组上的非下标键不看)。
|
|
46
|
+
// `workers` 读不成纯数据 / 元素读不出(结构陷阱抛、下标的 getter 抛)⇒ 「不是这个形」,原样放行交整域读侧判(不按条丢:丢一行 = 对账方把那只 worker 当作已撤销);行的 `name` 读不出 ⇒ 「认不出名字」,该行原样留在 doc
|
|
47
|
+
if (!isPlainJsonObject(raw))
|
|
48
|
+
return { doc: raw, held: [] };
|
|
49
|
+
const workers = ownDeclaredValueOf(raw, "workers");
|
|
50
|
+
if (!workers.ok || !isJsonArray(workers.value))
|
|
51
|
+
return { doc: raw, held: [] };
|
|
52
|
+
const rows = ownElementsOf(workers.value);
|
|
53
|
+
if (!rows.ok)
|
|
26
54
|
return { doc: raw, held: [] };
|
|
27
|
-
const rows = raw.workers;
|
|
28
55
|
const kept = [];
|
|
29
56
|
const held = [];
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
57
|
+
for (const [index, row] of rows.value) {
|
|
58
|
+
const name = isPlainJsonObject(row) ? ownDeclaredValueOf(row, "name") : undefined;
|
|
59
|
+
if (!isPlainJsonObject(row) || name === undefined || !name.ok || typeof name.value !== "string") {
|
|
60
|
+
appendOwn(kept, row); // 认不出名字:整域读侧判(这一读口的追加都走定义语义:`push` 会被继承的数字键 setter 吞掉)
|
|
61
|
+
continue;
|
|
34
62
|
}
|
|
35
63
|
const v = workerRowVerdict(row, "stored");
|
|
36
64
|
// 坐标与拒因都走出门那一道:issue 路径里的 Record 键是用户写的(例:一个不合法的 env 键名可能就是粘错位置的凭据)。
|
|
37
65
|
if (v === undefined)
|
|
38
|
-
kept
|
|
66
|
+
appendOwn(kept, row);
|
|
39
67
|
else
|
|
40
|
-
held
|
|
41
|
-
}
|
|
42
|
-
return held.length === 0 ? { doc: raw, held } : { doc:
|
|
68
|
+
appendOwn(held, { name: name.value, index, field: outgoingPath(v.field), reason: redactSecrets(v.reason), original: row });
|
|
69
|
+
}
|
|
70
|
+
return held.length === 0 ? { doc: raw, held } : { doc: withWorkers(raw, kept), held };
|
|
43
71
|
}
|
package/dist/zod-unwrap.d.ts
CHANGED
|
@@ -9,3 +9,9 @@ import { z } from "zod";
|
|
|
9
9
|
* 不是变换的那一侧。两侧都是 schema 的管道(`a.pipe(b)`)不是包装:到此为止(按它本身的形判,认不出就不抢救)。
|
|
10
10
|
* `.refine()` / `.superRefine()` 在 zod 4 里不是包装层(判据挂在同一只 schema 上),无须展开。 */
|
|
11
11
|
export declare function unwrapSchema(schema: z.ZodType): z.ZodType;
|
|
12
|
+
/** 剥一层包装:`wrapper` = `.optional()` 一类(`.unwrap()`);`preprocess` = `z.preprocess(f, schema)`(变换在**输入**侧,先于里面的 schema);`postprocess` = `.transform(f)`(变换在输出侧)。不是包装 ⇒ `undefined`。
|
|
13
|
+
* `unwrapSchema` 把三种都一视同仁地剥掉(「条目能不能单独解析」与变换无关);要区分的读者(按声明键投影:输入侧的变换会看到整个值,投影不了)用它。 */
|
|
14
|
+
export declare function unwrapOnce(cur: z.ZodType): {
|
|
15
|
+
readonly next: z.ZodType;
|
|
16
|
+
readonly via: "wrapper" | "preprocess" | "postprocess";
|
|
17
|
+
} | undefined;
|
package/dist/zod-unwrap.js
CHANGED
|
@@ -12,14 +12,21 @@ export function unwrapSchema(schema) {
|
|
|
12
12
|
let cur = schema;
|
|
13
13
|
// 有界:包装层数是 schema 作者写出来的常数,8 层远超实际(防被畸形 schema 拖住)。
|
|
14
14
|
for (let i = 0; i < 8; i++) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
else if (cur instanceof z.ZodPipe && cur.in instanceof z.ZodTransform)
|
|
18
|
-
cur = cur.out;
|
|
19
|
-
else if (cur instanceof z.ZodPipe && cur.out instanceof z.ZodTransform)
|
|
20
|
-
cur = cur.in;
|
|
21
|
-
else
|
|
15
|
+
const step = unwrapOnce(cur);
|
|
16
|
+
if (step === undefined)
|
|
22
17
|
return cur;
|
|
18
|
+
cur = step.next;
|
|
23
19
|
}
|
|
24
20
|
return cur;
|
|
25
21
|
}
|
|
22
|
+
/** 剥一层包装:`wrapper` = `.optional()` 一类(`.unwrap()`);`preprocess` = `z.preprocess(f, schema)`(变换在**输入**侧,先于里面的 schema);`postprocess` = `.transform(f)`(变换在输出侧)。不是包装 ⇒ `undefined`。
|
|
23
|
+
* `unwrapSchema` 把三种都一视同仁地剥掉(「条目能不能单独解析」与变换无关);要区分的读者(按声明键投影:输入侧的变换会看到整个值,投影不了)用它。 */
|
|
24
|
+
export function unwrapOnce(cur) {
|
|
25
|
+
if (cur instanceof z.ZodOptional || cur instanceof z.ZodNullable || cur instanceof z.ZodDefault || cur instanceof z.ZodPrefault || cur instanceof z.ZodCatch)
|
|
26
|
+
return { next: cur.unwrap(), via: "wrapper" };
|
|
27
|
+
if (cur instanceof z.ZodPipe && cur.in instanceof z.ZodTransform)
|
|
28
|
+
return { next: cur.out, via: "preprocess" };
|
|
29
|
+
if (cur instanceof z.ZodPipe && cur.out instanceof z.ZodTransform)
|
|
30
|
+
return { next: cur.in, via: "postprocess" };
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
package/docs/API-SURFACE.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
> 每次全量重算并逐名比对 —— 加 / 删 / 改形一个导出而不重生成本档 ⇒ 红。导出面的每次变动因此以本档的 diff 出现在评审里。
|
|
5
5
|
> 形:`value` = 运行期拿得到的值;`type` = 只在类型层;`value+type` = 同名的值与类型(zod schema 与它推出的类型)。
|
|
6
6
|
|
|
7
|
-
子路径 24 条(资产出口 `./package.json` / `./fleet-paths.json` 不是模块,不列),导出名合计
|
|
7
|
+
子路径 24 条(资产出口 `./package.json` / `./fleet-paths.json` 不是模块,不列),导出名合计 1396 个(同名在多条子路径上各计一次)。
|
|
8
8
|
|
|
9
|
-
## `.`(
|
|
9
|
+
## `.`(708)
|
|
10
10
|
|
|
11
11
|
- `ABSOLUTE_HOST_PATH_MAX` — value
|
|
12
12
|
- `ACCESS_TOKEN_TTL_SECONDS` — value
|
|
@@ -56,7 +56,9 @@
|
|
|
56
56
|
- `ConfigChangeHookInput` — value
|
|
57
57
|
- `ConfigPath` — type
|
|
58
58
|
- `ConfigReader` — type
|
|
59
|
+
- `CredentialHandleAnswer` — value+type
|
|
59
60
|
- `CredentialParamName` — type
|
|
61
|
+
- `CredentialResolveRequest` — value+type
|
|
60
62
|
- `CrossSessionInboundSetting` — value
|
|
61
63
|
- `CrossSessionInboundSettingValue` — type
|
|
62
64
|
- `CrossSessionInboundValue` — type
|
|
@@ -151,6 +153,7 @@
|
|
|
151
153
|
- `FEEDBACK_DESCRIPTION_MAX_CHARS` — value
|
|
152
154
|
- `FEEDBACK_TRANSCRIPT_MAX_JSON_CHARS` — value
|
|
153
155
|
- `FEEDBACK_V1_PATH` — value
|
|
156
|
+
- `FLEET_ADVERTISE_ADDRESS_ENV` — value
|
|
154
157
|
- `FLEET_GENERATION_ENV` — value
|
|
155
158
|
- `FLEET_LIVE_PATHS` — value
|
|
156
159
|
- `FLEET_PATHS` — value
|
|
@@ -280,7 +283,9 @@
|
|
|
280
283
|
- `OAuthErrorCode` — type
|
|
281
284
|
- `OAuthErrorResponse` — value+type
|
|
282
285
|
- `PARSE_TRANSPARENT_KEYS` — value
|
|
286
|
+
- `PATH_BASE_URL_FORBIDDEN_PARTS` — value
|
|
283
287
|
- `PLUGIN_ORIGIN` — value
|
|
288
|
+
- `PRINCIPAL_INC_CLAIM` — value
|
|
284
289
|
- `PRINCIPAL_MAX_LENGTH` — value
|
|
285
290
|
- `PRIVATE_KEY_PEM_HEADER` — value
|
|
286
291
|
- `PROBE_CPU_CORES_MAX` — value
|
|
@@ -316,6 +321,7 @@
|
|
|
316
321
|
- `PreModelSwitchHookInput` — value+type
|
|
317
322
|
- `PreToolUseHookInput` — value
|
|
318
323
|
- `PrincipalCapsWire` — value+type
|
|
324
|
+
- `PrincipalIncarnation` — value+type
|
|
319
325
|
- `PrincipalOrgMemoryWire` — value+type
|
|
320
326
|
- `ProjectContextItem` — value+type
|
|
321
327
|
- `ProjectContextItemKind` — type
|
|
@@ -377,6 +383,13 @@
|
|
|
377
383
|
- `RostersConfig` — value+type
|
|
378
384
|
- `RoutingVerdict` — type
|
|
379
385
|
- `SAFETY_MERGE_SPEC` — value
|
|
386
|
+
- `SANDBOX_GIT_MAX_ORIGINS` — value
|
|
387
|
+
- `SANDBOX_GIT_ORIGIN_REASONS` — value
|
|
388
|
+
- `SANDBOX_GIT_ORIGIN_STATES` — value
|
|
389
|
+
- `SANDBOX_GIT_ORIGIN_VERDICTS` — value
|
|
390
|
+
- `SANDBOX_GIT_PERMANENCE` — value
|
|
391
|
+
- `SANDBOX_GIT_REFUSALS` — value
|
|
392
|
+
- `SANDBOX_GIT_REFUSAL_ERRORS` — value
|
|
380
393
|
- `SCOPES_V1_PATHS` — value
|
|
381
394
|
- `SCOPE_CLAIM` — value
|
|
382
395
|
- `SCOPE_ID_REGEX` — value
|
|
@@ -403,6 +416,19 @@
|
|
|
403
416
|
- `SUBMIT_IDEMPOTENCY_KEY` — value
|
|
404
417
|
- `SafetyMergeCategory` — type
|
|
405
418
|
- `SafetyMergeMember` — type
|
|
419
|
+
- `SandboxGitConfig` — value+type
|
|
420
|
+
- `SandboxGitConnectUrl` — value+type
|
|
421
|
+
- `SandboxGitCredentialAnswer` — value+type
|
|
422
|
+
- `SandboxGitCredentialRefusal` — value+type
|
|
423
|
+
- `SandboxGitCredentialRequest` — value+type
|
|
424
|
+
- `SandboxGitOrigin` — value+type
|
|
425
|
+
- `SandboxGitOriginAnswer` — value+type
|
|
426
|
+
- `SandboxGitOriginEntry` — value+type
|
|
427
|
+
- `SandboxGitOriginList` — value+type
|
|
428
|
+
- `SandboxGitOriginReason` — type
|
|
429
|
+
- `SandboxGitOriginState` — type
|
|
430
|
+
- `SandboxGitPermanence` — type
|
|
431
|
+
- `SandboxGitRefusalError` — type
|
|
406
432
|
- `ScenarioAssignments` — value+type
|
|
407
433
|
- `ScenarioConfig` — value+type
|
|
408
434
|
- `ScenarioEntry` — value+type
|
|
@@ -589,6 +615,7 @@
|
|
|
589
615
|
- `isRetiredDomainName` — value
|
|
590
616
|
- `isRole` — value
|
|
591
617
|
- `isRoutable` — value
|
|
618
|
+
- `isSandboxGitOrigin` — value
|
|
592
619
|
- `isSchedulerRecord` — value
|
|
593
620
|
- `isStringArray` — value
|
|
594
621
|
- `isStringRecord` — value
|
|
@@ -619,6 +646,7 @@
|
|
|
619
646
|
- `parseSchedulerStore` — value
|
|
620
647
|
- `parseWebAdminCredentialFile` — value
|
|
621
648
|
- `parseWebAdminSessionUrl` — value
|
|
649
|
+
- `pathBaseUrlFlaws` — value
|
|
622
650
|
- `pickInstance` — value
|
|
623
651
|
- `projectWarning` — value
|
|
624
652
|
- `promptArtifactFor` — value
|
|
@@ -1256,7 +1284,7 @@
|
|
|
1256
1284
|
- `interpolateHookEnvVars` — value
|
|
1257
1285
|
- `stopAttributionText` — value
|
|
1258
1286
|
|
|
1259
|
-
## `./fleet`(
|
|
1287
|
+
## `./fleet`(84)
|
|
1260
1288
|
|
|
1261
1289
|
- `AggregatedPrincipalUsage` — type
|
|
1262
1290
|
- `CapabilityReading` — type
|
|
@@ -1280,6 +1308,7 @@
|
|
|
1280
1308
|
- `ENGINE_SIGNAL_KEY` — value
|
|
1281
1309
|
- `EngineDraining` — value+type
|
|
1282
1310
|
- `EngineSignal` — value+type
|
|
1311
|
+
- `FLEET_ADVERTISE_ADDRESS_ENV` — value
|
|
1283
1312
|
- `FLEET_GENERATION_ENV` — value
|
|
1284
1313
|
- `FLEET_LIVE_PATHS` — value
|
|
1285
1314
|
- `FLEET_PATHS` — value
|
|
@@ -1368,7 +1397,7 @@
|
|
|
1368
1397
|
- `nextPollInterval` — value
|
|
1369
1398
|
- `normalizeUserCode` — value
|
|
1370
1399
|
|
|
1371
|
-
## `./api/auth-bridge`(
|
|
1400
|
+
## `./api/auth-bridge`(23)
|
|
1372
1401
|
|
|
1373
1402
|
- `AUTH_BRIDGE_ALGS` — value
|
|
1374
1403
|
- `AUTH_BRIDGE_ERROR_CODES` — value
|
|
@@ -1379,7 +1408,9 @@
|
|
|
1379
1408
|
- `DEFAULT_JWKS_REFRESH_MIN_INTERVAL_SEC` — value
|
|
1380
1409
|
- `DEFAULT_OFFLINE_GRACE_SEC` — value
|
|
1381
1410
|
- `JwksCacheSnapshot` — type
|
|
1411
|
+
- `PRINCIPAL_INC_CLAIM` — value
|
|
1382
1412
|
- `PRINCIPAL_MAX_LENGTH` — value
|
|
1413
|
+
- `PrincipalIncarnation` — value+type
|
|
1383
1414
|
- `VerifiedIdentity` — value+type
|
|
1384
1415
|
- `VerifierConfig` — value+type
|
|
1385
1416
|
- `VerifierConfigInput` — type
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
> S-570 收车档;3.0.0 之后的下一次真实改动,请同一批把这份文档也带上,别再停摆。**7.0.0**(M-R2 WorkerSpec 结构块)的
|
|
8
8
|
> 三方迁移句在 §0.2,`remoteExec` 删 `remote-docker` 在 §5。**8.0.0**(一致性门第四条腿 + 表态律 + CLI `--check`)在 §0.3。
|
|
9
9
|
> **11.0.0** 的持久面(`runtime` 域退役、读侧兼容臂退役、一次性迁移族 `./one-time-migrations`)在 §0.4。
|
|
10
|
+
> **14.7.0** 的沙箱 git 凭据平面(取值口 wire 型、有效配置块 `sandboxGit`、`VerifiedIdentity.principalInc`)在 §12。
|
|
11
|
+
> **14.7.0** 的路径基址判官(`PATH_BASE_URL_FORBIDDEN_PARTS` / `pathBaseUrlFlaws`)与公告地址 env 名(`FLEET_ADVERTISE_ADDRESS_ENV`)在 §13。
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
|
@@ -236,6 +238,7 @@ server 直接拒启,不是静默降级。上一代 `SEMA_REGISTRY_*` 八名(`URL
|
|
|
236
238
|
命令行 `migrate` 与这只函数同一份实现;写盘用的就是本包那一只原子写器(契约文档新建 0o644、已有的沿用原模式、符号链接保留)。
|
|
237
239
|
手里已有存量文档原文、不经目录的消费方(例:命令行壳按层读 `settings` 里的 models 域,要的是「引擎起服那一次迁移之后这份文档整域读不读得进」)调同一个内核的同步口 `migrateConfigDocuments(docs, { documents })`(14.5.0,`./node`):
|
|
238
240
|
同一个闭集的无 io 形(`refused` ⇒ 引擎同样不写回、整域落缺省;**反向不成立** —— 引擎对整个目录一判,别的文档被拒也会让整目录不写,单层单域的 `noop` / `migrated` 不保证引擎那一次放行;`docs` 是壳的写手要的迁移后那一份)。一层一次调用;**别自己把 `migrateStoredDocuments` 与 `parseDomain` 按这个顺序再组装一遍**。
|
|
241
|
+
- **路径基址判官与公告地址**:「别人要往它后面拼路径的基址」座位(中心基址三席、公告地址、会话链接基址)的禁用成分集 `PATH_BASE_URL_FORBIDDEN_PARTS` 与判官 `pathBaseUrlFlaws` 在本包,公告地址的 env 名是 `FLEET_ADVERTISE_ADDRESS_ENV`;**别手写 env 名、别手抄那三个词** —— 两方读法见 §13。
|
|
239
242
|
- **会话网页链接**:要给用户一个 web-admin 里的会话链接,调 `webAdminSessionUrl(webBaseUrl, { worker, sessionId })`(`webBaseUrl` 取引擎 `/health` 自报的人用界面根 URL,
|
|
240
243
|
`worker` 取引擎向 web-admin 登记用的 worker 名),得到 `<webBaseUrl>/chat?agent=<worker>&session=<sessionId>`;**别按地址形手拼** —— 路由属于 web-admin,模板与读回的
|
|
241
244
|
`parseWebAdminSessionUrl(link)` 同在本包,路径与参数名只此一份。两位必填:只带 `session` 的链接会落到页面自己挑的 worker 上、可能找不到会话。
|
|
@@ -283,3 +286,178 @@ server 直接拒启,不是静默降级。上一代 `SEMA_REGISTRY_*` 八名(`URL
|
|
|
283
286
|
这份档里重复展开。
|
|
284
287
|
- 今天真接了这道门的:server(`wire` + `localRoot` 两条读腿)、管理面(`domains` 往返腿,钉在 6.x);cli 显式拒接 kit 读腿
|
|
285
288
|
(壳不走上游 effective 读腿),client-core 零 import。8.0.0 起两家接线方都要对四条腿逐条表态(§0.3)。
|
|
289
|
+
|
|
290
|
+
## 12. 沙箱 git 凭据平面(14.7.0 起)—— web-admin 与 server 两方的读法
|
|
291
|
+
|
|
292
|
+
沙箱里的 git 用**成员本人**的凭据:凭据住在 web-admin 的凭据库,引擎的数据面按 run 的身份向取值口取,只在该成员自己的沙箱里经代理使用,永不进模型可读的容器。
|
|
293
|
+
本节说**本包发什么、两方各自怎么读**。本包只有**形与词表**(纯、浏览器安全,零 IO);鉴权、委托、活表复核、行 MAC、租约与续期都是两方自己的事(§12.9 逐条列出)。
|
|
294
|
+
|
|
295
|
+
### 12.1 本包发什么
|
|
296
|
+
|
|
297
|
+
| 件 | 在哪 | 是什么 |
|
|
298
|
+
|---|---|---|
|
|
299
|
+
| `isSandboxGitOrigin` · `SandboxGitOrigin` · `SandboxGitOriginList` · `SANDBOX_GIT_MAX_ORIGINS` | 主桶(`src/sandbox-git.ts`) | origin 的规范形判官与 zod 形;一个 origin 就是它自己的 WHATWG origin |
|
|
300
|
+
| `SandboxGitConfig` · `SandboxGitOriginEntry` · `SandboxGitConnectUrl` | 主桶 | 有效配置块 `sandboxGit` 的形 |
|
|
301
|
+
| `SandboxGitCredentialRequest` · `CredentialHandleAnswer` · `CredentialResolveRequest` · `SandboxGitCredentialAnswer` · `SandboxGitOriginAnswer` · `SandboxGitCredentialRefusal` | 主桶(`src/api/credentials.ts`,不开子路径) | 取值口两步的 wire 型 |
|
|
302
|
+
| `SANDBOX_GIT_ORIGIN_VERDICTS` → `SANDBOX_GIT_ORIGIN_STATES` · `SANDBOX_GIT_ORIGIN_REASONS`;`SANDBOX_GIT_REFUSALS` → `SANDBOX_GIT_REFUSAL_ERRORS`;`SANDBOX_GIT_PERMANENCE` | 主桶 | 三张词表(每个词只在 `src/api/credentials.ts` 里拼一次;状态词、原因词、错误词表与类型全由表派生) |
|
|
303
|
+
| `PRINCIPAL_INC_CLAIM`(`"sub_inc"`) · `PrincipalIncarnation` · `VerifiedIdentity.principalInc` | 主桶与 `./api/auth-bridge` | 令牌里的化身号声明 |
|
|
304
|
+
| `EffectiveWire.sandboxGit?: unknown` | 主桶(`types`) | `/effective` 载荷上的非域顶层键,逐字承运 |
|
|
305
|
+
|
|
306
|
+
全部是加性(新导出 / 可选键),既有导出对既有输入的答案不变。
|
|
307
|
+
|
|
308
|
+
### 12.2 有效配置块 `sandboxGit`
|
|
309
|
+
|
|
310
|
+
```json
|
|
311
|
+
{
|
|
312
|
+
"sandboxGit": {
|
|
313
|
+
"origins": [
|
|
314
|
+
{ "origin": "https://git.example.com:9999", "connectUrl": "https://console.example.com/connect/git" },
|
|
315
|
+
{ "origin": "http://git.legacy.example:8080", "connectUrl": "https://console.example.com/connect/git" }
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
- **非域顶层键**:web-admin 按部署登记册**投影**,不是存储域 —— `buildEffective` 不产它、`FileConfigStore` 没有 `sandboxGit.json`(单机模式没有这个平面)。**可选、无默认**:键缺席 = 这个部署没有投影这一块。
|
|
322
|
+
- `readEffectiveWire` 对它走 open-world:**逐字承运,不校验、不丢**(`EffectiveWire.sandboxGit` 是 `unknown`)。**判它的唯一座位是 `SandboxGitConfig`**:消费方在用之前对 `wire.sandboxGit` 跑 `safeParse`。
|
|
323
|
+
- `origins` ≤ 16(`SANDBOX_GIT_MAX_ORIGINS`)、按 `origin` 两两不同,空表合法;解析剥未知键(前向兼容)。
|
|
324
|
+
- **规范形只有一条律**:`origin` 逐字等于 `new URL(origin).origin`,且 scheme ∈ {http, https}。小写 host、去缺省端口(443 / 80)、无尾斜杠、无 userinfo / 路径 / 查询 / 片段都是它的推论 ——
|
|
325
|
+
凡 WHATWG 会改写的串(大写、缺省端口、IPv4 简写、百分号编码的 host、前后空白……)都不是规范形。**origin 不表达子路径部署**:`https://host/gitea` 不是 origin,判官拒;本包没有「削成 origin」的规范化器(把运维写的路径静默削掉会把凭据送到他没写的地方)。
|
|
326
|
+
- 🔴 **块里 http origin 可读**。它为什么送不出凭据是**逐 origin 应答里的一个词**(§12.4 第 1 行 `insecure_transport`)与能力读数里的一个词,不是块的校验拒:块若因一个 http origin 整块不可读,同块里的 https origin 一并失效,「逐 origin 说拒因」就无从谈起。
|
|
327
|
+
http origin 只配路由、永不取值,是 server 的事。
|
|
328
|
+
- `connectUrl` = 控制台「连接 Gitea(git)」页的绝对 **https** URL(`SandboxGitConnectUrl`:`NON_SECRET_URL_NO_MIGRATION` 的判据 + https)。
|
|
329
|
+
|
|
330
|
+
### 12.3 取值口两步(wire 型)
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
① POST /api/v1/credentials/handles 请求 SandboxGitCredentialRequest → 200 CredentialHandleAnswer { handle, expiresAt }
|
|
334
|
+
② POST /api/v1/credentials/resolve 请求 CredentialResolveRequest { handle } → 200 SandboxGitCredentialAnswer
|
|
335
|
+
→ 非 2xx 体 SandboxGitCredentialRefusal { error, permanence, message }
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
```json
|
|
339
|
+
{ "kind": "sandbox_git", "principal": "alice", "principalInc": "<化身号>", "scope": "team-android",
|
|
340
|
+
"origins": ["https://git.example.com:9999"], "sid": "<会话 id,审计标签>" }
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
- `kind` 是字面量 `"sandbox_git"`;`principal` 的长度界同令牌 `sub`(`PRINCIPAL_MAX_LENGTH`);`principalInc` 就是 `PrincipalIncarnation`(与令牌 `sub_inc`、`VerifiedIdentity.principalInc` 是**同一只 schema 对象**);
|
|
344
|
+
`scope` 非空串(与 `readTokenScope` 读令牌声明同一条规则);`origins` 1–16 个、规范形、两两不同 —— **http origin 也收**(中心对它答判定序第 1 行,请求形不抢先拒)。
|
|
345
|
+
- 应答(200)里的 `principal` / `principalInc` / `scope` 是请求的**回显**;`answeredAt`(应答时刻)、`cacheUntil`(句柄到期)与 `active` 行里的 `expiresAt` 是**同一只钟**(中心的)给的毫秒:收方只该用它们的**差**,不拿它们和自己的钟比。
|
|
346
|
+
- 每个 origin 一行 `SandboxGitOriginAnswer`,按 `state` 判别。`active` 独有 `credentialId` `version` `username` `secret` `expiresAt`(OAuth 令牌:到期毫秒;个人访问令牌:`null`);`needs_reauth` 行带 `credentialId`;其余只有 `origin` / `state` / `reason`。
|
|
347
|
+
**解析一律剥未知键**,`secret` 只在 `active` 臂的形里 —— 别的臂收到也剥掉。`secret` 是应答里唯一的秘密位;`credentialId` / `version` / `auditId` 是不带值的审计位,日志里记它们、不记 `secret`。
|
|
348
|
+
|
|
349
|
+
### 12.4 逐 origin 判定序表(`SANDBOX_GIT_ORIGIN_VERDICTS`,11 行,序即判定序)
|
|
350
|
+
|
|
351
|
+
每个 origin 独立判,**首条命中即答**,一个 origin 的结果不影响别的 origin。`state` 六词、`reason` 十词都由这张表派生。
|
|
352
|
+
|
|
353
|
+
| 序 | 条件(什么事实命中) | `state` | `reason` |
|
|
354
|
+
|---|---|---|---|
|
|
355
|
+
| 1 | origin 的 scheme 不是 `https` | `insecure_transport` | `not_https` |
|
|
356
|
+
| 2 | 本部署本 scope 的登记册里没有这个 origin 的 git 应用 | `not_offered` | `not_in_registry` |
|
|
357
|
+
| 3 | 选行键下没有行 | `not_connected` | `no_row` |
|
|
358
|
+
| 4 | 行 `status = revoked`(吊销后无密文、留作审计锚的行) | `not_connected` | `revoked` |
|
|
359
|
+
| 5 | 行 `status = revoking` | `needs_reauth` | `revoking` |
|
|
360
|
+
| 6 | 行 `status = suspended` | `needs_reauth` | `suspended` |
|
|
361
|
+
| 7 | 行 `status = needs_reauth` | `needs_reauth` | `row_needs_reauth` |
|
|
362
|
+
| 8 | 行 `active`,但行 MAC 或解密 AAD 校验不过 | `needs_reauth` | `integrity_failed` |
|
|
363
|
+
| 9 | 行 `active`、OAuth、剩余寿命 < 600 s,单飞刷新得上游 `invalid_grant` 或其余 4xx(`invalid_grant` 时行同时置 `needs_reauth`) | `needs_reauth` | `refresh_rejected` |
|
|
364
|
+
| 10 | 同 9,刷新遇网络错 / 5xx / 超时,且现令牌剩余 < 60 s | `temporarily_unavailable` | `refresh_unavailable` |
|
|
365
|
+
| 11 | 其余(行 `active`;不需刷新,或刷新成功,或刷新暂不可用但现令牌剩余 ≥ 60 s) | `active` | — |
|
|
366
|
+
|
|
367
|
+
选行键 = (scope, 属主键 = 主体 + 化身号, `sandbox_git`, origin);「条件」列是 web-admin 的判定逻辑,**不进运行期表**(本包不知道行状态、登记册、MAC)。状态 × 原因的配对由表定:`SandboxGitOriginAnswer` 每个状态一个臂,臂里 `reason` 的值域 = 表里该状态的行,原因贴在不属于它的状态上一律拒(状态 × 原因的整个叉积里,恰好表里那 10 对加上无原因的 `active` 被收下)。
|
|
368
|
+
|
|
369
|
+
### 12.5 整次拒答表(`SANDBOX_GIT_REFUSALS`)
|
|
370
|
+
|
|
371
|
+
体 = `{ "error", "permanence", "message" }`。`permanence` 两词:`terminal` = 不按定时重试;`transient` = 退避重试。**一个错误词的 permanence 是固定的**,拒体里再带一份只为收方不必查表 —— 两处不一致是畸形应答(`SandboxGitCredentialRefusal` 拒)。
|
|
372
|
+
|
|
373
|
+
| `error` | HTTP | `permanence` | 说明 |
|
|
374
|
+
|---|---|---|---|
|
|
375
|
+
| `caller_not_admitted` | 401 / 403 | terminal | 调用方不是被承认的舰队 worker |
|
|
376
|
+
| `scope_mismatch` | 403 | terminal | 请求的 scope 不等于调用方凭据的 scope |
|
|
377
|
+
| `incarnation_mismatch` | 403 | terminal | 请求的化身号不等于该主体当前的化身号 |
|
|
378
|
+
| `request_invalid` | 400 | terminal | 请求形不合(含 `principalInc` 缺或空) |
|
|
379
|
+
| `principal_not_live` | 403 | terminal | 主体活表复核不过 |
|
|
380
|
+
| `delegation_required` | 403 | terminal | 没有活的委托 |
|
|
381
|
+
| `vault_disabled` | 503 | terminal | 凭据库关着 |
|
|
382
|
+
| `vault_frozen` | 503 | terminal | 凭据库冻结 |
|
|
383
|
+
| `handle_invalid` | 401 | transient | 句柄验不过 / 已用 / 已过期 |
|
|
384
|
+
| `vault_unavailable` | 503 | transient | 凭据库暂不可用 |
|
|
385
|
+
|
|
386
|
+
收方怎么处置某个词(例如哪些 terminal 可由用户动作恢复、哪些不可恢复)是收方的状态机,不在本包里。**错误词不在闭集 ⇒ 畸形应答,不是「当 transient 重试」。**
|
|
387
|
+
|
|
388
|
+
### 12.6 `VerifiedIdentity.principalInc` 与令牌声明 `sub_inc`
|
|
389
|
+
|
|
390
|
+
同名主体删号重建之后是**另一个人**:`sub` 只命名一个槽位,化身号才区分「同一个名字」与「同一个人」。
|
|
391
|
+
|
|
392
|
+
- `toVerifiedIdentity` 读声明 `PRINCIPAL_INC_CLAIM`(`sub_inc`):**在场且是非空串 ⇒ `identity.principalInc` 原样**(不 trim、不折大小写);**缺席 ⇒ 读出形里不铸键**(从不读成 `0` / 空串 / 别的占位);
|
|
393
|
+
**在场而不是非空串(数字含 0 / 空串 / `null` / 布尔 / 对象 / 数组)⇒ 该令牌 `malformed`**(与 `sub`、`iat` 同律:声明形是垃圾,不降级成缺席 —— 降级会把坏掉的签发方读成「没有化身号」)。
|
|
394
|
+
- **缺化身号不是本契约的拒**:读方要化身号而令牌没有时,答什么是读方的事(server 把它记成「化身号未记录」,取值一律不放)。
|
|
395
|
+
- 行为面唯一变化:此前令牌带了 `sub_inc` 声明也被忽略;从本版起它在场而形不对就拒。
|
|
396
|
+
|
|
397
|
+
### 12.7 web-admin 做什么
|
|
398
|
+
|
|
399
|
+
- **铸令牌**:用 `PRINCIPAL_INC_CLAIM` 铸 `sub_inc`(值 = 会话建立时绑定的化身号,非空串)。「会话化身 = 用户行当前化身」的签发不变量是 web-admin 的,不是本包的。
|
|
400
|
+
- **投影 `sandboxGit`**:`origin` 必须已经是规范形(`isSandboxGitOrigin`),`connectUrl` 是 https;自己的出口先 `SandboxGitConfig.parse` 再发,拒掉的是运维配置的问题,不要静默改写。
|
|
401
|
+
- **收请求**:`SandboxGitCredentialRequest.safeParse` 不过 ⇒ `request_invalid`。
|
|
402
|
+
- **答应答**:按 `SANDBOX_GIT_ORIGIN_VERDICTS` 的序逐 origin 判,首条命中即答;用 `SandboxGitCredentialAnswer.parse` 过一遍再发(臂的键集错了在自己这里红,不要等收方判畸形)。
|
|
403
|
+
- **答拒**:`permanence` 取自 `SANDBOX_GIT_REFUSALS[error].permanence`,HTTP 状态取表里该词的状态集之一。
|
|
404
|
+
|
|
405
|
+
### 12.8 server 做什么
|
|
406
|
+
|
|
407
|
+
- **读块**:`wire.sandboxGit` 缺席 ⇒ 没有这一块;在场 ⇒ `SandboxGitConfig.safeParse`,不过 ⇒ 当作没有任何 origin,并响亮说(坐标可记,拒句不回显值)。http origin 只配路由、永不取值。
|
|
408
|
+
- **读令牌**:`toVerifiedIdentity` 之后用 `identity.principalInc`;缺 ⇒ 化身号未记录(本契约不拒令牌)。
|
|
409
|
+
- **发请求 / 收应答**:`SandboxGitCredentialRequest` 构造后再发;应答先 `SandboxGitCredentialAnswer.safeParse`,**再**核逐条对应与回显(§12.9);`secret` 只存在于 `active` 行,日志里不出现。
|
|
410
|
+
- **收拒**:体过 `SandboxGitCredentialRefusal` 才算认得;`permanence` 读表(或读体 —— 二者已被形保证相等)。
|
|
411
|
+
- **时刻**:`answeredAt` / `cacheUntil` / `expiresAt` 只取差;不拿它们和 server 自己的钟比。
|
|
412
|
+
|
|
413
|
+
### 12.9 本包不做的(如实)
|
|
414
|
+
|
|
415
|
+
- **应答与请求的逐条对应 / 回显相等**(`origins` 同序同长、`principal` / `principalInc` / `scope` 等于请求)是收方在 `safeParse` 之后要核的事,不在形里。
|
|
416
|
+
- **租约算术与续期状态机**(`cacheUntil` / `expiresAt` − `answeredAt` 的差、封顶、重试退避、「踢」)、哪些 terminal 词可恢复,都是 server 自己的。
|
|
417
|
+
- **取值口的另两种凭据**(`model` / `mcp_static`)的请求与应答形不在本节:它们落地时与 `sandbox_git` 形并成按 `kind` 判别的联合,`sandbox_git` 形不动(`kind` 字面量已经在)。`CredentialHandleAnswer` / `CredentialResolveRequest` 与种类无关,三种共用。
|
|
418
|
+
- **两个端点的路径常量**不在包里(上面的路径是文字,不是导出)。
|
|
419
|
+
- **调用方鉴权、委托、活表复核、行 MAC、冻结**:全是 web-admin 的。
|
|
420
|
+
- **一致性门**:没有新腿 —— `sandboxGit` 是 wire 专属键,走 §11 里 T4 那一条(open-world 逐字承运),既有语料的读数不变。新增两条语料(`c84` 合格块含一个 http origin、`c85` 不合格块):wire 腿都要把块**逐字承运、不出告警**,判它是消费方用 `SandboxGitConfig` 的事 —— 你的 wire 读腿若校验后丢掉坏块,跑语料时会在 `c85` 上红。
|
|
421
|
+
|
|
422
|
+
## 13. 路径基址判官与公告地址 `FLEET_ADVERTISE_ADDRESS`(14.7.0 起)—— web-admin 编排器与 server 两方的读法
|
|
423
|
+
|
|
424
|
+
有一种座位的值是「别人要往它后面拼路径的基址」:中心基址三席(`WEB_ADMIN_ENV.url` / `liveUrl` / `webUrl`,值 `SEMA_WEB_ADMIN_URL` / `SEMA_WEB_ADMIN_LIVE_URL` / `SEMA_WEB_ADMIN_WEB_URL`)、
|
|
425
|
+
fleet 成员对中心公告的可达地址(`FLEET_ADVERTISE_ADDRESS`,中心往它后面拼路径)、会话网页链接的基址(`webAdminSessionUrl` 的第一个参数)。这种座位有同一条规则:
|
|
426
|
+
不许带凭据,也不许带 query / fragment(`http://x?a=1` 拼上 `/v1/…` 是 `http://x?a=1/v1/…`);路径前缀放行(要拼的路径接在前缀后面)。
|
|
427
|
+
本节说**本包发什么、两方各自怎么读**。本包只有**判这种座位的那一只判官、它禁用的成分集与公告地址的 env 名**(纯、浏览器安全,零 IO);值从哪来、占位怎么展开、地址是不是真打得到,都是两方自己的事(§13.4)。
|
|
428
|
+
|
|
429
|
+
### 13.1 本包发什么
|
|
430
|
+
|
|
431
|
+
| 件 | 是什么 |
|
|
432
|
+
|---|---|
|
|
433
|
+
| `PATH_BASE_URL_FORBIDDEN_PARTS` | 「后面要拼路径的基址」座位禁用的 URL 成分,闭集、冻结、判序:`userinfo` · `query` · `fragment`(**策略集,独立于判官词表 `HTTP_URL_PARTS`**:词表说 URL 有哪些成分,本集说这种座位禁哪些;今天碰巧同三词,但不由词表派生,词表加词时要显式裁);这种座位的策略只此一张,没有第二份抄本;包根 |
|
|
434
|
+
| `pathBaseUrlFlaws(url)` | = `httpUrlFlaws(url, PATH_BASE_URL_FORBIDDEN_PARTS)`(本包唯一的 URL 形判官,不另写判法)。合格 ⇒ `[]`;否则按判序交回规则词(`not-http-url` / `userinfo` / `query` / `fragment`),词的规则句取 `httpUrlRule(词)`;答案只有词,不含值的任何片段;包根 |
|
|
435
|
+
| `FLEET_ADVERTISE_ADDRESS_ENV` | 公告地址的 env 名 `"FLEET_ADVERTISE_ADDRESS"`(字面量类型),与 `FLEET_GENERATION_ENV` / `FLEET_SCOPE_ENV` 同文件同形;写的一方和读的一方都 import,不各自拼;包根与 `./fleet` |
|
|
436
|
+
|
|
437
|
+
本包自己的 `webAdminSessionUrl` 已改读这一只判官(读数逐字不变)。判官今天的答案(逐行钉在 `test/path-base-url-forbids-14.7.0.test.ts`):
|
|
438
|
+
|
|
439
|
+
- `http://$(POD_IP):8090` ⇒ `[]`(占位在主机位:`$` `(` `)` 都是合法主机码点);`http://10.0.0.5:8090`、`http://[fd00::1]:8090`、`https://worker.example.com` ⇒ `[]`。
|
|
440
|
+
- `http://[$(POD_IP)]:8090` ⇒ `["not-http-url"]`:方括号里必须是 IPv6 字面量,占位不是 —— **判占位展开之后的值**,不判模板。
|
|
441
|
+
- 路径前缀 `http://10.0.0.5:8090/prefix` ⇒ `[]`(路径不在禁用集里:要拼的路径接在前缀后面)。
|
|
442
|
+
- `…?a=1`(含空 `?`)⇒ `["query"]`;`…#f`(含空 `#`)⇒ `["fragment"]`;`http://user:pw@host`(只有用户名也算)⇒ `["userinfo"]`;三件齐 ⇒ 三个词,按判序。
|
|
443
|
+
- `127.0.0.1:8121`(缺 scheme)、`ftp://x:1`、`file:///etc/passwd`、`data:…`、空串 ⇒ 含 `not-http-url`(`fetch` 认 `file://` / `data:`,配错的地址不许变成读本地文件)。
|
|
444
|
+
|
|
445
|
+
### 13.2 web-admin 编排器做什么
|
|
446
|
+
|
|
447
|
+
- **渲染**:往成员 env 写公告地址时,键名取 `FLEET_ADVERTISE_ADDRESS_ENV`,不手写字面量。k8s 后端写 `http://$(POD_IP):<端口>` 这种形,`$(POD_IP)` 由部署后端展开。
|
|
448
|
+
- **发出前判**:对**展开之后**的值调 `pathBaseUrlFlaws`,长度非 0 就是渲染器自己的配置问题 —— 拒掉并点名规则词(规则句取 `httpUrlRule`),不要静默改写(例如悄悄削掉 query):改写会把地址送到运维没写的地方。
|
|
449
|
+
- **不手抄集**:不要在编排器里再写一遍 `["userinfo", "query", "fragment"]` 或自己的 URL 判法;集与判官只有本包这一份,它与引擎起服时判的是同一个答案。给用户铸会话链接用 `webAdminSessionUrl`,它判基址用的也是这一只。
|
|
450
|
+
|
|
451
|
+
### 13.3 server 做什么
|
|
452
|
+
|
|
453
|
+
- **读 env**:`process.env[FLEET_ADVERTISE_ADDRESS_ENV]`;不手写字面量。缺席或空串(compose 的 `${NAME:-}` 常态)⇒ 没声明地址 —— 这个读法是 server 的,不在判官里(判官对 `""` 答 `not-http-url`)。
|
|
454
|
+
- **判**:非空值调 `pathBaseUrlFlaws`;长度非 0 ⇒ 拒启。运维旋钮律:无条件解析,没接中心的机器也判,形错的值不躺着等哪天生效。拒句点名没过的规则(`httpUrlRule`),**不回显值**(值里可能有凭据)。
|
|
455
|
+
- **中心基址三席同一只**:`WEB_ADMIN_ENV.url` / `liveUrl` / `webUrl` 的值(起服时与请求期)和公告地址都调 `pathBaseUrlFlaws`;server 里原先本地的禁用集副本与公告地址 env 名字面量改读本包后删除,不留第二份。判官读数与改前逐字相同(词与判官同一只)。
|
|
456
|
+
|
|
457
|
+
### 13.4 本包不做的(如实)
|
|
458
|
+
|
|
459
|
+
- **占位展开**(`$(POD_IP)` 等):是部署后端的事,不是本包的;判官看到的永远是一个字符串。
|
|
460
|
+
- **可达性**:地址真不真打得到是运维的话,判官只判形;引擎不自猜可达地址。
|
|
461
|
+
- **缺席 / 空串的处置**:见 §13.3 —— 读的一方自己答。
|
|
462
|
+
- **座位名册**:一个值算不算「后面要拼路径的基址」是读它的一方的事;本包给的是判这种座位的那一只判官,不维护座位清单(§13 开头列的是今天已知的读者)。
|
|
463
|
+
- **不进保留 env 名表**:`FLEET_ADVERTISE_ADDRESS` 与 generation / scope 两只不同 —— 那两只只有渲染器能写,所以进 `RESERVED_WORKER_ENV`;公告地址是运维可以声明的值(渲染器也可以写),`worker.env` 设它照旧不被拒。
|
package/llms-full.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
llms-full.txt — 自包含全文 · 消费方(使用者)视角 · @sema-agent/settings-schema
|
|
3
|
-
重写日期: 2026-10-
|
|
3
|
+
重写日期: 2026-10-25 | 包版本: 14.7.0
|
|
4
4
|
生成方式: 无生成脚本——按当前树 src/*.ts 导出面 + package.json + README/CHANGELOG 手写事实版。
|
|
5
5
|
证据约定: 每条"它怎么工作"的断言附 (文件: 符号) 坐标,刻意不用行号(行号逐版腐烂;符号名由
|
|
6
6
|
typecheck 与 test/package-surface.test.ts、test/docs-hygiene.test.ts 等常驻门钉住)。无证据推断显式标【推断】。
|
|
@@ -297,8 +297,8 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
|
|
|
297
297
|
- `httpHookAllowlists`(src/http-hook-allowlists.ts):类目行 `SAFETY_MERGE_SPEC.httpHookAllowlists`(denyFirst / global / setNarrower / resolver / closed)。
|
|
298
298
|
`HTTP_HOOK_ALLOWLIST_KEYS`;片段 `HttpHookAllowlistSettings`;层 `HttpHookAllowlistLayer = { source: SettingsSource, 两张名单? }`(只带源名,不带档);
|
|
299
299
|
层读法 `readHttpHookAllowlistLayer(source, settings)` → `{ layer, malformed }`(坏形 ⇒ `[]` 并点名);
|
|
300
|
-
`httpHookUrlVerdict(url, layers, workspace)` → `undefined` | `HttpHookUrlBlock{ list:"allowedHttpHookUrls", rule:"empty"|"url", sources }`:每张**准入**名单
|
|
301
|
-
(准入 ⇔ `layerAdmission(源, 工作区读数, "httpHookAllowlists") === "admitted"` —— 源表定档、类目行定地板;闭集外的源 / 读数 RangeError)都须放行 =
|
|
300
|
+
`httpHookUrlVerdict(url, layers, workspace)`(`layers` 的每一层经读器同一只读法读 —— 读器交出的 `read.layer`、手造的寻常层、本 realm 的 `JSON.parse` 出来的层同答;读不出 `source`〔缺席 / 只靠继承 / 不一致 / 非串〕的层当坏形层全拦、判决词 `malformed` 不点名;源读得出而名单读不出 ⇒ `malformed` 点名那一层;`empty` 只给真空名单)→ `undefined` | `HttpHookUrlBlock{ list:"allowedHttpHookUrls", rule:"malformed"|"empty"|"url", sources }`:每张**准入**名单
|
|
301
|
+
(准入 ⇔ `layerAdmission(源, 工作区读数, "httpHookAllowlists") === "admitted"` —— 源表定档、类目行定地板;闭集外的源 / 读数 RangeError)都须放行 = 跨层取交;名单、`hookVars`、`layers` 都只认朴素数组(原型恒等于本 realm 的 `Array.prototype`〔另一个 realm 的数组按坏形,先 JSON 往返〕、`constructor` / `filter` / `flatMap` / `Symbol.iterator` 是本 realm 的内建、自有键只有下标与 `length`;子类等一律按坏形);
|
|
302
302
|
`httpHookEnvVarsAllowed(hookVars, layers, workspace)` = hook 自己的 allowedEnvVars ∩ 每张准入名单。与 CC 差:拼接 → 取交、任意层 → 准入层(SS-CCD-06 / 07)。
|
|
303
303
|
- `mcpServerPolicyVerdict(server, layers)`(src/mcp-server-policy.ts)→ `undefined` | `McpPolicyBlock{ name, list, rule, target, written, sources }`;闭集 `MCP_SERVER_LIST_KEYS` /
|
|
304
304
|
`MCP_POLICY_RULES`(name / command / url / empty)。层 `McpPolicyLayer = { source: SettingsSource, … }`(只带源名)。拒绝绝对优先、各层都算(名字 → 命令整数组 → URL 拒绝出口);
|
|
@@ -430,6 +430,7 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
|
|
|
430
430
|
`HEARTBEAT_REPLY_CAPABILITIES_KEY = "capabilities"`(`WebAdminCapabilities` 的唯一载体 = 心跳 2xx 答复体的这个键,键查找在 `readCapabilityReading` 里;位按调用方凭证答,共享令牌看不到 `servingLease`);
|
|
431
431
|
env 名常量 `FLEET_GENERATION_ENV` = `"FLEET_GENERATION"`(进 `RESERVED_WORKER_ENV`;渲染器与引擎共用,不各自拼;实例身份 `instanceId`(体的顶层)是引擎每进程自铸的,无 env 名)、
|
|
432
432
|
`FLEET_SCOPE_ENV` = `"FLEET_SCOPE"`(8.3.0,8.3.1 注改真;成员所属租户 scope,与该成员 per-worker 令牌绑定的 scope 同值,渲染器写、引擎读作自身身份的 scope、只用来比对 `DrainRequest.scope`(请求不带 scope ⇒ 读成默认 scope)、不从令牌格式反推;续租 / 心跳的 scope 由凭证定、不取这只 env,两者同值是渲染器的义务;缺席 = 默认 scope `GLOBAL_SCOPE`;同样进 `RESERVED_WORKER_ENV`);
|
|
433
|
+
14.7.0 additive(公告地址 env 名;`.` 与 `./fleet`):env 名常量 `FLEET_ADVERTISE_ADDRESS_ENV` = `"FLEET_ADVERTISE_ADDRESS"`(成员对中心公告的可达基址,中心往它后面拼路径;渲染的一方与读的一方都 import,不各自拼;**不**进 `RESERVED_WORKER_ENV`——运维可经 `worker.env` 声明;它的判官见 4.10d);
|
|
433
434
|
派发(`DISPATCH_STRATEGIES` round-robin|least-inflight|consistent-hash、`DispatchPolicy`、`pickInstance`、
|
|
434
435
|
`SUBMIT_IDEMPOTENCY_KEY`);配额租约(`QuotaLease`/`leaseRemaining`/`leaseExhausted`/`shouldRenewLease`/
|
|
435
436
|
`reconcileLease`);用量上报(`UsageEntry`/`UsageReport`/`aggregateUsage`/`QuotaResetEvent`)。
|
|
@@ -453,7 +454,8 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
|
|
|
453
454
|
四个消费仓对现包名自始至终零 import —— 仅 sdk 的同源锚测试经退役包名 `registry-core` 的冻结版仍取它)。`api/scopes` 同理持有 `SCOPES_V1_PATHS`/`SCOPE_CLAIM`。
|
|
454
455
|
- `api/auth-bridge`:worker 验 web-admin 签发用户 JWT 的契约——RS256-only、JWKS(`WEB_ADMIN_JWKS_PATH`,
|
|
455
456
|
kid-miss 强刷 + ≥60s 节流)、时钟偏移 60s(exp / nbf / iat 同一个容忍)、24h 离线宽限后 fail-closed;`VerifierConfig`/`VerifiedIdentity`
|
|
456
|
-
(携 `scope?` 与 `iat
|
|
457
|
+
(携 `scope?`、`iat?` 与 `principalInc?`:`iat` 签发时刻整数秒原样带出,缺席不铸键,在场而非非负整数 ⇒ 该令牌 malformed;`principalInc`(14.7.0)= 令牌声明 `PRINCIPAL_INC_CLAIM`(`"sub_inc"`)的化身号,
|
|
458
|
+
非空串原样,缺席不铸键(从不读成 0),在场而非非空串 ⇒ 该令牌 malformed;`PrincipalIncarnation` 是所有化身号字段共读的那一只 schema)/`AuthBridgeErrorCode` + 纯判定 `shouldForceJwksRefresh`/`jwksWithinOfflineGrace`/
|
|
457
459
|
`classifyTimeClaims`/`toVerifiedIdentity`/`looksLikeJwt`。
|
|
458
460
|
- `api/scopes`:多租户 scope 契约——`Scope`/`ScopeMember`(viewer<editor<publisher<admin)、保留
|
|
459
461
|
`GLOBAL_SCOPE="global"`、JWT `scope` claim(缺席=global);判定纯函数 `resolveTokenScope`/`canSwitchScope`/
|
|
@@ -489,6 +491,23 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
|
|
|
489
491
|
`retiredEnvRefusal(env)`(纯,读传入的 env;码 `RETIRED_ENV_REFUSAL_CODE` = `config.env_key_retired`;只点名键不回显值);
|
|
490
492
|
目录 wire 投影 `buildRetiredEnvWire()`。引擎起服 / 壳起本机引擎 / web-admin 渲染 worker env 判同一张表。
|
|
491
493
|
|
|
494
|
+
--- 4.10c 沙箱 git 凭据平面(src/sandbox-git.ts + src/api/credentials.ts,主 barrel,不开子路径;14.7.0) ---
|
|
495
|
+
- 沙箱里的 git 用成员本人的凭据:数据面向 web-admin 的凭据取值口按 run 身份申领句柄、凭句柄兑换。本包只有形与词表,零 IO。
|
|
496
|
+
- origin 规范形:`isSandboxGitOrigin(raw)` —— 串逐字等于 `new URL(raw).origin` 且 scheme ∈ {http, https}(小写 host、去缺省端口、无尾斜杠、无 userinfo / 路径 / 查询 / 片段都是这一个等式的推论;origin 不表达子路径部署,无「削成 origin」的规范化器);
|
|
497
|
+
zod 形 `SandboxGitOrigin` / `SandboxGitOriginList`(≤ `SANDBOX_GIT_MAX_ORIGINS` = 16、两两不同、空表合法)。
|
|
498
|
+
- 有效配置块 `sandboxGit`:`SandboxGitConfig` = `{ origins: [{ origin, connectUrl }] }`(`connectUrl` 过 `SandboxGitConnectUrl` = 非秘密 https URL)。`/effective` 载荷上的**非域顶层键**,可选、无默认;`readEffectiveWire` 逐字承运(`EffectiveWire.sandboxGit` 是 `unknown`),
|
|
499
|
+
消费方用 `SandboxGitConfig` 判。块里 http origin 可读(它的拒因是逐 origin 应答里的 `insecure_transport`,不是块的校验拒)。
|
|
500
|
+
- 取值口 wire(`kind: "sandbox_git"`):`SandboxGitCredentialRequest`(申领)/ `CredentialHandleAnswer` / `CredentialResolveRequest`(与种类无关)/ `SandboxGitCredentialAnswer`(每 origin 一行 `SandboxGitOriginAnswer`,按 `state` 判别;
|
|
501
|
+
`secret` 只在 `active` 臂,别的臂剥掉;`needs_reauth` 行必带 `credentialId`)/ `SandboxGitCredentialRefusal`(`{ error, permanence, message }`,`permanence` 必须等于拒答表里这一行的)。解析一律剥未知键。
|
|
502
|
+
- 三张词表,各一张、每个词只在 `src/api/credentials.ts` 里拼一次:`SANDBOX_GIT_ORIGIN_VERDICTS`(逐 origin 判定序表 11 行,序即判定序;`SANDBOX_GIT_ORIGIN_STATES` 六词、`SANDBOX_GIT_ORIGIN_REASONS` 十词与应答臂的原因值域由它派生)·
|
|
503
|
+
`SANDBOX_GIT_REFUSALS`(十个整次拒答词 → HTTP 状态集 + `permanence`;`SANDBOX_GIT_REFUSAL_ERRORS` 由它派生)· `SANDBOX_GIT_PERMANENCE`(`terminal` / `transient`)。两方各自怎么读:`docs/CONSUMER-INTEGRATION.md` §12。
|
|
504
|
+
|
|
505
|
+
--- 4.10d 「后面要拼路径的基址」座位判官(src/url-shape.ts,主 barrel;14.7.0) ---
|
|
506
|
+
- 一种座位的值是别人要往它后面拼路径的基址(中心基址三席、成员对中心公告的地址 `FLEET_ADVERTISE_ADDRESS_ENV`、会话链接的基址):不许带凭据 / query / fragment,路径前缀放行。
|
|
507
|
+
- `PATH_BASE_URL_FORBIDDEN_PARTS`:这种座位禁用的 URL 成分,闭集、冻结、判序 `userinfo` · `query` · `fragment`(策略集,独立于判官词表 `HTTP_URL_PARTS`:词表说 URL 有哪些成分,本集说这种座位禁哪些;今天碰巧同三词,不由词表派生,词表加词时要显式裁)。
|
|
508
|
+
- `pathBaseUrlFlaws(url)` = `httpUrlFlaws(url, PATH_BASE_URL_FORBIDDEN_PARTS)`:`[]` = 合格,否则按判序交回规则词(`not-http-url` / `userinfo` / `query` / `fragment`),不含值的片段;
|
|
509
|
+
判占位展开之后的值(`http://$(POD_IP):8090` 过,`http://[$(POD_IP)]:8090` 拒);`webAdminSessionUrl` 也读它。占位展开、可达性、缺席 / 空串的处置不在本包;两方读法见 `docs/CONSUMER-INTEGRATION.md` §13。
|
|
510
|
+
|
|
492
511
|
--- 4.11 Node-only(`./node`:file-store / file-edit / bundle / local-load / scheduler-store-node / 目录迁移) ---
|
|
493
512
|
- `loadLocalConfig(root, {onWarning}?)` → `LocalConfig { effective, remoteExec, env, requiredEnv, warnings }`。
|
|
494
513
|
- `loadRemoteExec(root)`(三态,§8 T3)、`writeRemoteExec`(校验+原子写)、`remoteExecPath`、`loadEnvFile`
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
|
|
3
|
-
重写日期: 2026-10-
|
|
3
|
+
重写日期: 2026-10-25 | 包版本: 14.7.0
|
|
4
4
|
生成方式: 无生成脚本——按当前树的 src/*.ts 导出面 + package.json + README/CHANGELOG 手写事实版;
|
|
5
5
|
每条断言附证据坐标(文件:符号),刻意不用行号(行号随每版腐烂,符号名由 typecheck/test 钉住)。
|
|
6
6
|
刷新触发: package.json 版号变更(test/docs-hygiene.test.ts D 组钉「包版本:」与 package.json 相等、
|
|
@@ -110,7 +110,7 @@ llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
|
|
|
110
110
|
http/https/ws/wss 且 `ws+unix:` 套接字段逐字、解析不出的模式不放、解码出的字面 `*` 不当通配)/ `urlDenyPatternMatches`(⊇ `g9` ∪ 整串 glob)。
|
|
111
111
|
偏离登 `docs/CC-DIVERGENCE.md`。(src/url-pattern.ts)
|
|
112
112
|
- **http hook 两张名单**(13.0.0):类目 `SAFETY_MERGE_SPEC.httpHookAllowlists`(地板 global);`readHttpHookAllowlistLayer(source, settings)`(坏形读成 `[]`)·
|
|
113
|
-
`httpHookUrlVerdict(url, layers, workspace)` → `HttpHookUrlBlock{list, rule, sources}` 或 `undefined`(每张准入名单都须放行 = 跨层取交)·
|
|
113
|
+
`httpHookUrlVerdict(url, layers, workspace)`(`layers` 的每一层经读器同一只读法读 —— 读器交出的 `read.layer`、手造的寻常层、本 realm 的 `JSON.parse` 出来的层同答;另一个 realm 的数组按坏形全拦)→ `HttpHookUrlBlock{list, rule, sources}` 或 `undefined`(每张准入名单都须放行 = 跨层取交)·
|
|
114
114
|
`httpHookEnvVarsAllowed(hookVars, layers, workspace)`(取交);准入 ⇔ `layerAdmission(源, 工作区读数, "httpHookAllowlists") === "admitted"`。
|
|
115
115
|
(src/http-hook-allowlists.ts)
|
|
116
116
|
- **MCP 名单判决**(13.0.0):`mcpServerPolicyVerdict(server, layers)` → `McpPolicyBlock{name, list, rule, target, written, sources}` 或 `undefined`;
|
|
@@ -141,6 +141,7 @@ llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
|
|
|
141
141
|
判官只读信号:`judgeReadiness(signal)` / `judgeRoutability(row, nowMs)` → `{ routable }` 或 `{ routable:false, code ∈ NOT_ROUTABLE_CODES, why }`,
|
|
142
142
|
`isReadyForTraffic` / `isRoutable` 是它们的布尔形;没有信号(旧引擎)= `no-engine-signal`,不可路由;布尔对 `draining` / `drainingSince` 标 `@deprecated`、本包零读点、退役已登记;
|
|
143
143
|
8.3.0 additive:env 名常量 `FLEET_SCOPE_ENV`(`"FLEET_SCOPE"`,成员所属租户 scope,渲染器写、引擎读;缺席 = 默认 scope `GLOBAL_SCOPE`;进保留 env 名表);
|
|
144
|
+
14.7.0 additive:公告地址 env 名常量 `FLEET_ADVERTISE_ADDRESS_ENV`(`"FLEET_ADVERTISE_ADDRESS"`)+「后面要拼路径的基址」座位的禁用成分集 `PATH_BASE_URL_FORBIDDEN_PARTS`(`userinfo` / `query` / `fragment`)+ 判官 `pathBaseUrlFlaws(url)`(= `httpUrlFlaws` 配这一集;判展开之后的值;`webAdminSessionUrl` 也读它);
|
|
144
145
|
9.0.0 BREAKING:`readCenterCapabilities` 删,换三态读器 `readCapabilityReading(reply): CapabilityReading`(`declared` | `undeclared` | `unreadable`;键在场而形坏 ≠ 没宣告)、`EngineSignal.configTargetVersion` / `configAppliedVersion` 由串改数)、**scheduler-store 契约**(自唤醒
|
|
145
146
|
存储形 + node 绑定)、**auth / auth-bridge / scopes / wire** 契约(RFC 8628 设备流、RS256 JWKS 鉴权桥、
|
|
146
147
|
多租户 scope)。(src/fleet.ts;src/scheduler-store*.ts;src/api/*.ts)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/settings-schema",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.7.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",
|