@sema-agent/settings-schema 6.1.0 → 6.3.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +265 -0
  2. package/README.md +40 -9
  3. package/conformance/VERSION +1 -1
  4. package/conformance/cases/c41-s792-encoded-pem-identity/expected.json +166 -0
  5. package/conformance/cases/c41-s792-encoded-pem-identity/input.json +62 -0
  6. package/conformance/cases/c41-s792-encoded-pem-identity/meta.json +12 -0
  7. package/conformance/cases/c42-s792-unknown-key-secret-redacted/expected.json +120 -0
  8. package/conformance/cases/c42-s792-unknown-key-secret-redacted/input.json +25 -0
  9. package/conformance/cases/c42-s792-unknown-key-secret-redacted/meta.json +11 -0
  10. package/conformance/cases/c43-s792-form-and-deep-encoded-pem/expected.json +137 -0
  11. package/conformance/cases/c43-s792-form-and-deep-encoded-pem/input.json +44 -0
  12. package/conformance/cases/c43-s792-form-and-deep-encoded-pem/meta.json +12 -0
  13. package/conformance/cases/c44-s792-utf8-escape-glued-token/expected.json +115 -0
  14. package/conformance/cases/c44-s792-utf8-escape-glued-token/input.json +30 -0
  15. package/conformance/cases/c44-s792-utf8-escape-glued-token/meta.json +10 -0
  16. package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/expected.json +185 -0
  17. package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/input.json +78 -0
  18. package/conformance/cases/c45-s792-identity-bounds-and-decode-depth/meta.json +11 -0
  19. package/conformance/cases/c46-s811-host-name-url-userinfo-characterization/expected.json +88 -0
  20. package/conformance/cases/c46-s811-host-name-url-userinfo-characterization/input.json +18 -0
  21. package/conformance/cases/c46-s811-host-name-url-userinfo-characterization/meta.json +6 -0
  22. package/conformance/cases/c47-s811-roles-key-url-userinfo-characterization/expected.json +98 -0
  23. package/conformance/cases/c47-s811-roles-key-url-userinfo-characterization/input.json +26 -0
  24. package/conformance/cases/c47-s811-roles-key-url-userinfo-characterization/meta.json +6 -0
  25. package/conformance/cases/cli01-model-name-nfc-vs-nfd/expected.json +0 -8
  26. package/conformance/cases/cli01-model-name-nfc-vs-nfd/meta.json +2 -1
  27. package/conformance/cases/cli02-control-and-zero-width-chars/expected.json +0 -8
  28. package/conformance/cases/cli02-control-and-zero-width-chars/meta.json +2 -1
  29. package/dist/config-fns.d.ts +62 -14
  30. package/dist/config-fns.js +105 -30
  31. package/dist/cross-session.d.ts +8 -5
  32. package/dist/cross-session.js +8 -5
  33. package/dist/fleet.d.ts +163 -0
  34. package/dist/fleet.js +126 -5
  35. package/dist/secret-scan.d.ts +39 -0
  36. package/dist/secret-scan.js +110 -0
  37. package/dist/types.d.ts +79 -72
  38. package/dist/types.js +17 -31
  39. package/package.json +2 -2
@@ -0,0 +1,78 @@
1
+ {
2
+ "meta": {
3
+ "version": 16,
4
+ "updatedAt": "2026-09-27T00:00:00.000Z"
5
+ },
6
+ "domains": {
7
+ "models": {
8
+ "models": [
9
+ {
10
+ "name": "keep",
11
+ "provider": "openai",
12
+ "id": "keep-id",
13
+ "apiKeyEnv": "OPENAI_API_KEY"
14
+ },
15
+ {
16
+ "name": "maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
17
+ "provider": "openai",
18
+ "id": "cap-256-id",
19
+ "apiKeyEnv": "not an env name"
20
+ },
21
+ {
22
+ "name": "maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
23
+ "provider": "openai",
24
+ "id": "cap-257-id",
25
+ "apiKeyEnv": "not an env name"
26
+ },
27
+ {
28
+ "name": "db-url-id",
29
+ "provider": "openai",
30
+ "id": "postgres://svc:FAKEC45USERINFOPW@db.internal/app",
31
+ "apiKeyEnv": "not an env name"
32
+ },
33
+ {
34
+ "name": "scope-path-id",
35
+ "provider": "openai",
36
+ "id": "https://registry.example.com/@scope/pkg",
37
+ "apiKeyEnv": "not an env name"
38
+ }
39
+ ],
40
+ "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": 1,
41
+ "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": 1
42
+ },
43
+ "mcp": {
44
+ "servers": [
45
+ {
46
+ "name": "ok-server",
47
+ "transport": {
48
+ "kind": "stdio",
49
+ "command": "node",
50
+ "args": [
51
+ "server.js"
52
+ ]
53
+ }
54
+ },
55
+ {
56
+ "name": "triple-encoded-arg",
57
+ "transport": {
58
+ "kind": "stdio",
59
+ "command": "node",
60
+ "args": [
61
+ "--token=%252573%25256B-live-FAKEC45TRIPLEENCODEDARG00"
62
+ ]
63
+ }
64
+ }
65
+ ]
66
+ },
67
+ "hosts": {
68
+ "hosts": [
69
+ {
70
+ "name": "ok-host"
71
+ },
72
+ {
73
+ "name": "sk-live-FAKEC45HOSTNAME000000000000000000000000000000000000000000000000000000000000"
74
+ }
75
+ ]
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "contributor": "contract",
3
+ "claim": "6.3.0(合并复审 opus 腿 L5 / M1 / M2 / L1,S-792):给语料里此前没有杀手的几道边补上 —— ① 长度上界 256(身份白名单与出门坐标段同一只常量):256 字的合法模型名被丢时身份照带 name、257 字不带;256 字的良性未知键名逐字点名、257 字整段 `[redacted-secret]`。② 解码层数 3(校验侧探测器):mcp stdio 参数里三重百分号编码的 `sk-` 形令牌照旧被拒、条目被丢(层数少一层就放行进 effective)。③ 身份否决里的 URL userinfo 判定:`postgres://svc:…@db…` 作被丢条目 id 不带;路径里的 `@`(`https://…/@scope/pkg`)照带。④ `hosts-grandfathered.droppedNames` 过同一道出门:`sk-live-…` 形超长主机名读 `[redacted-secret]`,不再是 63 字原文前缀。",
4
+ "firstRedOn": [],
5
+ "secrets": [
6
+ "FAKEC45USERINFOPW",
7
+ "sk-live-FAKEC45HOSTNAME",
8
+ "FAKEC45TRIPLEENCODEDARG00"
9
+ ],
10
+ "note": "车PE(2026-09-27)合并复审 opus 腿之后同轮加;是变异门的杀手语料,不是红先复现(对应的红先在 test/disclosable-identity-6.3.0.test.ts 的 M1 / M2 / L1 组)。变异门靶:`DISCLOSABLE_IDENTITY_MAX` 改大、`outgoingSegment` 去上界、`SECRET_SCAN_DECODE_LAYERS` 3 → 2、身份否决去 `carriesUserinfo`、`droppedNames` 不过出门那一道 —— 各由本条杀(逐靶实测见车PE 收车档)。firstRedOn 为空:historical 阶梯证据真跑于本条入库之前。"
11
+ }
@@ -0,0 +1,88 @@
1
+ {
2
+ "domains": {
3
+ "outcome": "effective",
4
+ "effective": {
5
+ "collab": {
6
+ "templates": []
7
+ },
8
+ "entitlement": {
9
+ "budgetGroups": [],
10
+ "groupBindings": [],
11
+ "subjects": [],
12
+ "tiers": []
13
+ },
14
+ "execution": {
15
+ "allowedLanes": [
16
+ "host"
17
+ ],
18
+ "required": false
19
+ },
20
+ "governance": {},
21
+ "hosts": {
22
+ "hosts": [
23
+ {
24
+ "approved": false,
25
+ "drain": false,
26
+ "enabled": true,
27
+ "labels": [],
28
+ "name": "ok-host"
29
+ }
30
+ ]
31
+ },
32
+ "limits": {},
33
+ "mcp": {
34
+ "servers": []
35
+ },
36
+ "models": {
37
+ "models": [],
38
+ "roles": {},
39
+ "tierGroups": []
40
+ },
41
+ "plugins": {
42
+ "plugins": []
43
+ },
44
+ "projects": {
45
+ "projects": {}
46
+ },
47
+ "prompts": {
48
+ "bindings": []
49
+ },
50
+ "rosters": {
51
+ "rosters": []
52
+ },
53
+ "runtime": {},
54
+ "scenarios": {
55
+ "scenarios": []
56
+ },
57
+ "skills": {
58
+ "skills": []
59
+ },
60
+ "systems": {
61
+ "systems": []
62
+ },
63
+ "workers": {
64
+ "workers": []
65
+ }
66
+ },
67
+ "warnings": [
68
+ {
69
+ "domain": "hosts",
70
+ "droppedNames": [
71
+ "https://admin:hunter2@hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh…"
72
+ ],
73
+ "kind": "hosts-grandfathered"
74
+ }
75
+ ],
76
+ "metadata": {
77
+ "version": 17,
78
+ "updatedAt": "2026-09-27T00:00:00.000Z"
79
+ }
80
+ },
81
+ "wire": {
82
+ "derive": true
83
+ },
84
+ "localRoot": {
85
+ "derive": true,
86
+ "localVersion": 2617555914511015
87
+ }
88
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "meta": {
3
+ "version": 17,
4
+ "updatedAt": "2026-09-27T00:00:00.000Z"
5
+ },
6
+ "domains": {
7
+ "hosts": {
8
+ "hosts": [
9
+ {
10
+ "name": "ok-host"
11
+ },
12
+ {
13
+ "name": "https://admin:hunter2@hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh.com"
14
+ }
15
+ ]
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "contributor": "contract",
3
+ "claim": "🚧 S-811 特征格(既有,非回归;本版刻意不修,设计随 S-809 三表归一):超长主机名 `https://admin:hunter2@hhh…h.com`(81 字)被 `hosts-grandfathered` 按名剔掉,`droppedNames` 的标签过出门那一道 —— 但那一道(`redactSecrets`)不查 URL userinfo,于是 63 字标签里原样带着 `admin:hunter2`。本条把**今天的读数**钉成金样:S-811 修后(自由文本面加 userinfo 判定)本条翻红 —— 届时金样改成 `droppedNames: [\"[redacted-secret]\"]`、meta.secrets 补上 `hunter2`,这一格就从特征钉变成护栏。",
4
+ "firstRedOn": [],
5
+ "note": "车PE(2026-09-27)按主会话令加(codex 验修腿 [high] S-811)。刻意**不**在 secrets 里登 `hunter2`:登了,告警面零命中门会把今天的现状判红 —— 现状要能如实入库,修复时一并补。"
6
+ }
@@ -0,0 +1,98 @@
1
+ {
2
+ "domains": {
3
+ "outcome": "effective",
4
+ "effective": {
5
+ "collab": {
6
+ "templates": []
7
+ },
8
+ "entitlement": {
9
+ "budgetGroups": [],
10
+ "groupBindings": [],
11
+ "subjects": [],
12
+ "tiers": []
13
+ },
14
+ "execution": {
15
+ "allowedLanes": [
16
+ "host"
17
+ ],
18
+ "required": false
19
+ },
20
+ "governance": {},
21
+ "hosts": {
22
+ "hosts": []
23
+ },
24
+ "limits": {},
25
+ "mcp": {
26
+ "servers": []
27
+ },
28
+ "models": {
29
+ "models": [
30
+ {
31
+ "api": "openai-completions",
32
+ "apiKeyEnv": "OPENAI_API_KEY",
33
+ "enabled": true,
34
+ "id": "keep-id",
35
+ "name": "keep",
36
+ "provider": "openai",
37
+ "quotaWeight": 1,
38
+ "reasoning": false,
39
+ "tier": "standard",
40
+ "vision": false
41
+ }
42
+ ],
43
+ "roles": {
44
+ "summarize": {
45
+ "model": "keep"
46
+ }
47
+ },
48
+ "tierGroups": []
49
+ },
50
+ "plugins": {
51
+ "plugins": []
52
+ },
53
+ "projects": {
54
+ "projects": {}
55
+ },
56
+ "prompts": {
57
+ "bindings": []
58
+ },
59
+ "rosters": {
60
+ "rosters": []
61
+ },
62
+ "runtime": {},
63
+ "scenarios": {
64
+ "scenarios": []
65
+ },
66
+ "skills": {
67
+ "skills": []
68
+ },
69
+ "systems": {
70
+ "systems": []
71
+ },
72
+ "workers": {
73
+ "workers": []
74
+ }
75
+ },
76
+ "warnings": [
77
+ {
78
+ "domain": "models",
79
+ "kind": "entry-dropped",
80
+ "path": [
81
+ "roles",
82
+ "https://admin:hunter2@db.example.com/x"
83
+ ]
84
+ }
85
+ ],
86
+ "metadata": {
87
+ "version": 18,
88
+ "updatedAt": "2026-09-27T00:00:00.000Z"
89
+ }
90
+ },
91
+ "wire": {
92
+ "derive": true
93
+ },
94
+ "localRoot": {
95
+ "derive": true,
96
+ "localVersion": 715023802301241
97
+ }
98
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "meta": {
3
+ "version": 18,
4
+ "updatedAt": "2026-09-27T00:00:00.000Z"
5
+ },
6
+ "domains": {
7
+ "models": {
8
+ "models": [
9
+ {
10
+ "name": "keep",
11
+ "provider": "openai",
12
+ "id": "keep-id",
13
+ "apiKeyEnv": "OPENAI_API_KEY"
14
+ }
15
+ ],
16
+ "roles": {
17
+ "summarize": {
18
+ "model": "keep"
19
+ },
20
+ "https://admin:hunter2@db.example.com/x": {
21
+ "model": "keep"
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "contributor": "contract",
3
+ "claim": "🚧 S-811 特征格(既有,非回归;本版刻意不修,设计随 S-809 三表归一):坏 roles 键 `https://admin:hunter2@db.example.com/x` 被逐条丢掉,坐标段与 zod 回显的 received / message 都只过 `redactSecrets`,它不查 URL userinfo,于是坐标 `[\"roles\", \"https://admin:hunter2@db.example.com/x\"]` 原样出门(错误句同带)。同一个串作身份 6.3.0 起不可披露(身份面有 userinfo 否决),自由文本面没有 —— 本条把今天的读数钉成金样:S-811 修后本条翻红,届时坐标段改成 `[redacted-secret]`、meta.secrets 补上 `hunter2`。",
4
+ "firstRedOn": [],
5
+ "note": "车PE(2026-09-27)按主会话令加(codex 验修腿 [high] S-811)。刻意**不**在 secrets 里登 `hunter2`(登了即判红今天的现状)。"
6
+ }
@@ -72,10 +72,6 @@
72
72
  "warnings": [
73
73
  {
74
74
  "domain": "models",
75
- "identity": {
76
- "id": "café-id",
77
- "name": "café"
78
- },
79
75
  "kind": "entry-dropped",
80
76
  "path": [
81
77
  "models",
@@ -84,10 +80,6 @@
84
80
  },
85
81
  {
86
82
  "domain": "models",
87
- "identity": {
88
- "id": "café-id",
89
- "name": "café"
90
- },
91
83
  "kind": "entry-dropped",
92
84
  "path": [
93
85
  "models",
@@ -5,5 +5,6 @@
5
5
  "settings-schema@1.0.0",
6
6
  "settings-schema@1.10.0",
7
7
  "settings-schema@1.5.0"
8
- ]
8
+ ],
9
+ "note": "6.3.0(车PE,2026-09-27):被丢条目的身份改走白名单闭形 `DISCLOSABLE_IDENTITY_RE`(`A-Za-z0-9._:/@+-`,1–256)—— 两条的 name / id 含非 ASCII 字母(é / 组合符),落在集外 ⇒ 按无名处置,`identity` 键缺席;两条仍各自按下标点名(坐标照旧),effective 与三腿一致性不动。expected.json 随之重 bless,diff 只少两处 identity。"
9
10
  }
@@ -85,10 +85,6 @@
85
85
  "warnings": [
86
86
  {
87
87
  "domain": "models",
88
- "identity": {
89
- "id": "a\u0007b-id",
90
- "name": "a\u0007b"
91
- },
92
88
  "kind": "entry-dropped",
93
89
  "path": [
94
90
  "models",
@@ -97,10 +93,6 @@
97
93
  },
98
94
  {
99
95
  "domain": "models",
100
- "identity": {
101
- "id": "zero​width-id",
102
- "name": "zero​width"
103
- },
104
96
  "kind": "entry-dropped",
105
97
  "path": [
106
98
  "models",
@@ -5,5 +5,6 @@
5
5
  "settings-schema@1.0.0",
6
6
  "settings-schema@1.10.0",
7
7
  "settings-schema@1.5.0"
8
- ]
8
+ ],
9
+ "note": "6.3.0(车PE,2026-09-27):被丢条目的身份改走白名单闭形 `DISCLOSABLE_IDENTITY_RE`(`A-Za-z0-9._:/@+-`,1–256)—— 两条的 name / id 含控制字符(BEL)/ 零宽空格,落在集外 ⇒ 按无名处置,`identity` 键缺席;两条仍各自按下标点名(坐标照旧),effective 与三腿一致性不动。expected.json 随之重 bless,diff 只少两处 identity。"
9
10
  }
@@ -21,15 +21,24 @@ import { type DomainConfig, type DomainName, type EffectiveConfig, type Effectiv
21
21
  * any secret-shaped run (`%` kept in the run so a percent-encoded secret stays whole for the percent-aware
22
22
  * containsSecretToken). invariant ①: a secret VALUE never rides an error. R13/R14.
23
23
  *
24
- * **Output invariant** (S-712 verification pass N1 + codex review [high] ×2): a string holding a private-key PEM
25
- * header ANYWHERE ({@link PRIVATE_KEY_PEM_HEADER}) is withheld WHOLE, and no result trips `containsSecretToken`.
26
- * The PEM header is judged on the ORIGINAL text, before any replacement: the token pass can rewrite the header
27
- * itself away (`sk-note:-----BEGIN` is one token-charset run that starts with `sk-`, so it becomes
28
- * `[redacted-secret]` and the key body after it would ride out untouched — codex verification round). A PEM header
29
- * carries spaces, so the targeted passes can never isolate it, and the detector only sees it at the very start of
30
- * a string. Every warning face that goes through here (coordinates, error text, entry identity) inherits the same
31
- * guarantee. The validation-side detector `containsSecretToken` is deliberately NOT widened here: making it reject
32
- * a mid-string PEM would tighten every field it validates (a major). */
24
+ * **Output invariant** (S-712 verification pass N1 + codex review [high] ×2; 6.3.0): a string holding a private-key
25
+ * PEM header ANYWHERE ({@link PRIVATE_KEY_PEM_HEADER}) in ANY of its {@link secretScanForms} `forms` is withheld WHOLE, a
26
+ * string whose normalization did not finish (`unresolved`) is withheld WHOLE, and no result trips `containsSecretToken` on
27
+ * any of its forms.
28
+ * The whole-string judgement is ONE rule — both detectors run over the normalized forms: the PEM header on every form of
29
+ * the ORIGINAL text, `containsSecretToken` on every form of the targeted result; what could not be normalized does not go
30
+ * out (6.3.0, codex r1 F1: `-----BEGIN+PRIVATE+KEY` form-encoded headers and four-layer encodings both rode out).
31
+ * 6.3.0 (codex review of v6.1.0 [high]): `key=` + a percent-encoded PEM showed its header only on a decoded form
32
+ * (`-----BEGIN%20PRIVATE%20KEY` — `%20` is not in `[A-Z0-9 ]`), and the detector's anchored decode missed it behind
33
+ * the `key=` prefix, so the whole key rode out through coordinates, zod `received` / `message` and entry identity.
34
+ * The PEM header is judged BEFORE any replacement: the token pass can rewrite the header itself away
35
+ * (`sk-note:-----BEGIN` is one token-charset run that starts with `sk-`, so it becomes `[redacted-secret]` and the
36
+ * key body after it would ride out untouched — codex verification round). A PEM header carries spaces, so the
37
+ * targeted passes can never isolate it, and the detector only sees it at the very start of a string. Every
38
+ * free-text warning face that goes through here (coordinates, error text) inherits the same guarantee; the entry
39
+ * identity face additionally has to be an identifier ({@link isDisclosableIdentity}). The validation-side detector
40
+ * `containsSecretToken` is deliberately NOT widened here: making it reject a mid-string PEM would tighten every field
41
+ * it validates (a major). */
33
42
  export declare function redactSecrets(text: string): string;
34
43
  /** Sanitize a ZodError IN PLACE so no surfaced error (message / `received` / nested `unionErrors`) echoes a
35
44
  * pasted secret. RECURSES into `unionErrors` (a `z.union` failure nests a ZodError per member — e.g. RoleTarget
@@ -164,9 +173,10 @@ export declare function formatConfigPath(p: ConfigPath): string;
164
173
  /** 一条被丢掉的条目的**身份**(S-712):只从被丢条目**原文**里取,三键各自可缺。
165
174
  *
166
175
  * 律(一条,不分域):`name` / `id` 取**字符串**形、`enabled` 取**布尔**形,类型不对 ⇒ 不带该键(不猜、
167
- * 不 `String()` 转换);只认**数据属性**(不触发访问器);{@link redactSecrets} 会改动的串 ⇒ 不带该键 ——
168
- * 与坐标段同一只脱敏判据:坐标段必须在场,所以打码出门;身份是可缺的,打过码的串不再是任何条目的身份,
169
- * 所以是**不带**而不是打码。三键都读不出 ⇒ 整个身份缺席(不铸空对象)。
176
+ * 不 `String()` 转换);只认**数据属性**(不触发访问器);{@link isDisclosableIdentity} 说不可披露 ⇒ 不带该键
177
+ * (6.3.0 起:身份是**标识符**,须落在 {@link DISCLOSABLE_IDENTITY_RE} 白名单闭形里,且坐标脱敏器
178
+ * {@link redactSecrets} 原样放行 —— 坐标段必须在场,所以打码出门;身份是可缺的,打过码的串不再是任何条目的身份,
179
+ * 所以是**不带**而不是打码)。三键都读不出 ⇒ 整个身份缺席(不铸空对象)。
170
180
  *
171
181
  * **缺席 = 读不出**(不是字符串,或是字符串但不能原样出门),两种原因刻意不分:对消费方的正确处置相同
172
182
  * (身份未知 ⇒ 按未知处置,例如 fail-closed),而一个「被扣下」的标记本身就在说「这里有一段像凭据的东西」。
@@ -186,6 +196,35 @@ export interface DroppedEntry {
186
196
  error: unknown;
187
197
  identity?: DroppedEntryIdentity;
188
198
  }
199
+ /** 可披露身份的**闭形**(6.3.0):字符集 `A-Z a-z 0-9 . _ : / @ + -`、长度 1–256(上限与 web-admin 读侧名长上限 256 对齐;`ModelEntry.name`
200
+ * 本身不设上限,超 256 字的合法名按无名处置)。身份是**标识符**不是自由文本 ——
201
+ * 允许集才是它的语义:上游模型 id 的真实形(`accounts/fireworks/models/…`、`Qwen/Qwen2.5-72B-Instruct`、
202
+ * `claude-3-5-sonnet@20240620`、`deepseek-v4-flash:free`、`o3-mini+high`)都在集内;`%` / `=` / 空白 / 引号 / 反斜杠 /
203
+ * 控制与零宽字符 / 非 ASCII 一律在集外 —— 编码过的、带前缀的、多行的、会在日志里伪造行的串,不可能是一个标识符。
204
+ * 无旗标(无 `g` ⇒ `.test` 无状态,可放心共享这一只)。判据只有 {@link isDisclosableIdentity} 一只,消费方要
205
+ * 「这个名能不能写出去」问它,不要拿本常量自拼(集内仍有密钥形,见那一只的否决项)。 */
206
+ export declare const DISCLOSABLE_IDENTITY_RE: RegExp;
207
+ /** 身份串 —— 「一个用户写的身份串(条目的 `name` / `id`)能不能**原样**出门」的**唯一**判据(6.3.0 起两项合取):
208
+ * ① **形**:落在 {@link DISCLOSABLE_IDENTITY_RE} 白名单闭形里(不再是「不像密钥就可披露」—— 6.1.0 / 6.2.0 的黑名单
209
+ * 判据放行过 `key=` + 百分号编码的整把 PEM 私钥,codex 对 v6.1.0 复审 [high]);
210
+ * ② **否决**(「无密钥形」):坐标脱敏器 {@link redactSecrets} 原样放行 —— 集内照样有密钥形(`sk-…` / `ghp_…` /
211
+ * `AKIA…` / 三段 JWT 的字符全在集内),而且判它的必须是坐标段、`error` 文案({@link sanitizeZodError})用的**同一只**
212
+ * 脱敏器:两只判据会在同一条告警里给出两种答案(对抗轮 #2 真复现;集内的残例 = `@` 之后的单点 `eyJ…` 串,裸探测器
213
+ * 判阴、脱敏器会改,语料 c41 钉着);∧ 不是带 userinfo 的 URL —— 校验侧 `NON_SECRET_URL` 拒写的同一只判定
214
+ * (`carriesUserinfo`,包内私有;opus 腿 L1:`postgres://svc:pw@h` 的字符全在集内)。
215
+ * 入参是 `string`、返回 `boolean`,**刻意不是**类型谓词(`v is string`):它对一些字符串答 false,谓词形会让调用方的
216
+ * 否定分支把一个 `string` 收窄成 `never`;「是不是字符串」由调用点自己判(运行期收到非字符串照答 false、不抛)。
217
+ * 不可披露的串按**无名**处置(不带,而不是打码:打过码的串不再是身份)。
218
+ * 执法面(同一条律):被丢条目的身份({@link DroppedEntryIdentity},本文件铸);`ModelRefusalsWire` 的 `entries` 键
219
+ * (经 {@link isReportableRefusalName},S-768);引擎自己的日志 / 拒因句里要不要写出一个名字,同样问这一只。 */
220
+ export declare function isDisclosableIdentity(v: string): boolean;
221
+ /** S-768 —— 「一个目录条目名能不能当 {@link ModelRefusalsWire} `entries` 的键」的**唯一**判据;引擎铸键前只调这一只,
222
+ * 不过 ⇒ 按无名处置(不进键、不计数)。两条律的合取,不手抄任何一条:
223
+ * ① 这只 schema **自己载得住**这个键 —— 就地拿 schema 判(空串不过键规则;`__proto__` 这类名被 zod 的 record 静默丢掉,
224
+ * 载不住),不写名单;
225
+ * ② {@link isDisclosableIdentity}(不是白名单闭形里的标识符,或是秘密形 ⇒ 不出门)。
226
+ * 非字符串 ⇒ false。住在本文件而不是 `./fleet`:`fleet.ts` 被 `types.ts` 引,它再引本文件会成环。 */
227
+ export declare function isReportableRefusalName(name: string): boolean;
189
228
  /** 抢救造成的**下标位移表**:数组字段名 → 该字段压缩后每个位置的**原**下标(`kept[j]` = 压缩后第 j 条
190
229
  * 在原文档里的下标)。纯数据,无行为。
191
230
  *
@@ -222,7 +261,7 @@ export interface EntrySalvageResult {
222
261
  * 造出一个空集合**。
223
262
  *
224
263
  * 🔴 **告警不许比它诊断的东西更危险**(复审 R1 两条,红先复现):① Record 的键是用户写的,完全可能就是
225
- * 一条粘错位置的凭据,所以路径里的键段过 {@link redactSecrets} 才出门(不变量①:secret 值永不随错误外流,
264
+ * 一条粘错位置的凭据,所以路径里的键段过 {@link redactSecrets} 才出门(6.3.0 起经 `outgoingPath` 这一道;不变量①:secret 值永不随错误外流,
226
265
  * 与 parseDomain 的 R13/R14 同一条);② 整段遍历包 try/catch —— 读字段、枚举 Record 都会触发访问器,
227
266
  * 抛出来的文案可能带 secret。抢救是**尽力而为**的:抢不动就当没抢救(返回原引用),让既有的整域档位去裁,
228
267
  * 绝不把解析拖下水、更不回显它的错误(与同文件 {@link droppedKeys} 逐字同纪律)。
@@ -269,10 +308,14 @@ export declare function legacyGovernanceFromRuntime(rawRuntime: unknown): unknow
269
308
  * 0.19.0 加了两个 kind(additive union member —— 用 `switch` 穷举本类型的消费方需补臂):
270
309
  * `"unknown-keys-dropped"` / `"unread-config-file"`,成案见 {@link droppedKeys}(消费方
271
310
  * #322:配置写了、进程跑着、值没到,而没有任何一个字说出来)。 */
272
- export type EffectiveReadWarning = {
311
+ export type EffectiveReadWarning =
312
+ /** `droppedNames` 有界(6.3.0,S-813:与未知键同一只 `DROP_SCAN_MAX_KEYS`),超界时带 `droppedTotal`(= 按名剔掉的真实条数)——
313
+ * 缺席 = 列表是穷举。`truncatedFrom` 另是一件事:hosts 数组超 `HOSTS_ARRAY_MAX` 被切片前的长度。 */
314
+ {
273
315
  domain: "hosts";
274
316
  kind: "hosts-grandfathered";
275
317
  droppedNames: string[];
318
+ droppedTotal?: number;
276
319
  truncatedFrom?: number;
277
320
  } | {
278
321
  domain: DomainName;
@@ -542,6 +585,11 @@ export interface GrandfatherHostsReadResult {
542
585
  /** Host names DROPPED because they exceed HOST_NAME_MAX (63) — truncating would forge a NEW identity that
543
586
  * matches no ORCH_HOST_ID (and could collide into the duplicate-name refine), so the entry is skipped whole. */
544
587
  droppedNames: string[];
588
+ /** How many hosts were dropped by name — the TRUE count. `droppedNames` carries labels for at most `DROP_SCAN_MAX_KEYS` (64,
589
+ * the same bound as the unknown-key scan) of them; each label goes through the outgoing redaction, and a document with
590
+ * thousands of over-long names must not cost thousands of scans on every read (6.3.0, S-813). Same shape as
591
+ * {@link UnknownKeyScan}'s `{ keys, total }`. */
592
+ droppedTotal: number;
545
593
  /** Set when the hosts array (after drops) exceeded HOSTS_ARRAY_MAX (1024) and was sliced — the pre-slice length. */
546
594
  truncatedFrom?: number;
547
595
  /** 这次夹紧造成的**下标位移表**(与 {@link EntrySalvageResult.keptIndex} 同一种账、同一条律):本函数