@sema-agent/settings-schema 14.5.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +531 -0
  2. package/README.md +46 -3
  3. package/conformance/VERSION +1 -1
  4. package/conformance/cases/c84-sandbox-git-block-carried-verbatim/expected.json +153 -0
  5. package/conformance/cases/c84-sandbox-git-block-carried-verbatim/input.json +23 -0
  6. package/conformance/cases/c84-sandbox-git-block-carried-verbatim/meta.json +5 -0
  7. package/conformance/cases/c85-sandbox-git-refused-block-still-carried/expected.json +153 -0
  8. package/conformance/cases/c85-sandbox-git-refused-block-still-carried/input.json +23 -0
  9. package/conformance/cases/c85-sandbox-git-refused-block-still-carried/meta.json +5 -0
  10. package/dist/api/auth-bridge.d.ts +16 -2
  11. package/dist/api/auth-bridge.js +59 -24
  12. package/dist/api/credentials.d.ts +281 -0
  13. package/dist/api/credentials.js +149 -0
  14. package/dist/api/scopes.js +5 -1
  15. package/dist/atomic-write.js +10 -7
  16. package/dist/bundle.d.ts +1 -1
  17. package/dist/bundle.js +1 -1
  18. package/dist/config-d-file.js +33 -15
  19. package/dist/config-dir-migration.js +2 -1
  20. package/dist/config-fns.js +142 -78
  21. package/dist/conformance/canonical.js +7 -10
  22. package/dist/conformance/contract-adapter.js +26 -1
  23. package/dist/conformance/corpus.js +5 -5
  24. package/dist/conformance/derive.js +6 -5
  25. package/dist/conformance/run.js +44 -6
  26. package/dist/cross-session.d.ts +4 -4
  27. package/dist/declared-capture.d.ts +41 -0
  28. package/dist/declared-capture.js +344 -0
  29. package/dist/file-edit.js +11 -15
  30. package/dist/file-store.d.ts +1 -31
  31. package/dist/file-store.js +3 -30
  32. package/dist/fleet.d.ts +11 -0
  33. package/dist/fleet.js +60 -26
  34. package/dist/fs-failure.d.ts +12 -7
  35. package/dist/fs-failure.js +53 -29
  36. package/dist/hash.d.ts +0 -9
  37. package/dist/hash.js +64 -7
  38. package/dist/hooks-config.d.ts +2 -2
  39. package/dist/hooks-config.js +129 -33
  40. package/dist/http-hook-allowlists.d.ts +27 -10
  41. package/dist/http-hook-allowlists.js +189 -25
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.js +4 -1
  44. package/dist/mcp-request-entry.d.ts +13 -8
  45. package/dist/mcp-request-entry.js +246 -107
  46. package/dist/one-time-migrations.js +207 -95
  47. package/dist/own-key-read.d.ts +247 -0
  48. package/dist/own-key-read.js +449 -0
  49. package/dist/plain-json-object.d.ts +38 -3
  50. package/dist/plain-json-object.js +84 -7
  51. package/dist/portable-domains.d.ts +31 -0
  52. package/dist/portable-domains.js +30 -0
  53. package/dist/remote-exec.js +9 -1
  54. package/dist/safety-merge-spec.d.ts +88 -6
  55. package/dist/safety-merge-spec.js +246 -17
  56. package/dist/sandbox-git.d.ts +64 -0
  57. package/dist/sandbox-git.js +89 -0
  58. package/dist/scheduler-store.js +21 -12
  59. package/dist/settings-units.d.ts +85 -0
  60. package/dist/settings-units.js +177 -0
  61. package/dist/types.d.ts +6 -2
  62. package/dist/types.js +65 -56
  63. package/dist/url-shape.d.ts +27 -5
  64. package/dist/url-shape.js +29 -5
  65. package/dist/web-admin-credential.js +5 -2
  66. package/dist/web-admin-session-url.js +2 -2
  67. package/dist/worker-row-verdict.d.ts +11 -0
  68. package/dist/worker-row-verdict.js +51 -1
  69. package/dist/workers-rows.d.ts +2 -1
  70. package/dist/workers-rows.js +41 -12
  71. package/dist/zod-unwrap.d.ts +6 -0
  72. package/dist/zod-unwrap.js +14 -7
  73. package/docs/API-SURFACE.md +50 -5
  74. package/docs/CONSUMER-INTEGRATION.md +178 -0
  75. package/llms-full.txt +34 -5
  76. package/llms.txt +6 -3
  77. package/package.json +1 -1
@@ -0,0 +1,247 @@
1
+ /**
2
+ * 包内私有(不进主桶、不进 exports 表):**读嵌入方对象的内核** —— 自有键读 + 定义语义的复制。
3
+ * **读不可信的对象,只问「这个对象自己有没有这个键、值是什么」,不读继承来的值,不让陷阱 / getter 的抛出去;写读出来的副本,不走 `[[Set]]`。**
4
+ *
5
+ * 为什么:`obj.key` 是 `[[Get]]` —— 键不在自有属性上时顺原型链读,`Object.prototype` 被污染成数据值(`Object.prototype.args = ["--evil"]`)就读出注入的值;
6
+ * 对象是 Proxy 时 `get` 陷阱会抛,是会抛的 getter 时也抛;`push` / 下标赋值是 `[[Set]]`,会命中继承的数字键 setter 被吞掉。JSON 解析出来的值只有自有可枚举的数据属性,这些全是 JS 对象面
7
+ * 才有的路 —— 读口在这条路上的答案必须是**确定的、响亮的、读口自己的**(不是引擎的 TypeError、不是被污染的值)。
8
+ *
9
+ * **一只读内核,两种归类**(如实:归类有两种是一致性债,差别只在「自有但不是可枚举数据属性」的键上 —— JSON 面两种逐位同)。**选哪一种归类只看读口交出去的是什么**:
10
+ * 交回**副本**(调用方只读这份副本,读到的就是判过的)⇒ 可以宽;交回**原引用**、作 `x is T` **类型守卫**、或对原值下判决(调用方随后对同一个对象的普通读必须读到判过的那一份 ——
11
+ * 访问器下一次可以答别的、可以抛)⇒ 必须严。
12
+ * · **内核**:{@link readOwnDescriptor} —— 一个键**一次** `getOwnPropertyDescriptor`(缺席时再问一次 `in`),在场与值都只从**这一份**描述符里取({@link valueOfDescriptor}:数据属性取值,
13
+ * 访问器调这份描述符里的 getter);**从不 `[[Get]]`、不问 Proxy 的 `get` 陷阱** —— 「是不是自有」与「值是什么」之间没有第二次读,没有人能在中间删掉自有键、换成 `Object.prototype` 上被污染的同名值。
14
+ * 整容器(对象或数组)只有一只读法 `containerView`:**先定域、再问描述符** —— 一次 `Reflect.ownKeys`,域 = 串键(数组再只留下标键与 `length`),只对域内的键各问一次 `getOwnPropertyDescriptor`,
15
+ * 值同样只从描述符里取。符号键与数组上挂的非下标键(可枚举或隐藏)从来不是成员:不问描述符、不读、不判(校验器解析数组也从不读它们)。
16
+ * · **宽归类**(自有的都在场)—— {@link readKey} / {@link ownValueOf} / {@link ownFieldsOf} / {@link captureStringArray} 的 `wide` / {@link ownElementsOf} / 哈希(`stableStringify`):不可枚举的自有数据键读成在场
17
+ * (整表列成员时同 `Object.keys` 只列可枚举的),访问器调它自己的 getter 一次。{@link readKey} 一个键四种在场(`own` / `inherited` / `absent` / `unreadable`),读者对 `inherited` 怎么办是读者的事。
18
+ * 用户(都交副本 / 值,不交原引用):名单层(读器与判官)/ 传输与身份头(`kind` / 字段袋 / `args` / `env` / `headers` 的成员)/ remote-exec 的判别词 / 未知键扫描 /
19
+ * `salvageEntries` 读条目集合字段(`ownValueOf`;集合里的条目再由校验器读)/ workers 行读口读 `workers` 数组的元素(按校验器解析数组的读法)/ 哈希等「值或缺席」的读者。
20
+ * 闭包注入组(请求面 MCP 条目判官的抄本)里交副本的读法就是这一组。
21
+ * · **严归类**(只收自有、可枚举的数据属性)—— {@link readDeclaredKey} / {@link ownDeclaredValueOf} / {@link ownOrThrow} / {@link ownEntriesOf} / {@link captureJson} / {@link captureStringArray} 的 `strict`,与 `./declared-capture` 的声明键投影:
22
+ * 自有访问器 / 不可枚举的自有键 ⇒ 读不成纯数据(读口答它既有的「读不出」,**不当缺席**,getter 一次都不调);只靠继承 ⇒ 缺席。
23
+ * 用户:令牌声明、一次性迁移的固定键与存在判、fleet 各读口、workers 行读口(`workers` / 行的 `name` / 扣行时拼文档)、`readEffectiveWire` 的载荷袋;
24
+ * 以及交回原引用 / 作类型守卫 / 对原值下判决的读口:`isStringArray` / `isStringRecord` / `isSchedulerRecord`、`readSettingsUnit` 的列表单元与环境变量表、比较器的串集合(`tightenVerdict` 的集合规则)。
25
+ * 内核覆盖声明键读与整容器读;**仍自带读法的读者按名登记**(各自写明契约;普查钉按「文件 → 函数 → 读法 API」逐处数,登记外出现即红):
26
+ * 既有、未经内核的数据读者:`tightenVerdict` 的 `none` 规则(`strictJsonCopy`:对象的不可枚举键跳过、访问器 ⇒ 整份 `unreadable`;数组按 `length` 逐位读描述符 —— `length` 走一次 `[[Get]]`、不可枚举的下标照读)·
27
+ * 被丢条目的身份(`readEntryIdentity`:访问器 ⇒ 当缺席,从不调)· 传输记录读法(`readPlainStringRecord`:自己枚举成员名 `getOwnPropertyNames`,值经 {@link readKey});
28
+ * 不是数据读的:安全判官 `extraBodyUnsafe` 的审计读(`./types`:问「任何自有键上有没有可疑」,含符号键与会抛的描述符,访问器 ⇒ 判不安全,从不调)。
29
+ * 直接用 `[[Get]]` 的几处(不经内核,按名登记):hooks 分类器(`Object.keys` + 成员读;闭包可抄的内建写法,随闭包契约变更收)· `collectDropped` / `collectionSlots`(`./config-fns`:
30
+ * 未知键扫描与条目集合的位置表,自己枚举容器再 `[[Get]]`;既有)· http hook 名单读器与判官的**普通读对拍**(安全轴的名单、判官的 `layers` / `hookVars` 要描述符视图
31
+ * 与普通读两份观测一致才算读到 —— 普通读只作对拍,交出去的值取自描述符那一份;见 `./http-hook-allowlists`)。`stableStringify` 已归零(每个容器经 {@link containerView} 的宽归类列一次成员、
32
+ * 按哈希序从列成员时的描述符取值);http hook 判官经读器读每一层(层的 `source` 与名单同一条双读一致律),调用方的 `layers` / `hookVars` 数组按同一条律核;安全轴的数组(`layers` / `hookVars` / 两张名单)只许是朴素数组(座位的 `isPlainJsonArray` ∧ 经 {@link denseArrayView} 的 `wide` 归类读,`foreign` ⇒ 坏形)。
33
+ * 描述符「是不是访问器」只有一种写法:{@link isAccessorDescriptor}。
34
+ *
35
+ * 其余件:
36
+ * · {@link inspect}:检视的律与句 —— 抛了 ⇒ `ok:false` 带唯一一句 {@link UNINSPECTABLE};全包不在读器里各包一个 `try`、各写一句。要**读错误对象**的 zod 判决只有一种写法:
37
+ * {@link guardedSafeParse}(`safeParse` 与错误对象的整个构造同在守护里);只问 `success` / `data`、从不构造错误对象的判决(令牌判官的两处声明值判)直接用 `inspect`;
38
+ * `parseDeclared` 的守护在它的入口一处(schema 内省、快照递归与校验同在里面,见 `./declared-capture`)。
39
+ * · {@link captureJson}:一份 JSON 形值的**自有键快照**(整棵树):朴素对象 ⇒ 隔离原型({@link COPY_PROTOTYPE})的数据副本、数组 ⇒ 普通数组副本(洞仍是洞),继承来的值进不了副本;
40
+ * 读者要对一棵会被一路读下去又会被改写的值干活时,先拍一张快照再读,不在原对象上边读边改。
41
+ * · {@link captureStringArray}:一份串数组的捕获副本(按下标、自有下标、经内核一次读、非串即坏、不走迭代协议 —— 宽归类,下标上的 getter 调一次);{@link dataDescriptor}:写副本用的零原型描述符。
42
+ * 形状(是不是朴素对象 / 数组)归 `./plain-json-object` 的座位;本模块只管「形状已知之后怎么读成员」。
43
+ */
44
+ import type { z } from "zod";
45
+ /** 撤销 / 读不出的 Proxy 的拒句(`got ` 之后的名词短语)—— **全包唯一的一句**:陷阱抛出来、getter 抛出来、已撤销的 Proxy,读器与描述器都不能因此被带出去。 */
46
+ export declare const UNINSPECTABLE = "an object that could not be inspected (a proxy trap threw)";
47
+ /** 一次安全检视的结果:读出来的值,或「检视不了」那一句。 */
48
+ export type Inspected<T> = {
49
+ readonly ok: true;
50
+ readonly value: T;
51
+ } | {
52
+ readonly ok: false;
53
+ readonly sentence: string;
54
+ };
55
+ /**
56
+ * 唯一的**安全检视内核**:读器与描述器要碰不可信的值(`Array.isArray` 对已撤销的 Proxy 抛、`get` / 原型 / 描述符陷阱抛、会抛的自有 getter)都经它 ——
57
+ * 「检视不了」的**律与句都单源**:抛了 ⇒ `ok:false` 带 {@link UNINSPECTABLE} 那一句。
58
+ */
59
+ export declare function inspect<T>(read: () => T): Inspected<T>;
60
+ /** 一个键在一个对象上怎么在场(四种,闭集)。 */
61
+ export type KeyRead = {
62
+ readonly presence: "own";
63
+ readonly value: unknown;
64
+ } | {
65
+ readonly presence: "inherited";
66
+ } | {
67
+ readonly presence: "absent";
68
+ } | {
69
+ readonly presence: "unreadable";
70
+ };
71
+ /**
72
+ * 一份自有描述符的值(全包唯一的取值步):数据属性 ⇒ `value`;访问器 ⇒ 调**这份描述符里的** getter 一次(`this` 是被读的对象;只有 setter ⇒ `undefined`)—— 不经 `[[Get]]`、不问 `get` 陷阱。
73
+ * getter 抛 ⇒ 照抛(调用方在 {@link inspect} 里调它)。描述符是引擎交回的完整描述符(字段全是自有的),所以读 `get` 不碰原型链。
74
+ */
75
+ export declare const valueOfDescriptor: (record: object, d: PropertyDescriptor) => unknown;
76
+ /**
77
+ * 读一个键(内核 {@link readOwnDescriptor} 的宽归类):自有 ⇒ `own` 带值 —— 值只从那一份描述符里来(数据属性取值,不可枚举的也照读;访问器调**它自己的** getter 一次;**不问 `get` 陷阱**);
78
+ * 只靠继承 ⇒ `inherited`(不读值);都没有 ⇒ `absent`;检视就抛(已撤销的 Proxy、`getOwnPropertyDescriptor` / `has` 陷阱抛、自有 getter 抛)⇒ `unreadable`。从不抛。
79
+ */
80
+ export declare function readKey(record: object, key: PropertyKey): KeyRead;
81
+ /** 一个字段的值,**只读自有属性**:继承与缺席都是 `undefined`,读不出 ⇒ `ok:false`(调用方各自决定怎么办、不再各包一层)。由 {@link readKey} 派生。 */
82
+ export declare function ownValueOf(record: object, key: string): Inspected<unknown>;
83
+ /** 按顺序读若干字段,**第一个读不出的就停**(后面的一个不读),整体读不出向上传;交出的袋是零原型、定义语义写入。 */
84
+ export declare function ownFieldsOf(record: object, keys: readonly string[]): Inspected<Readonly<Record<string, unknown>>>;
85
+ /**
86
+ * 包自有查表(`Partial<Record<域名, 行>>` 一类的常量表)的一行:**表自己的行**,没有就 `undefined` —— 行缺席时不从原型链上借一行(`Object.prototype.<域名>` 被污染成数据值时,
87
+ * `table[域名]` 会把它读成「这张表给这个域的行」:写权限的角色、扩展命名空间、未知键扫描的已知键表)。表是包自己的普通对象(没有读不出的问题),所以不经 {@link inspect}。
88
+ */
89
+ export declare function ownRow<V>(table: Readonly<Partial<Record<string, V>>>, key: string): V | undefined;
90
+ /** 抛出值若是本内核铸的 {@link UninspectableError} ⇒ 它的句子,否则(别人的错 / 随便什么原始值 / 读不出的对象)⇒ `undefined`。只靠身份,从不碰抛出值的反射面。 */
91
+ export declare function sentenceOfMinted(thrown: unknown): string | undefined;
92
+ /** 读不出时 {@link ownOrThrow} 抛的类型:是 `TypeError`(调用方给的对象读不出是调用方的错),message 是全包唯一那一句(或坏形自己的句子:环 / 非纯数据)。
93
+ * 识别它**不用** `instanceof`、取它的句子**不读** `.message` —— 一律走 {@link sentenceOfMinted}。 */
94
+ export declare class UninspectableError extends TypeError {
95
+ constructor(sentence?: string);
96
+ }
97
+ /**
98
+ * 描述符是访问器?—— 描述符对象是寻常对象,它的字段**只认自有的**:数据描述符没有自有的 `get` / `set`,继承来的不算(`Object.prototype.get` 被污染成函数时,
99
+ * `d.get !== undefined` 会把每个数据属性判成访问器,整个读口对合法的 JSON 拒服务)。全包问「是不是访问器 / 是不是数据属性」只用这一只(引擎交回的描述符恒完整:
100
+ * 数据属性有自有的 `value` / `writable`,访问器有自有的 `get` / `set`,所以「不是访问器」就是「是数据属性」)。
101
+ */
102
+ export declare const isAccessorDescriptor: (d: PropertyDescriptor) => boolean;
103
+ /** {@link readKey} 再多一种答案:`hidden` —— 键是自有的、但**不可枚举或是访问器**(读不成纯数据的自有键)。围栏处它不是「缺席」:校验器按名读它能读到。 */
104
+ export type DeclaredKeyRead = KeyRead | {
105
+ readonly presence: "hidden";
106
+ };
107
+ /**
108
+ * 读一个**声明键**(读器声明要读的那个键;内核 {@link readOwnDescriptor} 的严归类,与 {@link readKey} 同一读):自有、可枚举的数据属性 ⇒ `own` 带 `value`(不调 getter、不问 `get` 陷阱);
109
+ * 只靠继承 ⇒ `inherited`、缺席 ⇒ `absent`(调用方都当缺席;缺席时问过一次 `in`:`has` 陷阱抛的 Proxy 是读不出,不是缺席);
110
+ * 自有但不可枚举、或是访问器 ⇒ `hidden`(调用方当「读不成纯数据」整份拒,**不当缺席**,getter 一次都不调);读不出 ⇒ `unreadable`。从不抛。
111
+ */
112
+ export declare function readDeclaredKey(record: object, key: string): DeclaredKeyRead;
113
+ /**
114
+ * 一个**固定键**的值(描述符律,与 {@link readDeclaredKey} 同一只核):自有数据属性 ⇒ 描述符里的值(不调 getter、不问 `get` 陷阱);只靠继承 / 缺席 ⇒ `undefined`;
115
+ * 自有访问器 / 不可枚举的自有键 ⇒ `ok:false` 带 {@link NOT_PLAIN_DATA}(**不当缺席**,getter 零次);读不出 ⇒ 带 {@link UNINSPECTABLE}。从不抛。
116
+ * 给令牌声明、迁移的固定键读、workers 行读口:它们读的是「调用方交来的 JSON」,JSON 铸不出访问器 / 隐藏键。(`ownValueOf` 是同一读的宽归类 —— 隐藏键照读、访问器调一次,闭包注入组里的那一只。)
117
+ */
118
+ export declare function ownDeclaredValueOf(record: object, key: string): Inspected<unknown>;
119
+ /** {@link ownDeclaredValueOf},读不出 / 不是纯数据就抛 {@link UninspectableError}(带各自那一句)。给没有自己失败臂的读者(迁移、令牌判官);有失败臂的读者用 `ownDeclaredValueOf`。 */
120
+ export declare function ownOrThrow(record: object, key: string): unknown;
121
+ /**
122
+ * 一个对象的**键值对**(自有可枚举串键,顺序同 `Object.entries`;每个成员一份描述符、值只从它里面取,见 `containerView`:不调 getter、不触发 Proxy 的 `get` 陷阱)—— 给「把整个载荷 / 文档集拍成一只袋」的读者。
123
+ * 自有串键里有不可枚举的或访问器 ⇒ `ok:false` 带 {@link NOT_PLAIN_DATA}(此前用 `Object.entries`:不可枚举的自有键被静默当缺席,访问器被调一次);读不出 ⇒ `ok:false` 带 {@link UNINSPECTABLE}。
124
+ */
125
+ export declare function ownEntriesOf(record: object): Inspected<Array<readonly [string, unknown]>>;
126
+ /**
127
+ * 一个数组的**元素**,按校验器解析数组的读法读(zod 按下标读元素、从不读非下标键):自有下标,升序 —— {@link containerView} 的 `wide` 归类:先定域、域内每键一次描述符,
128
+ * **只看下标键**,每个下标的值经内核的取值步(与 {@link readKey} 同一步:数据下标取值、不可枚举的下标照读、访问器下标调它自己的 getter 一次,不问 `get` / `has` 陷阱);
129
+ * 洞不是元素(不出现);数组上挂的非下标键(可枚举或隐藏,例:响应式框架挂的 `__ob__`)不是元素、也不构成「读不出」。
130
+ * 读不出(`ownKeys` / `getOwnPropertyDescriptor` 陷阱抛、下标的 getter 抛)⇒ `ok:false` 带 {@link UNINSPECTABLE}(整份)。
131
+ */
132
+ export declare function ownElementsOf(array: readonly unknown[]): Inspected<Array<readonly [index: number, value: unknown]>>;
133
+ /** {@link ownOrThrow} 再把值拍成**自有键快照**({@link captureJson}):字段值本身是对象 / 数组时,调用方之后对它做的任何事(交给校验器、`includes`、取成员)都落在副本上,不再触发原值的陷阱 / getter;
134
+ * 值读不出 / 是环 / 不是纯数据 ⇒ 抛 {@link UninspectableError}(带各自的句子)。原始值原样。给「读一个声明、再拿它做事」的读者(令牌声明)。 */
135
+ export declare function ownJsonOrThrow(record: object, key: string): unknown;
136
+ /** 跑 `body`;它里面的 {@link ownOrThrow} 读不出(抛 {@link UninspectableError})⇒ 答 `unreadable()`。别的抛(不是我们的)照常往外传。给「读不出 ⇒ 我自己的 fail-closed 答案」的读者:读法写成直线(`ownOrThrow`),失败臂只在入口写一处。 */
137
+ export declare function orWhenUninspectable<T>(body: () => T, unreadable: () => T): T;
138
+ /** {@link guardedSafeParse} 的判决:通过 ⇒ 数据;不过 ⇒ `error` 已经在守护里读出来了。纯数据。 */
139
+ export type GuardedVerdict<T> = {
140
+ readonly success: true;
141
+ readonly data: T;
142
+ } | {
143
+ readonly success: false;
144
+ readonly error: z.ZodError;
145
+ };
146
+ /**
147
+ * 要读错误对象的 zod 判决里「校验过程抛 ⇒ 读不出」的**唯一写法**({@link inspect} 用在 zod 判决上;只问 `success` / `data` 的判决不构造错误对象,直接 `inspect`):`run` 是一次 `safeParse`(调用点照写 `X.safeParse(…)`,不改形),它与判决里
148
+ * **错误对象的整个构造**在同一只守护里 —— 首读 `error`(拼 issue 句子:`received …` 会读输入的 `constructor.name`,另一 realm 的怪形值、被污染的运行时在这一步抛)
149
+ * 与它的 `message`(`JSON.stringify(issues)`:issue 的 `params` 里会抛的 getter、环在这一步抛)。zod 4.4 在 `safeParse` 里就把两步做完,4.6 两步都是首读才做:
150
+ * 只守 `safeParse` 那一行的话,同一份输入在两版 zod 上一个答「读不出」、一个把引擎的错抛出去(或在后面的脱敏里抛)。
151
+ * 调用方对错误对象的处置(`finish`,例:脱敏 —— 它要读 issue 的每个成员,`params` 里不可枚举的会抛 getter `JSON.stringify` 跳过、脱敏不跳过)也在同一只守护里:
152
+ * 错误对象读不完 ⇒ 判决读不出,不论卡在构造还是处置。
153
+ * 抛了 ⇒ `ok:false`(调用方给它自己那一句「读不出」);不抛 ⇒ `ok:true` 带判决(`error` 已经过 `finish`)。
154
+ */
155
+ export declare function guardedSafeParse<T>(run: () => z.ZodSafeParseResult<T>, finish?: (error: z.ZodError) => z.ZodError): Inspected<GuardedVerdict<T>>;
156
+ /**
157
+ * 同一个值上**已经读过**的声明键(键名 → 那一次的读数;判别联合读过的判别键):整份捕获列这个值的成员时,这些键**由那一次读数定在场与值、不再问描述符**
158
+ * (`own` ⇒ 成员,值是那次的读数;其余 ⇒ 不是成员)—— 所以快照里的判别词恒是选臂的那个词,第二次读不存在,也就影响不了接受与否。只对同一个值有效。
159
+ */
160
+ export type PriorReads = ReadonlyMap<string, DeclaredKeyRead>;
161
+ export declare const NO_PRIOR_READS: PriorReads;
162
+ /** {@link containerView} 的读数:成员(键与它**那一份**自有描述符 —— 值由调用方经 {@link valueOfDescriptor} 在它要的时刻取)、数组自有 `length` 的值(对象恒 `undefined`),
163
+ * 与 `foreign` —— 同一次 `Reflect.ownKeys` 里有没有**域外**的自有键(符号键;数组上既不是下标也不是 `length` 的串键)。域外的键不问描述符、不是成员;要「只许普通数组」的读者(安全轴)据它拒。 */
164
+ export interface ContainerView {
165
+ readonly members: ReadonlyArray<readonly [key: string, descriptor: PropertyDescriptor]>;
166
+ readonly length: unknown;
167
+ readonly foreign: boolean;
168
+ }
169
+ /**
170
+ * 一个容器的**自有视图**(全包唯一的整容器读):**先定域、再问描述符** —— 一次 `Reflect.ownKeys`(只问 `ownKeys` 陷阱)列出自有键,筛出**域**:串键(符号键不是任何读口声明的键,
171
+ * 不在域内);数组再只留**下标键**与 `length`(挂在数组上的非下标键 —— 可枚举或隐藏,例:响应式框架挂的 `__ob__` —— 从来不是元素);然后**只对域内的键**逐个问一次
172
+ * `getOwnPropertyDescriptor`(交回 `undefined` ⇒ 不是成员)。域外的键一次都不问描述符 —— 它们的描述符陷阱抛也不构成「读不出」。每个成员恰一份描述符,
173
+ * 之后不再对被读的对象做任何属性读(没有第二次 `[[Get]]`,所以没有人能在两次读之间改它),值只从这份描述符里取。数组成员按下标升序(校验器按下标读的顺序)。两种归类,与逐键读的内核同一对:
174
+ * · `strict`(整容器捕获与交回原引用 / 类型守卫的读口:`captureJson` / `ownEntriesOf` / `captureStringArray` 的 `strict`):成员 = 对象的自有串键 / 数组的下标;其中有不可枚举的、或是访问器的 ⇒ 抛 {@link UninspectableError}(NOT_PLAIN_DATA)
175
+ * —— 「自有但读不成纯数据」不是「缺席」,getter 一次都不调;成员都是数据属性。
176
+ * · `wide`(交回副本 / 值的读口:`ownElementsOf` / `captureStringArray` 的 `wide` / `stableStringify`):成员 = 数组的下标(不可枚举的也算 —— 按下标读的校验器读得到)/ 对象的**可枚举**串键(同 `Object.keys`);
177
+ * 访问器成员的值由调用方经取值步调这份描述符里的 getter(一次)。
178
+ * `prior`({@link PriorReads}):已经读过的键由那一次读数定(排在成员最前),列成员时跳过、不再问描述符。
179
+ * 读不出(`ownKeys` / 域内键的 `getOwnPropertyDescriptor` 陷阱抛、撤销的 Proxy)⇒ 抛 {@link UninspectableError}。
180
+ */
181
+ export declare const containerView: (record: object, isArray: boolean, classification: "strict" | "wide", prior?: PriorReads) => ContainerView;
182
+ /**
183
+ * 一个**稠密数组**的整容器读数({@link containerView}):`length` 是安全非负整数、自有下标正好 `0 … length-1`(不顺原型链读继承的数字键;`length` 很大的稀疏数组立即判否,不逐位扫)
184
+ * ⇒ 每个下标**那一份**描述符(升序;值由调用方经 {@link valueOfDescriptor} 取)与 `foreign`(见 {@link ContainerView});否则 `undefined`。读不出 ⇒ 抛 {@link UninspectableError}(调用方在 {@link inspect} 里调)。
185
+ * 串数组的捕获({@link captureStringArray})与安全轴的「只许普通数组」(`./http-hook-allowlists`)都从这一只取稠密判据,不各写一份。
186
+ */
187
+ export declare function denseArrayView(array: readonly unknown[], classification: "strict" | "wide"): {
188
+ readonly descriptors: readonly PropertyDescriptor[];
189
+ readonly foreign: boolean;
190
+ } | undefined;
191
+ /** {@link captureJson} 的两句坏形(与「检视不了」那一句并列,各只在这里拼一次):环 —— JSON 没有环;非纯数据 —— 只有朴素对象 / 数组 / 原始值是纯数据。 */
192
+ export declare const CYCLIC_VALUE = "a value that refers to itself (a JSON document has no cycles)";
193
+ export declare const NOT_PLAIN_DATA = "a value that is not plain data (a class instance, a Map, a Date, a function, an object with a hidden \u2014 non-enumerable \u2014 or an accessor own property \u2026 \u2014 only plain objects, arrays and primitives are)";
194
+ /**
195
+ * 一份纯数据值的**自有键快照**(整棵树;每个容器**一次**列成员、每个成员一份描述符、只从描述符取值 —— 见 `containerView`:不调任何 getter、不触发 `get` 陷阱,继承来的值进不来,没有「前一个 getter 改了后面的键」这回事):
196
+ * · 朴素对象(座位的 `plain`)⇒ 数据副本,键 = 自有可枚举的串键(符号键不进;`JSON.parse` 铸得出的自有 `__proto__` 键作为自有数据属性保留);**自有的串键里有不可枚举的、或是访问器的 ⇒ 整份拒**(NOT_PLAIN_DATA),不静默丢、不读;
197
+ * 副本默认**隔离原型**({@link COPY_PROTOTYPE}:读者之后在副本上读没有继承可说),`copyAs: "ordinary"` 时是寻常对象(交回给调用方的那一份);
198
+ * · 数组 ⇒ 同长的普通数组副本,元素只拷自有下标,**洞仍是洞**(按自有可枚举键走,不按 `length` 逐位扫:`length` 很大的稀疏数组不拖死读者);
199
+ * · 原始值原样;
200
+ * · **没有字面深度上限**:JSON 往返能成的东西都要能拷,实现是迭代的(显式栈),深度只受内存限制;
201
+ * · 共享引用(菱形)只拷一次、副本里仍共享;
202
+ * · `prior`(可选,{@link PriorReads}):根上那个值已经读过的键 —— 它们的在场与值取那一次的读数,不再问描述符(判别联合选中整份捕获的臂时,判别词就是选臂的词);
203
+ * · 坏形只有三种,各一句,`ok:false`、不抛:**环**({@link CYCLIC_VALUE};再遇到进行中的节点)· **非纯数据**({@link NOT_PLAIN_DATA}:`Map` / `Date` / 类实例 / 函数 / 带隐藏自有键的对象,不论在哪一层)·
204
+ * **读不出**({@link UNINSPECTABLE}:陷阱抛、撤销的 Proxy)。
205
+ * 副本是新对象,读者之后在副本上读 / 改都不碰调用方的值,也不受 `Object.prototype` / `Array.prototype` 污染影响。
206
+ */
207
+ export declare function captureJson(v: unknown, copyAs?: "isolated" | "ordinary", prior?: PriorReads): Inspected<unknown>;
208
+ /**
209
+ * 捕获出来的副本的**原型**(所有 {@link captureJson} 副本与按声明键投影的副本共用这一只):**没有继承来的成员**(`Object.prototype` 被污染成数据值的同名键不在它的原型链上,也没有 `constructor`),
210
+ * 但仍答寻常对象对「转原始值」的两问(`toString` / `valueOf`,不可枚举)。为什么不是零原型:零原型对象没有这两只,校验器对**不是字符串却带 `length` 的值**做长度检查时会把它转成原始值 ——
211
+ * 寻常对象能转(得到 `"[object Object]"`,于是出一条 `too_small`),零原型对象抛引擎的 `TypeError`;读者拿副本去校验,答案就和拿原对象校验不一样了(拒因退成「读不出」、令牌判官抛)。
212
+ */
213
+ export declare const COPY_PROTOTYPE: object;
214
+ /** 一个以 {@link COPY_PROTOTYPE} 为原型的空对象(副本的袋)。 */
215
+ export declare const isolatedObject: () => Record<string, unknown>;
216
+ /**
217
+ * 包自己造的**空文档**(「域文档缺席 ⇒ 按空文档校验、落默认值」的那一份;迁移里的各种累加容器也是它):原型是 {@link COPY_PROTOTYPE}(和所有副本同一只)。交给校验器读它声明的键时,
218
+ * `Object.prototype` 上被污染成数据值的同名键不会被读成「文档里写着的」(带 `Object.prototype` 的 `{}` 会)。调用方给的文档不归这里管 —— 那是调用方的值。
219
+ */
220
+ export declare function emptyDocument(): Record<string, unknown>;
221
+ /**
222
+ * 往包自己的数组末尾追加一项,**定义语义**。走它的是这七处:整容器读的成员表({@link containerView})、快照的遍历栈({@link captureJson})、`extraBodyUnsafe` 的遍历栈(`./types` 两臂)、
223
+ * `readWorkersRows` 的留下(两臂)/ 扣下两张表(`./workers-rows`);包内其余数组追加仍是 `push`(本版未收)。`push` / 下标赋值是 `[[Set]]` —— `Object.prototype`(或 `Array.prototype`)上被污染出数字键的 setter 时,
224
+ * 新下标不是自有的,`[[Set]]` 顺原型链找到那只 setter、把这一项吞掉(之后读那一格还会读到污染 getter 的值)。`Object.defineProperty` 直接在数组上定义自有下标,`length` 随之更新。
225
+ */
226
+ export declare function appendOwn<T>(list: T[], value: T): void;
227
+ /** 数据属性描述符(可写 / 可枚举 / 可配置),**零原型**:不继承 `Object.prototype` 上被污染的 `get` / `set` 等键,也不靠对象字面量。 */
228
+ export declare function dataDescriptor(value: unknown): PropertyDescriptor;
229
+ /**
230
+ * 一份**串数组的捕获副本**;不是串数组 ⇒ `undefined`(调用方据此读成坏形 —— 名单读成 `[]` 并点名,`args` 丢键并进 `lost`,守卫答 `false`)。
231
+ * 按那一只整容器读({@link containerView})读:`length` 与每个自有下标各一份描述符,两种归类与容器读同一对,**按交出去的是什么选**:
232
+ * · `strict`(交回原引用 / 类型守卫 / 对原值下判决:`isStringArray`、设置单元的列表、比较器的串集合):下标是访问器或不可枚举 ⇒ 不是串数组(getter 一次都不调)——
233
+ * 判为真,调用方随后对**同一个数组**的普通读读到的就是判过的那一份(访问器下一次可以答别的、可以抛);
234
+ * · `wide`(交回副本:请求面 `args`):不可枚举的下标照读,访问器下标调它的 getter 一次 —— 调用方只读这份副本,读到的就是判过的。
235
+ * 其余同一张表:不是数组 / `length` 不是安全非负整数 / 有洞(自有下标不正好是 `0 … length-1` —— 不顺原型链读继承的数字键;`length` 很大的稀疏数组立即判坏,不逐位扫)/
236
+ * 条目不是串 / 读不出(结构陷阱抛、getter 抛)⇒ `undefined`。副本用 `Object.defineProperty` + {@link dataDescriptor} 写(`push` / 下标赋值是 `[[Set]]`,会命中继承的数字键 setter);
237
+ * 不走迭代协议(数组实例上被替换的 `Symbol.iterator` 供不出别的条目);交出去的是副本,调用方之后改原数组,副本不变。
238
+ */
239
+ export declare function captureStringArray(v: unknown, classification: "strict" | "wide"): string[] | undefined;
240
+ /** 条目是不是串(串数组读法的条目判据;安全轴的串数组同用这一只)。 */
241
+ export declare const isStringEntry: (entry: unknown) => entry is string;
242
+ /**
243
+ * **稠密数组的捕获副本 —— 全包唯一的一份拷贝循环**({@link captureStringArray} 与安全轴的朴素数组读法 `./http-hook-allowlists` 都调它;调用方先问座位判数组):
244
+ * {@link denseArrayView} 取稠密判据与 `foreign`;`foreign: "refuse"` ⇒ 有域外自有键就不读元素、答 `undefined`(安全轴),`"ignore"` ⇒ 不看;
245
+ * 元素值逐个经取值步从那一份描述符取,逐个过 `isEntry`(不过即停、后面的不读);副本用 `Object.defineProperty` + {@link dataDescriptor} 写(定义语义)。读不出 ⇒ `undefined`。
246
+ */
247
+ export declare function captureDenseArray<T>(v: readonly unknown[], classification: "strict" | "wide", isEntry: (entry: unknown) => entry is T, foreign: "refuse" | "ignore"): T[] | undefined;