@lqc123qwe/car-runtime 1.9.0 → 1.10.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 (176) hide show
  1. package/README.md +17 -1
  2. package/dist/SHA256SUMS +1 -0
  3. package/dist/authz/authz.d.ts +44 -0
  4. package/dist/authz/authz.js +65 -0
  5. package/dist/car-runtime-1.10.0.tgz +0 -0
  6. package/dist/car-runtime-1.10.0.tgz.sig.bundle +1 -0
  7. package/dist/cli.d.ts +1 -0
  8. package/dist/cli.js +825 -0
  9. package/dist/dx/doctor.d.ts +62 -0
  10. package/dist/dx/doctor.js +127 -0
  11. package/dist/governance/dump.d.ts +47 -0
  12. package/dist/governance/dump.js +17 -0
  13. package/dist/host/facade.d.ts +13 -0
  14. package/dist/host/facade.js +154 -0
  15. package/dist/host/hostGateway.d.ts +117 -0
  16. package/dist/host/hostGateway.js +65 -0
  17. package/dist/host/mappings.d.ts +27 -0
  18. package/dist/host/mappings.js +52 -0
  19. package/dist/host/stdio.d.ts +14 -0
  20. package/dist/host/stdio.js +83 -0
  21. package/dist/kernel/context.d.ts +76 -0
  22. package/dist/kernel/context.js +203 -0
  23. package/dist/kernel/events.d.ts +37 -0
  24. package/dist/kernel/events.js +82 -0
  25. package/dist/load/config.d.ts +79 -0
  26. package/dist/load/config.js +285 -0
  27. package/dist/load/loader.d.ts +72 -0
  28. package/dist/load/loader.js +162 -0
  29. package/dist/load/registry.d.ts +44 -0
  30. package/dist/load/registry.js +58 -0
  31. package/dist/load/report.d.ts +98 -0
  32. package/dist/load/report.js +301 -0
  33. package/dist/load/sigGate.d.ts +22 -0
  34. package/dist/load/sigGate.js +68 -0
  35. package/dist/load/sign.d.ts +25 -0
  36. package/dist/load/sign.js +47 -0
  37. package/dist/load/verifier.d.ts +35 -0
  38. package/dist/load/verifier.js +56 -0
  39. package/dist/loop/goal.d.ts +31 -0
  40. package/dist/loop/goal.js +34 -0
  41. package/dist/loop/recover.d.ts +17 -0
  42. package/dist/loop/recover.js +39 -0
  43. package/dist/loop/stop.d.ts +79 -0
  44. package/dist/loop/stop.js +151 -0
  45. package/dist/mcp/gateway.d.ts +96 -0
  46. package/dist/mcp/gateway.js +69 -0
  47. package/dist/mcp/httpClient.d.ts +27 -0
  48. package/dist/mcp/httpClient.js +196 -0
  49. package/dist/mcp/stdioClient.d.ts +8 -0
  50. package/dist/mcp/stdioClient.js +73 -0
  51. package/dist/ptc/budget.d.ts +21 -0
  52. package/dist/ptc/budget.js +36 -0
  53. package/dist/ptc/erasable.d.ts +14 -0
  54. package/dist/ptc/erasable.js +27 -0
  55. package/dist/ptc/runCode.d.ts +65 -0
  56. package/dist/ptc/runCode.js +140 -0
  57. package/dist/ptc/schemaRender.d.ts +15 -0
  58. package/dist/ptc/schemaRender.js +90 -0
  59. package/dist/ptc/sdk.d.ts +27 -0
  60. package/dist/ptc/sdk.js +23 -0
  61. package/dist/ptc/worker-entry.d.ts +1 -0
  62. package/dist/ptc/worker-entry.js +71 -0
  63. package/dist/release-audit.jsonl +4 -0
  64. package/dist/runtime-core/chatStep.d.ts +40 -0
  65. package/dist/runtime-core/chatStep.js +104 -0
  66. package/dist/runtime-core/credentials.d.ts +49 -0
  67. package/dist/runtime-core/credentials.js +118 -0
  68. package/dist/runtime-core/errors.d.ts +30 -0
  69. package/dist/runtime-core/errors.js +36 -0
  70. package/dist/runtime-core/llm.d.ts +76 -0
  71. package/dist/runtime-core/llm.js +553 -0
  72. package/dist/runtime-core/redaction.d.ts +39 -0
  73. package/dist/runtime-core/redaction.js +79 -0
  74. package/dist/runtime-core/telemetry.d.ts +88 -0
  75. package/dist/runtime-core/telemetry.js +332 -0
  76. package/dist/runtime-core/tools.d.ts +15 -0
  77. package/dist/runtime-core/tools.js +12 -0
  78. package/dist/runtime-core/trace.d.ts +55 -0
  79. package/dist/runtime-core/trace.js +137 -0
  80. package/dist/runtime-core/types.d.ts +84 -0
  81. package/dist/runtime-core/types.js +13 -0
  82. package/dist/sandbox/sandbox.d.ts +68 -0
  83. package/dist/sandbox/sandbox.js +153 -0
  84. package/dist/sbom.json +263 -0
  85. package/dist/seam.d.ts +21 -0
  86. package/dist/seam.js +20 -0
  87. package/dist/security/secrets-baseline.d.ts +43 -0
  88. package/dist/security/secrets-baseline.js +176 -0
  89. package/dist/security/secrets.d.ts +45 -0
  90. package/dist/security/secrets.js +138 -0
  91. package/dist/session/export.d.ts +55 -0
  92. package/dist/session/export.js +81 -0
  93. package/dist/session/fork.d.ts +51 -0
  94. package/dist/session/fork.js +63 -0
  95. package/dist/session/format.d.ts +21 -0
  96. package/dist/session/format.js +49 -0
  97. package/dist/session/indexStore.d.ts +44 -0
  98. package/dist/session/indexStore.js +265 -0
  99. package/dist/session/log.d.ts +79 -0
  100. package/dist/session/log.js +157 -0
  101. package/dist/session/store.d.ts +9 -0
  102. package/dist/session/store.js +37 -0
  103. package/dist/telemetry/metrics.d.ts +25 -0
  104. package/dist/telemetry/metrics.js +26 -0
  105. package/package.json +17 -1
  106. package/src/seam.ts +21 -0
  107. package/.gitattributes +0 -11
  108. package/.github/workflows/ci.yml +0 -293
  109. package/.github/workflows/release.yml +0 -54
  110. package/adr/ADR-001.md +0 -4
  111. package/adr/ADR-002.md +0 -5
  112. package/adr/ADR-003.md +0 -35
  113. package/adr/host-onboarding.md +0 -68
  114. package/adr/mlps-audit-checklist.md +0 -41
  115. package/adr/win32-spike.md +0 -45
  116. package/docs/plugin-authoring.md +0 -82
  117. package/native/landlock-run/Makefile +0 -19
  118. package/native/landlock-run/landlock-run.c +0 -162
  119. package/scripts/contract-check.ts +0 -56
  120. package/scripts/invariant-n1.ts +0 -96
  121. package/scripts/package-check.ts +0 -29
  122. package/scripts/ptc-baseline/run-baseline.ts +0 -118
  123. package/scripts/release-artifacts.ts +0 -111
  124. package/scripts/release-pipeline.ts +0 -245
  125. package/scripts/secrets-baseline.ts +0 -33
  126. package/scripts/secrets-scan.ts +0 -56
  127. package/scripts/win32-ffi-debug.ts +0 -143
  128. package/scripts/win32-koffi-spike.ts +0 -537
  129. package/test/contract/eventmap.golden.json +0 -7
  130. package/test/fixtures/hello-plugin.ts +0 -5
  131. package/test/kernel.spec.ts +0 -136
  132. package/test/registry-e2e/run-e2e.ts +0 -213
  133. package/test/s11.spec.ts +0 -129
  134. package/test/s12.spec.ts +0 -135
  135. package/test/s13.spec.ts +0 -117
  136. package/test/s14.spec.ts +0 -117
  137. package/test/s15.spec.ts +0 -80
  138. package/test/s16.spec.ts +0 -133
  139. package/test/s17.spec.ts +0 -102
  140. package/test/s18.spec.ts +0 -81
  141. package/test/s19.spec.ts +0 -138
  142. package/test/s2.spec.ts +0 -245
  143. package/test/s20.spec.ts +0 -241
  144. package/test/s21.spec.ts +0 -231
  145. package/test/s22-m7-store-format.spec.ts +0 -135
  146. package/test/s23-m7-export-index.spec.ts +0 -189
  147. package/test/s24-signature-gate.spec.ts +0 -185
  148. package/test/s25-m8-runtime-core.spec.ts +0 -600
  149. package/test/s26-signature-closeout.spec.ts +0 -349
  150. package/test/s27-host-load-wiring.spec.ts +0 -134
  151. package/test/s28-session-index-followup.spec.ts +0 -236
  152. package/test/s29-otel-producer.spec.ts +0 -252
  153. package/test/s3.spec.ts +0 -179
  154. package/test/s30-release-artifacts.spec.ts +0 -127
  155. package/test/s31-real-model-wiring.spec.ts +0 -329
  156. package/test/s32-telemetry-mcp-ptc.spec.ts +0 -218
  157. package/test/s33-anthropic-adapter.spec.ts +0 -354
  158. package/test/s34-mcp-remote-transport.spec.ts +0 -250
  159. package/test/s35-config-ts-zod.spec.ts +0 -145
  160. package/test/s36-host-tool-surface.spec.ts +0 -250
  161. package/test/s37-projection-dedupe.spec.ts +0 -161
  162. package/test/s38-config-jiti.spec.ts +0 -116
  163. package/test/s39-otlp-span-semantics.spec.ts +0 -100
  164. package/test/s4.spec.ts +0 -169
  165. package/test/s40-metrics-cumulative.spec.ts +0 -67
  166. package/test/s41-mcp-serve-turn-span.spec.ts +0 -148
  167. package/test/s42-traceparent-propagation.spec.ts +0 -415
  168. package/test/s43-remote-http-traceparent.spec.ts +0 -262
  169. package/test/s5.spec.ts +0 -95
  170. package/test/s6.spec.ts +0 -169
  171. package/test/s7.spec.ts +0 -136
  172. package/test/s7b-baseline.spec.ts +0 -20
  173. package/test/s9.spec.ts +0 -89
  174. package/test/sandbox-escape/j17-orchestrate.sh +0 -30
  175. package/test/sandbox-escape/run-matrix.sh +0 -98
  176. package/tsconfig.json +0 -18
@@ -1,185 +0,0 @@
1
- /**
2
- * M5-S28 · 装载签名门(sigGate + loadPlugins verify 阶段 + ReloadManager 透传)
3
- *
4
- * 覆盖(ADR-003 fail-closed 分级 / DEC-1 ② warn 缺省 / S20 §1 零内容计数):
5
- * - warn 缺签:放行 + CAR-W-SIG 横幅(含 fp 指纹)+ confirmed=no 计数
6
- * - unsignedAllow:confirmed=yes 改写(显式确认豁免动作),横幅保留
7
- * - enforce 缺签:verify FAIL + 空 plugins + 后续 SKIPPED + car_load_total failed
8
- * - 有签名验签失败:硬拒绝——unsignedAllow 亦不可放行(ADR-003 第一级)
9
- * - 好签名:静默放行,零签名计数
10
- * - car_load_total{result=ok} 逐插件计数
11
- * - ReloadManager.reload signature 透传(enforce FAIL)
12
- * - verifyPluginFile 单文件口径(car run 直载门同源)+ gateDepsFromEnv env 通道映射
13
- */
14
- import { test } from 'node:test'
15
- import assert from 'node:assert/strict'
16
- import { mkdtempSync, writeFileSync, readFileSync, rmSync } from 'node:fs'
17
- import { tmpdir } from 'node:os'
18
- import { join } from 'node:path'
19
- import { createHash, generateKeyPairSync, sign } from 'node:crypto'
20
- import { loadPlugins, ReloadManager } from '../src/load/report.ts'
21
- import { verifyPluginFile, gateDepsFromEnv } from '../src/load/sigGate.ts'
22
- import { createCounters, assertZeroContent } from '../src/telemetry/metrics.ts'
23
- import type { LoadReportVO } from '../src/load/report.ts'
24
-
25
- // ==================== fixture(抄 s6 密钥生成 + s20 临时目录模式) ====================
26
-
27
- const PLUGIN_BODY = (tool: string) =>
28
- `export default function apply(api) {\n api.registerTool({ name: '${tool}', run: async () => 'ok' })\n}\n`
29
-
30
- function makePlugin(dir: string, file: string, manifest: Record<string, unknown>, tool: string): string {
31
- const p = join(dir, file)
32
- writeFileSync(p, `export const manifest = ${JSON.stringify(manifest)}\n${PLUGIN_BODY(tool)}\n`)
33
- return p
34
- }
35
-
36
- function withTempDir(name: string, fn: (dir: string) => Promise<void> | void): Promise<void> {
37
- const dir = mkdtempSync(join(tmpdir(), `car-s24-${name}-`))
38
- return Promise.resolve()
39
- .then(() => fn(dir))
40
- .finally(() => { try { rmSync(dir, { recursive: true, force: true }) } catch { /* 红线 8 */ } })
41
- }
42
-
43
- const { publicKey, privateKey } = generateKeyPairSync('ed25519')
44
- const PUB_B64 = publicKey.export({ type: 'spki', format: 'der' }).toString('base64')
45
-
46
- /** 对插件文件裸字节求 sha256 hex,以 ed25519 签 hex 串 UTF-8 字节,写 sidecar `<file>.minisig` */
47
- function signSidecar(file: string, signKey = privateKey): string {
48
- const manifestHash = createHash('sha256').update(readFileSync(file)).digest('hex')
49
- const minisig = sign(null, Buffer.from(manifestHash), signKey).toString('base64')
50
- writeFileSync(`${file}.minisig`, minisig)
51
- return manifestHash
52
- }
53
-
54
- const stageNames = (r: LoadReportVO) => r.stages.map(s => `${s.stage}:${s.status}`)
55
- const stageOf = (r: LoadReportVO, s: string) => r.stages.find(x => x.stage === s)!
56
- const SIX_OK = ['discover:PASS', 'verify:PASS', 'parse:PASS', 'validate:PASS', 'topo:PASS', 'register:PASS']
57
-
58
- // ==================== warn 缺省(DEC-1 ②) ====================
59
-
60
- test('S28: warn 缺签——放行 + CAR-W-SIG 横幅含 fp 指纹 + confirmed=no 计数 + 六阶段全 PASS', async () => {
61
- await withTempDir('warn-unsigned', async (dir) => {
62
- makePlugin(dir, 'p.ts', { name: 'p', version: '1.0.0' }, 't')
63
- const c = createCounters()
64
- const { report, plugins } = await loadPlugins({ source: dir, signature: { onCount: (n, l) => c.onCount(n, l) } })
65
- assert.deepEqual(stageNames(report), SIX_OK)
66
- assert.equal(plugins.length, 1)
67
- const banner = report.warnings.find(w => w.startsWith('CAR-W-SIG'))
68
- assert.ok(banner, 'unsigned 横幅在位')
69
- assert.match(banner!, /\[fp:[0-9a-f]{12}\]/, '横幅含 manifestHash 指纹前缀')
70
- assert.deepEqual(c.snapshot(), { 'car_load_total|result=ok': 1, 'car_unsigned_confirmed|confirmed=no': 1 })
71
- assert.equal(assertZeroContent(c.snapshot()), true)
72
- })
73
- })
74
-
75
- test('S28: unsignedAllow 显式豁免——confirmed=yes 改写 + 横幅保留(S20 §4 路径②)', async () => {
76
- await withTempDir('unsigned-allow', async (dir) => {
77
- makePlugin(dir, 'p.ts', { name: 'p', version: '1.0.0' }, 't')
78
- const c = createCounters()
79
- const { report } = await loadPlugins({ source: dir, signature: { unsignedAllow: true, onCount: (n, l) => c.onCount(n, l) } })
80
- assert.equal(stageOf(report, 'verify').status, 'PASS')
81
- assert.ok(report.warnings.some(w => w.startsWith('CAR-W-SIG')), '横幅保留不消失')
82
- assert.deepEqual(c.snapshot(), { 'car_load_total|result=ok': 1, 'car_unsigned_confirmed|confirmed=yes': 1 })
83
- })
84
- })
85
-
86
- // ==================== enforce / 验签失败 fail-closed ====================
87
-
88
- test('S28: enforce 缺签——verify FAIL + 空 plugins + 后续 SKIPPED + load_total failed', async () => {
89
- await withTempDir('enforce-unsigned', async (dir) => {
90
- makePlugin(dir, 'p.ts', { name: 'p', version: '1.0.0' }, 't')
91
- const c = createCounters()
92
- const { report, plugins } = await loadPlugins({ source: dir, signature: { mode: 'enforce', onCount: (n, l) => c.onCount(n, l) } })
93
- assert.deepEqual(stageNames(report), [
94
- 'discover:PASS', 'verify:FAIL', 'parse:SKIPPED', 'validate:SKIPPED', 'topo:SKIPPED', 'register:SKIPPED',
95
- ])
96
- const v = stageOf(report, 'verify')
97
- assert.match(v.error!.reason, /CAR-E-SIG: signature missing/)
98
- assert.match(v.error!.file, /p\.ts$/)
99
- assert.equal(plugins.length, 0, 'fail-closed:拒绝即空')
100
- assert.deepEqual(c.snapshot(), { 'car_load_total|result=failed': 1 })
101
- })
102
- })
103
-
104
- test('S28: 有签名但验签失败——硬拒绝不可配置放行(unsignedAllow 亦不豁免,ADR-003 第一级)', async () => {
105
- await withTempDir('bad-sig', async (dir) => {
106
- const f = makePlugin(dir, 'p.ts', { name: 'p', version: '1.0.0' }, 't')
107
- signSidecar(f)
108
- // 签名后篡改插件文件 → 指纹失配 → 验签失败
109
- writeFileSync(f, `export const manifest = { name: 'p', version: '1.0.0' }\n// tampered\n${PLUGIN_BODY('t')}`)
110
- const { report } = await loadPlugins({ source: dir, signature: { trustRootPublicKey: PUB_B64, unsignedAllow: true } })
111
- assert.equal(stageOf(report, 'verify').status, 'FAIL')
112
- assert.match(stageOf(report, 'verify').error!.reason, /signature verification FAILED.*不可配置放行/)
113
- })
114
- })
115
-
116
- test('S28: 好签名(信任根在位)——静默放行,零签名计数、零横幅', async () => {
117
- await withTempDir('good-sig', async (dir) => {
118
- const f = makePlugin(dir, 'p.ts', { name: 'p', version: '1.0.0' }, 't')
119
- signSidecar(f)
120
- const c = createCounters()
121
- const { report, plugins } = await loadPlugins({ source: dir, signature: { trustRootPublicKey: PUB_B64, onCount: (n, l) => c.onCount(n, l) } })
122
- assert.deepEqual(stageNames(report), SIX_OK)
123
- assert.equal(plugins.length, 1)
124
- assert.equal(report.warnings.some(w => w.startsWith('CAR-W-SIG')), false)
125
- // 好签名路径零签名计数;car_load_total 正常计数(register 成功)
126
- assert.deepEqual(c.snapshot(), { 'car_load_total|result=ok': 1 })
127
- })
128
- })
129
-
130
- test('S28: car_load_total{result=ok} 逐插件计数(S27 采集面分母)', async () => {
131
- await withTempDir('load-total', async (dir) => {
132
- makePlugin(dir, 'a.ts', { name: 'a', version: '1.0.0' }, 'ta')
133
- makePlugin(dir, 'b.ts', { name: 'b', version: '1.0.0' }, 'tb')
134
- const c = createCounters()
135
- await loadPlugins({ source: dir, signature: { onCount: (n, l) => c.onCount(n, l) } })
136
- assert.deepEqual(c.snapshot(), { 'car_load_total|result=ok': 2, 'car_unsigned_confirmed|confirmed=no': 2 })
137
- })
138
- })
139
-
140
- // ==================== ReloadManager 透传 + 单文件门 + env 通道 ====================
141
-
142
- test('S28: ReloadManager.reload signature 透传——enforce FAIL 且不残留实例', async () => {
143
- await withTempDir('reload-sig', async (dir) => {
144
- const f = makePlugin(dir, 'hot.ts', { name: 'hot', version: '1.0.0' }, 't')
145
- const mgr = new ReloadManager()
146
- const r1 = await mgr.reload(f)
147
- assert.deepEqual(stageNames(r1.report), SIX_OK)
148
- const r2 = await mgr.reload(f, { signature: { mode: 'enforce' } })
149
- assert.equal(stageOf(r2.report, 'verify').status, 'FAIL')
150
- assert.equal(r2.plugins.length, 0)
151
- })
152
- })
153
-
154
- test('S28: verifyPluginFile 单文件口径——car run 直载门同源;他人签名 warn 下同样硬拒绝', async () => {
155
- await withTempDir('single-file', async (dir) => {
156
- const f = makePlugin(dir, 'p.ts', { name: 'p', version: '1.0.0' }, 't')
157
- const g1 = verifyPluginFile(f, { mode: 'warn' })
158
- assert.equal(g1.allowed, true)
159
- assert.ok(g1.warning)
160
- assert.match(g1.manifestHash!, /^[0-9a-f]{64}$/)
161
- const g2 = verifyPluginFile(f, { mode: 'enforce' })
162
- assert.equal(g2.allowed, false)
163
- // 好签名 + 信任根在位 → enforce 静默放行
164
- signSidecar(f)
165
- const g3 = verifyPluginFile(f, { mode: 'enforce', trustRootPublicKey: PUB_B64 })
166
- assert.equal(g3.allowed, true)
167
- assert.equal(g3.warning, undefined)
168
- // 信任根失配(他人签名)→ 验签失败硬拒绝(warn 模式也不放行——第一级 fail-closed)
169
- const { privateKey: other } = generateKeyPairSync('ed25519')
170
- signSidecar(f, other)
171
- const g4 = verifyPluginFile(f, { mode: 'warn', trustRootPublicKey: PUB_B64 })
172
- assert.equal(g4.allowed, false, '验签失败级不受模式影响')
173
- })
174
- })
175
-
176
- test('S28: gateDepsFromEnv env 通道映射(CAR_SIG_ENFORCE / CAR_TRUST_ROOT / CAR_UNSIGNED_ALLOW)', () => {
177
- const d1 = gateDepsFromEnv({})
178
- assert.equal(d1.mode, 'warn')
179
- assert.equal(d1.trustRootPublicKey, undefined)
180
- assert.equal(d1.unsignedAllow, false)
181
- const d2 = gateDepsFromEnv({ CAR_SIG_ENFORCE: '1', CAR_TRUST_ROOT: PUB_B64, CAR_UNSIGNED_ALLOW: '1' })
182
- assert.equal(d2.mode, 'enforce')
183
- assert.equal(d2.trustRootPublicKey, PUB_B64)
184
- assert.equal(d2.unsignedAllow, true)
185
- })