@iislee/opencodex 2.11.0 → 2.35.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 (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,143 @@
1
+ import { isIP } from "node:net";
2
+ import type {
3
+ PublicArtifactV1,
4
+ PublicEvidenceBundleUnsignedV1,
5
+ PublicEvidenceBundleV1,
6
+ PublicEvidenceRecordV1,
7
+ PublicEvidenceSubjectV1,
8
+ } from "./types";
9
+ import { PublicEvidenceValidationError } from "./validate";
10
+
11
+ const FORBIDDEN_PUBLIC_STRING_PATTERNS: ReadonlyArray<{ label: string; pattern: RegExp }> = [
12
+ { label: "URL", pattern: /(?:https?|file):\/\//i },
13
+ {
14
+ label: "local path",
15
+ pattern:
16
+ /(?:[A-Za-z]:[\\/]|\\\\[A-Za-z0-9._-]+\\|(?:^|[\s"'([{=:])\/(?:Users|home|root|tmp|var|opt|private|etc|mnt|media|srv|usr|dev|run|Library|System|Applications|Volumes|bin|sbin|lib|lib64|proc|sys|boot|Network|cores|nix|snap|app)(?:\/|$))/i,
17
+ },
18
+ { label: "email", pattern: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i },
19
+ { label: "IP address", pattern: /\b(?:\d{1,3}\.){3}\d{1,3}\b|\[[0-9a-f:]{2,}\]/i },
20
+ { label: "query string", pattern: /[?&][A-Za-z0-9_.~-]+=/ },
21
+ { label: "authorization/header material", pattern: /\b(?:authorization|proxy-authorization|cookie|set-cookie|x-api-key|api[_-]?key|bearer)\b/i },
22
+ { label: "credential", pattern: /\b(?:sk-[A-Za-z0-9_-]{8,}|gh[opusr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{8,}|AKIA[0-9A-Z]{12,})\b/ },
23
+ { label: "private key", pattern: /-----BEGIN [^-]*PRIVATE KEY-----/i },
24
+ { label: "local request/decision/Fabric id", pattern: /\b(?:request|decision|fabric)_[A-Za-z0-9_-]{6,}\b/i },
25
+ { label: "account/project/tenant context", pattern: /\b(?:account|tenant|project|organization|deployment)[=:][^\s]+/i },
26
+ { label: "precise timestamp", pattern: /\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/ },
27
+ ];
28
+
29
+ const PUBLIC_TEXT_ARTIFACT_MEDIA_TYPES = new Set([
30
+ "application/json",
31
+ "application/json; charset=utf-8",
32
+ "text/markdown",
33
+ "text/markdown; charset=utf-8",
34
+ "text/plain",
35
+ "text/plain; charset=utf-8",
36
+ ]);
37
+
38
+ function containsIpLiteral(value: string): boolean {
39
+ if (isIP(value) !== 0) return true;
40
+ for (const candidate of value.match(/[0-9A-Fa-f:]{2,}/g) ?? []) {
41
+ if (candidate.includes(":") && isIP(candidate) === 6) return true;
42
+ }
43
+ return false;
44
+ }
45
+
46
+ function assertPrivacySafeString(value: string, field: string): void {
47
+ // `PUBLIC_IDENTIFIER` intentionally permits `:` for reviewed identifiers, so use
48
+ // Node's IP parser to validate colon-bearing candidates instead of rejecting them
49
+ // with a broad regex. This catches both whole-string and embedded IPv6 literals.
50
+ if (containsIpLiteral(value)) {
51
+ throw new PublicEvidenceValidationError(
52
+ "privacy_rejected",
53
+ `${field} contains forbidden IP address material`,
54
+ );
55
+ }
56
+ for (const { label, pattern } of FORBIDDEN_PUBLIC_STRING_PATTERNS) {
57
+ if (pattern.test(value)) {
58
+ throw new PublicEvidenceValidationError(
59
+ "privacy_rejected",
60
+ `${field} contains forbidden ${label} material`,
61
+ );
62
+ }
63
+ }
64
+ }
65
+
66
+ function scanSubject(subject: PublicEvidenceSubjectV1, field: string): void {
67
+ if (subject.subjectKind === "protocol") {
68
+ assertPrivacySafeString(subject.compatibilityVersion, `${field}.compatibilityVersion`);
69
+ assertPrivacySafeString(subject.adapterFamily, `${field}.adapterFamily`);
70
+ assertPrivacySafeString(subject.inboundProtocol, `${field}.inboundProtocol`);
71
+ assertPrivacySafeString(subject.upstreamProtocol, `${field}.upstreamProtocol`);
72
+ assertPrivacySafeString(subject.surface, `${field}.surface`);
73
+ return;
74
+ }
75
+ if (subject.subjectKind === "route") {
76
+ assertPrivacySafeString(subject.providerId, `${field}.providerId`);
77
+ assertPrivacySafeString(subject.modelId, `${field}.modelId`);
78
+ assertPrivacySafeString(subject.adapterFamily, `${field}.adapterFamily`);
79
+ assertPrivacySafeString(subject.compatibilityVersion, `${field}.compatibilityVersion`);
80
+ return;
81
+ }
82
+ scanSubject(subject.route, `${field}.route`);
83
+ assertPrivacySafeString(subject.taskClassId, `${field}.taskClassId`);
84
+ assertPrivacySafeString(subject.taskClassVersion, `${field}.taskClassVersion`);
85
+ assertPrivacySafeString(subject.fabricCompatibilityVersion, `${field}.fabricCompatibilityVersion`);
86
+ }
87
+
88
+ function scanArtifact(artifact: PublicArtifactV1, index: number): void {
89
+ const field = `bundle.artifacts[${index}]`;
90
+ assertPrivacySafeString(artifact.artifactClass, `${field}.artifactClass`);
91
+ assertPrivacySafeString(artifact.mediaType, `${field}.mediaType`);
92
+
93
+ if (!PUBLIC_TEXT_ARTIFACT_MEDIA_TYPES.has(artifact.mediaType.toLowerCase())) {
94
+ throw new PublicEvidenceValidationError(
95
+ "privacy_rejected",
96
+ `${field}.mediaType is not in the closed public text-artifact set`,
97
+ );
98
+ }
99
+ if (typeof artifact.contentBase64 !== "string") {
100
+ throw new PublicEvidenceValidationError("privacy_rejected", `${field}.contentBase64 is invalid`);
101
+ }
102
+ const bytes = Buffer.from(artifact.contentBase64, "base64");
103
+ if (bytes.toString("base64") !== artifact.contentBase64 || bytes.byteLength !== artifact.byteCount) {
104
+ throw new PublicEvidenceValidationError(
105
+ "privacy_rejected",
106
+ `${field}.contentBase64 is non-canonical or does not match byteCount`,
107
+ );
108
+ }
109
+ let text: string;
110
+ try {
111
+ text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
112
+ } catch {
113
+ throw new PublicEvidenceValidationError("privacy_rejected", `${field} is not valid UTF-8 text`);
114
+ }
115
+ assertPrivacySafeString(text, `${field}.content`);
116
+ }
117
+
118
+ export function validatePublicEvidenceRecordPrivacy(record: PublicEvidenceRecordV1): void {
119
+ assertPrivacySafeString(record.suiteId, "record.suiteId");
120
+ assertPrivacySafeString(record.suiteVersion, "record.suiteVersion");
121
+ assertPrivacySafeString(record.scenarioId, "record.scenarioId");
122
+ assertPrivacySafeString(record.scenarioVersion, "record.scenarioVersion");
123
+ scanSubject(record.subject, "record.subject");
124
+ for (const [index, assertion] of record.assertions.entries()) {
125
+ assertPrivacySafeString(assertion.id, `record.assertions[${index}].id`);
126
+ }
127
+ for (const [index, incident] of (record.incidentRefs ?? []).entries()) {
128
+ assertPrivacySafeString(incident.corpusId, `record.incidentRefs[${index}].corpusId`);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Second-pass CL-10 export privacy boundary. Hashes, signatures and publisher public-key
134
+ * bytes are intentionally not pattern-scanned; every human-semantic public string and
135
+ * every final text artifact byte is scanned before local signing/storage or import.
136
+ */
137
+ export function validatePublicEvidencePrivacy(
138
+ bundle: PublicEvidenceBundleUnsignedV1 | PublicEvidenceBundleV1,
139
+ ): void {
140
+ assertPrivacySafeString(bundle.createdDayUtc, "bundle.createdDayUtc");
141
+ for (const record of bundle.records) validatePublicEvidenceRecordPrivacy(record);
142
+ for (const [index, artifact] of bundle.artifacts.entries()) scanArtifact(artifact, index);
143
+ }
@@ -0,0 +1,261 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import {
3
+ closeSync,
4
+ constants as fsConstants,
5
+ fsyncSync,
6
+ linkSync,
7
+ lstatSync,
8
+ openSync,
9
+ readdirSync,
10
+ unlinkSync,
11
+ writeSync,
12
+ } from "node:fs";
13
+ import type { Stats } from "node:fs";
14
+ import { basename, dirname, join } from "node:path";
15
+
16
+ export type PrivateFileCommitFault = "before_publish" | "parent_directory_sync" | null;
17
+ let privateFileCommitFaultForTests: PrivateFileCommitFault = null;
18
+ let privateFileCleanupSyncFaultForTests = false;
19
+ const PRIVATE_STAGE_RE = /^\..+\.(\d+)\.[0-9a-f-]{36}\.tmp$/;
20
+ export const PRIVATE_FILE_STAGE_RETENTION_MS = 24 * 60 * 60 * 1000;
21
+
22
+ export interface PrivateFilePublishOptions {
23
+ /** Validate or harden the empty stage before caller-controlled bytes are written. */
24
+ prepareStage?: (stagePath: string) => void;
25
+ }
26
+
27
+ function cleanup(path: string): void {
28
+ try { unlinkSync(path); } catch { /* absent/already removed */ }
29
+ }
30
+
31
+ function pidDefinitelyDead(pid: number): boolean {
32
+ try {
33
+ process.kill(pid, 0);
34
+ return false;
35
+ } catch (error) {
36
+ return (error as NodeJS.ErrnoException).code === "ESRCH";
37
+ }
38
+ }
39
+
40
+ function staleTempPrefix(finalPath: string): string {
41
+ return `.${basename(finalPath)}.`;
42
+ }
43
+
44
+ function fsyncParentBestEffort(path: string): void {
45
+ if (process.platform === "win32") return;
46
+ let fd: number | null = null;
47
+ try {
48
+ fd = openSync(dirname(path), fsConstants.O_RDONLY);
49
+ fsyncSync(fd);
50
+ } catch {
51
+ // Cleanup durability is best-effort after unlink. Publication and crash-witness
52
+ // retirement use the strict path below and never swallow POSIX failures.
53
+ } finally {
54
+ if (fd !== null) closeSync(fd);
55
+ }
56
+ }
57
+
58
+ function fsyncParentStrict(path: string): void {
59
+ if (process.platform === "win32") return;
60
+ let fd: number | null = null;
61
+ try {
62
+ fd = openSync(dirname(path), fsConstants.O_RDONLY);
63
+ fsyncSync(fd);
64
+ } catch (error) {
65
+ const code = (error as NodeJS.ErrnoException).code ?? "unknown";
66
+ const wrapped = new Error(`private-file parent directory sync failed (${code})`);
67
+ (wrapped as Error & { cause?: unknown }).cause = error;
68
+ throw wrapped;
69
+ } finally {
70
+ if (fd !== null) closeSync(fd);
71
+ }
72
+ }
73
+
74
+ function fsyncParentForPublication(path: string): void {
75
+ // Node does not provide a portable directory-fsync contract on Windows. The
76
+ // exclusive hard-link publication remains atomic there, while POSIX requires
77
+ // the parent directory sync before publication is reported as durable.
78
+ if (process.platform === "win32") return;
79
+ if (privateFileCommitFaultForTests === "parent_directory_sync") {
80
+ throw new Error("synthetic private-file parent directory sync failure");
81
+ }
82
+ fsyncParentStrict(path);
83
+ }
84
+
85
+ export function isPrivateFileStageName(name: string): boolean {
86
+ return PRIVATE_STAGE_RE.test(name);
87
+ }
88
+
89
+ function isPrivateRegularStage(stats: Stats): boolean {
90
+ return stats.isFile() && !stats.isSymbolicLink();
91
+ }
92
+
93
+ function shouldReclaimPrivateFileStage(dir: string, name: string, nowMs: number): boolean {
94
+ const match = PRIVATE_STAGE_RE.exec(name);
95
+ if (!match) return false;
96
+ const pid = Number(match[1]);
97
+ if (!Number.isSafeInteger(pid) || pid <= 0) return false;
98
+
99
+ let stats: Stats;
100
+ try {
101
+ stats = lstatSync(join(dir, name));
102
+ } catch (error) {
103
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return false;
104
+ throw error;
105
+ }
106
+ if (!isPrivateRegularStage(stats)) return false;
107
+
108
+ const expired = nowMs - stats.mtimeMs > PRIVATE_FILE_STAGE_RETENTION_MS;
109
+ const dead = pid !== process.pid && pidDefinitelyDead(pid);
110
+ return expired || dead;
111
+ }
112
+
113
+ /** Reclaim private-file stages whose writer is dead or whose crash witness is past the retention window. */
114
+ export function cleanupStalePrivateFileStagesInDir(dir: string): void {
115
+ let names: string[];
116
+ try {
117
+ names = readdirSync(dir);
118
+ } catch (error) {
119
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return;
120
+ throw error;
121
+ }
122
+ const nowMs = Date.now();
123
+ const reclaimable = names.filter((name) => shouldReclaimPrivateFileStage(dir, name, nowMs));
124
+ if (reclaimable.length === 0) return;
125
+
126
+ // A stale stage can be the hard-link witness for a final name that was linked
127
+ // before a crash or directory-sync failure. Make that final directory entry
128
+ // durable before removing any such witness.
129
+ if (process.platform !== "win32" && privateFileCleanupSyncFaultForTests) {
130
+ throw new Error("synthetic private-file cleanup parent directory sync failure");
131
+ }
132
+ fsyncParentStrict(join(dir, "."));
133
+
134
+ let changed = false;
135
+ for (const name of reclaimable) {
136
+ try {
137
+ unlinkSync(join(dir, name));
138
+ changed = true;
139
+ } catch {
140
+ // Another cleanup or writer may have removed it after enumeration.
141
+ }
142
+ }
143
+ if (changed) fsyncParentBestEffort(join(dir, "."));
144
+ }
145
+
146
+ /** Reclaim staging links from dead writers or expired crash witnesses. */
147
+ export function cleanupStalePrivateFileStages(finalPath: string): void {
148
+ cleanupStalePrivateFileStagesInDir(dirname(finalPath));
149
+ }
150
+
151
+ /** Remove only stage links that already reference the durable final inode. */
152
+ function cleanupPublishedPrivateFileStages(finalPath: string): void {
153
+ let finalStats;
154
+ try {
155
+ finalStats = lstatSync(finalPath);
156
+ } catch (error) {
157
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return;
158
+ throw error;
159
+ }
160
+ if (!finalStats.isFile() || finalStats.isSymbolicLink()) return;
161
+
162
+ const dir = dirname(finalPath);
163
+ const prefix = staleTempPrefix(finalPath);
164
+ let changed = false;
165
+ for (const name of readdirSync(dir)) {
166
+ if (!name.startsWith(prefix) || !PRIVATE_STAGE_RE.test(name)) continue;
167
+ const stagePath = join(dir, name);
168
+ try {
169
+ const stageStats = lstatSync(stagePath);
170
+ if (!stageStats.isFile() || stageStats.isSymbolicLink()) continue;
171
+ if (stageStats.dev !== finalStats.dev || stageStats.ino !== finalStats.ino) continue;
172
+ unlinkSync(stagePath);
173
+ changed = true;
174
+ } catch (error) {
175
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
176
+ }
177
+ }
178
+ if (changed) fsyncParentBestEffort(finalPath);
179
+ }
180
+
181
+ function writeAll(fd: number, bytes: Uint8Array): void {
182
+ let offset = 0;
183
+ while (offset < bytes.byteLength) {
184
+ const count = writeSync(fd, bytes, offset, bytes.byteLength - offset);
185
+ if (count <= 0) throw new Error("private file write made no progress");
186
+ offset += count;
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Publish immutable mode-0600 bytes without ever exposing a partially-written final path.
192
+ * The caller owns EEXIST comparison semantics because some objects are idempotent and
193
+ * others are identity conflicts. Staging files are target-scoped and stale stages from
194
+ * definitely-dead writers are reclaimed on the next read or publication attempt.
195
+ */
196
+ export function publishPrivateFileExclusive(
197
+ finalPath: string,
198
+ bytes: Uint8Array,
199
+ options: PrivateFilePublishOptions = {},
200
+ ): { created: boolean } {
201
+ cleanupStalePrivateFileStages(finalPath);
202
+ const tempPath = join(
203
+ dirname(finalPath),
204
+ `${staleTempPrefix(finalPath)}${process.pid}.${randomUUID()}.tmp`,
205
+ );
206
+ let fd: number | null = null;
207
+ let preservePublishedStage = false;
208
+ try {
209
+ fd = openSync(tempPath, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL, 0o600);
210
+ // Secret callers can harden the empty stage before any sensitive bytes exist.
211
+ // A failure here can therefore leave at most an empty cleanup witness.
212
+ options.prepareStage?.(tempPath);
213
+ writeAll(fd, bytes);
214
+ fsyncSync(fd);
215
+ closeSync(fd);
216
+ fd = null;
217
+
218
+ if (privateFileCommitFaultForTests === "before_publish") {
219
+ throw new Error("synthetic private-file commit failure before publish");
220
+ }
221
+
222
+ try {
223
+ linkSync(tempPath, finalPath);
224
+ } catch (error) {
225
+ if ((error as NodeJS.ErrnoException).code === "EEXIST") {
226
+ // A prior publication may have linked the final entry but failed while
227
+ // syncing the parent directory. Re-sync before reporting idempotent success,
228
+ // then remove only stages that are hard links to that durable final inode.
229
+ fsyncParentForPublication(finalPath);
230
+ cleanupPublishedPrivateFileStages(finalPath);
231
+ return { created: false };
232
+ }
233
+ throw error;
234
+ }
235
+ try {
236
+ fsyncParentForPublication(finalPath);
237
+ } catch (error) {
238
+ // The final name exists, but POSIX durability was not established. Keep this
239
+ // exact hard-link stage so a retry can re-sync and then identify it by inode.
240
+ preservePublishedStage = true;
241
+ throw error;
242
+ }
243
+ return { created: true };
244
+ } finally {
245
+ if (fd !== null) closeSync(fd);
246
+ if (!preservePublishedStage) {
247
+ cleanup(tempPath);
248
+ fsyncParentBestEffort(finalPath);
249
+ }
250
+ }
251
+ }
252
+
253
+ /** Test-only fault seam at the atomic publication point. Import this module directly in tests. */
254
+ export function setPrivateFileCommitFaultForTests(fault: PrivateFileCommitFault): void {
255
+ privateFileCommitFaultForTests = fault;
256
+ }
257
+
258
+ /** Test-only fault seam for strict stale-stage cleanup durability. */
259
+ export function setPrivateFileCleanupSyncFaultForTests(enabled: boolean): void {
260
+ privateFileCleanupSyncFaultForTests = enabled;
261
+ }
@@ -0,0 +1,124 @@
1
+ import type { CompatibilityVerdict } from "../constants";
2
+ import type { ObservationEvent, ProtocolSubjectV1 } from "../events/types";
3
+ import { validatePublicEvidenceAuthorities } from "./community-authority";
4
+ import { publicEvidenceId } from "./ids";
5
+ import { validatePublicEvidenceRecordPrivacy } from "./privacy";
6
+ import { publicUtcDay } from "./time";
7
+ import {
8
+ PUBLIC_ADAPTER_FAMILIES,
9
+ type PublicAdapterFamily,
10
+ type PublicEvidenceProjectionResult,
11
+ type PublicEvidenceRecordV1,
12
+ type PublicIncidentRefV1,
13
+ type PublicProtocolSubjectV1,
14
+ } from "./types";
15
+ import {
16
+ isPublicIncidentRef,
17
+ PublicEvidenceValidationError,
18
+ validatePublicEvidenceRecord,
19
+ } from "./validate";
20
+
21
+ const PROJECTOR_INVARIANT_ERROR_CODES = new Set([
22
+ "subject_id_mismatch",
23
+ "record_id_mismatch",
24
+ ]);
25
+
26
+ export interface ProjectPublicEvidenceRecordInput {
27
+ observation: ObservationEvent;
28
+ verdict: CompatibilityVerdict;
29
+ incidentRefs?: string[];
30
+ publicArtifactRefs?: string[];
31
+ }
32
+
33
+ function asPublicAdapterFamily(value: string): PublicAdapterFamily | undefined {
34
+ return (PUBLIC_ADAPTER_FAMILIES as readonly string[]).includes(value)
35
+ ? value as PublicAdapterFamily
36
+ : undefined;
37
+ }
38
+
39
+ function projectProtocolSubject(subject: ProtocolSubjectV1): PublicProtocolSubjectV1 | undefined {
40
+ const adapterFamily = asPublicAdapterFamily(subject.effectiveAdapter);
41
+ if (!adapterFamily) return undefined;
42
+ return {
43
+ subjectKind: "protocol",
44
+ compatibilityVersion: subject.opencodexCompatibilityVersion,
45
+ adapterFamily,
46
+ inboundProtocol: subject.inboundProtocol,
47
+ upstreamProtocol: subject.upstreamProtocol,
48
+ surface: subject.surface,
49
+ };
50
+ }
51
+
52
+ function projectIncidentRefs(values: string[] | undefined): PublicIncidentRefV1[] | undefined {
53
+ if (values === undefined) return undefined;
54
+ if (values.some((value) => !isPublicIncidentRef(value))) return undefined;
55
+ return values.map((corpusId) => ({ corpusId }));
56
+ }
57
+
58
+ /**
59
+ * Project one local observation into the closed public V1 record shape and apply the
60
+ * complete reviewed authority/privacy boundary before exposing it as exportable.
61
+ *
62
+ * Route and task observations deliberately fail closed here. Persisted RouteSubjectV1
63
+ * contains installation-salted provider-instance and endpoint identity, so the exact
64
+ * public/default route cannot be proven from ledger bytes alone. Dropping those fields
65
+ * would broaden a private exact route into a misleading public claim.
66
+ */
67
+ export function projectPublicEvidenceRecord(
68
+ input: ProjectPublicEvidenceRecordInput,
69
+ ): PublicEvidenceProjectionResult {
70
+ const { observation } = input;
71
+
72
+ if (observation.evidenceLayer === "live_route_compatibility" || observation.evidenceLayer === "task_effectiveness") {
73
+ return { status: "not_exportable", reason: "private_route_identity" };
74
+ }
75
+ if (observation.evidenceLayer !== "protocol_conformance" || observation.subject.subjectKind !== "protocol") {
76
+ return { status: "not_exportable", reason: "unsupported_subject" };
77
+ }
78
+
79
+ const subject = projectProtocolSubject(observation.subject);
80
+ if (!subject) return { status: "not_exportable", reason: "unsupported_adapter_family" };
81
+
82
+ const incidentRefs = projectIncidentRefs(input.incidentRefs);
83
+ if (input.incidentRefs !== undefined && incidentRefs === undefined) {
84
+ return { status: "not_exportable", reason: "unsafe_public_field" };
85
+ }
86
+
87
+ try {
88
+ const subjectId = publicEvidenceId("subject", subject);
89
+ const withoutRecordId: Omit<PublicEvidenceRecordV1, "recordId"> = {
90
+ subjectId,
91
+ evidenceLayer: "protocol_conformance",
92
+ suiteId: observation.suiteId,
93
+ suiteVersion: observation.suiteVersion,
94
+ scenarioId: observation.scenarioId,
95
+ scenarioVersion: observation.scenarioVersion,
96
+ verdict: input.verdict,
97
+ observedDayUtc: publicUtcDay(observation.completedAt),
98
+ subject,
99
+ assertions: observation.assertions.map((assertion) => ({
100
+ id: assertion.id,
101
+ required: assertion.required,
102
+ passed: assertion.passed,
103
+ })),
104
+ ...(incidentRefs !== undefined ? { incidentRefs } : {}),
105
+ ...(input.publicArtifactRefs !== undefined ? { artifactRefs: [...input.publicArtifactRefs] } : {}),
106
+ };
107
+ const record = validatePublicEvidenceRecord({
108
+ recordId: publicEvidenceId("record", withoutRecordId),
109
+ ...withoutRecordId,
110
+ });
111
+ validatePublicEvidenceAuthorities([record]);
112
+ validatePublicEvidenceRecordPrivacy(record);
113
+ return { status: "exportable", record };
114
+ } catch (error) {
115
+ if (error instanceof PublicEvidenceValidationError) {
116
+ if (PROJECTOR_INVARIANT_ERROR_CODES.has(error.code)) throw error;
117
+ return { status: "not_exportable", reason: "unsafe_public_field", detailCode: error.code };
118
+ }
119
+ if (error instanceof TypeError && error.message.startsWith("jcsStringify:")) {
120
+ return { status: "not_exportable", reason: "unsafe_public_field" };
121
+ }
122
+ throw error;
123
+ }
124
+ }
@@ -0,0 +1,21 @@
1
+ export type PublicEvidencePurgeFaultForTests =
2
+ | "before_export_delete"
3
+ | "export_directory_sync"
4
+ | null;
5
+
6
+ let purgeFaultForTests: PublicEvidencePurgeFaultForTests = null;
7
+
8
+ /** Arms the internal deterministic fault seam and returns a scoped restore handle. */
9
+ export function setPublicEvidencePurgeFaultForTests(
10
+ fault: PublicEvidencePurgeFaultForTests,
11
+ ): () => void {
12
+ const previous = purgeFaultForTests;
13
+ purgeFaultForTests = fault;
14
+ return () => {
15
+ purgeFaultForTests = previous;
16
+ };
17
+ }
18
+
19
+ export function publicEvidencePurgeFaultForTests(): PublicEvidencePurgeFaultForTests {
20
+ return purgeFaultForTests;
21
+ }