@wardby/cli 0.5.3 → 0.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 (763) hide show
  1. package/.env.example +33 -0
  2. package/README.md +25 -14
  3. package/deploy/local/docker-compose.quickstart-coding.yml +13 -0
  4. package/dist/claude-coding-worker/context.d.ts +22 -0
  5. package/dist/claude-coding-worker/context.js +92 -0
  6. package/dist/claude-coding-worker/driver.d.ts +27 -3
  7. package/dist/claude-coding-worker/driver.js +161 -20
  8. package/dist/claude-coding-worker/main.js +34 -6
  9. package/dist/claude-coding-worker/sdk.js +25 -5
  10. package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
  11. package/dist/claude-coding-worker/tool-socket.js +111 -0
  12. package/dist/claude-coding-worker/transcript.d.ts +18 -0
  13. package/dist/claude-coding-worker/transcript.js +77 -0
  14. package/dist/cli-help.d.ts +1 -1
  15. package/dist/cli-help.js +6 -2
  16. package/dist/cli-native-mode.d.ts +9 -0
  17. package/dist/cli-native-mode.js +20 -0
  18. package/dist/cli.d.ts +3 -1
  19. package/dist/cli.js +161 -11
  20. package/dist/coding/claude-context.d.ts +45 -0
  21. package/dist/coding/claude-context.js +434 -0
  22. package/dist/coding/continuation-wording.d.ts +35 -0
  23. package/dist/coding/continuation-wording.js +73 -0
  24. package/dist/coding/linked-issue-note.d.ts +23 -0
  25. package/dist/coding/linked-issue-note.js +47 -0
  26. package/dist/coding/merge-wording.d.ts +28 -0
  27. package/dist/coding/merge-wording.js +78 -0
  28. package/dist/coding/pr-description-note.d.ts +9 -0
  29. package/dist/coding/pr-description-note.js +32 -0
  30. package/dist/coding/profile.d.ts +50 -118
  31. package/dist/coding/profile.js +51 -4
  32. package/dist/coding/protected-path-wording.d.ts +8 -0
  33. package/dist/coding/protected-path-wording.js +1 -1
  34. package/dist/coding/protocol.d.ts +292 -270
  35. package/dist/coding/protocol.js +322 -15
  36. package/dist/coding/redact.d.ts +3 -0
  37. package/dist/coding/redact.js +12 -0
  38. package/dist/coding/registry/allowlist.d.ts +12 -0
  39. package/dist/coding/registry/allowlist.js +14 -1
  40. package/dist/coding/registry/audit-mode.d.ts +153 -0
  41. package/dist/coding/registry/audit-mode.js +304 -0
  42. package/dist/coding/registry/lockfile-shared.d.ts +36 -0
  43. package/dist/coding/registry/lockfile-shared.js +128 -0
  44. package/dist/coding/registry/lockfiles.js +1 -1
  45. package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
  46. package/dist/coding/registry/npm-lockfile-formats.js +41 -0
  47. package/dist/coding/registry/npm-lockfile.d.ts +8 -4
  48. package/dist/coding/registry/npm-lockfile.js +4 -6
  49. package/dist/coding/registry/npm.js +78 -8
  50. package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
  51. package/dist/coding/registry/pnpm-lockfile.js +189 -0
  52. package/dist/coding/registry/pypi-plan.d.ts +50 -0
  53. package/dist/coding/registry/pypi-plan.js +406 -0
  54. package/dist/coding/registry/pypi-requirements.d.ts +58 -0
  55. package/dist/coding/registry/pypi-requirements.js +155 -0
  56. package/dist/coding/registry/pypi.d.ts +3 -27
  57. package/dist/coding/registry/pypi.js +40 -154
  58. package/dist/coding/registry/refusal-hints.d.ts +20 -0
  59. package/dist/coding/registry/refusal-hints.js +61 -0
  60. package/dist/coding/registry/refusal-wording.d.ts +11 -0
  61. package/dist/coding/registry/refusal-wording.js +56 -0
  62. package/dist/coding/registry/report.d.ts +70 -8
  63. package/dist/coding/registry/report.js +112 -5
  64. package/dist/coding/registry/types.d.ts +58 -8
  65. package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
  66. package/dist/coding/registry/yarn-lockfile.js +367 -0
  67. package/dist/coding/services/catalog.d.ts +37 -351
  68. package/dist/coding/transcript/claude-code.d.ts +13 -0
  69. package/dist/coding/transcript/claude-code.js +273 -0
  70. package/dist/coding/transcript/download-protocol.d.ts +30 -0
  71. package/dist/coding/transcript/download-protocol.js +18 -0
  72. package/dist/coding/transcript/format.d.ts +20 -0
  73. package/dist/coding/transcript/format.js +32 -0
  74. package/dist/coding/transcript/recorder.d.ts +51 -0
  75. package/dist/coding/transcript/recorder.js +225 -0
  76. package/dist/coding/transcript/resume/checkout.d.ts +31 -0
  77. package/dist/coding/transcript/resume/checkout.js +203 -0
  78. package/dist/coding/transcript/resume/command.d.ts +17 -0
  79. package/dist/coding/transcript/resume/command.js +176 -0
  80. package/dist/coding/transcript/resume/download.d.ts +20 -0
  81. package/dist/coding/transcript/resume/download.js +153 -0
  82. package/dist/coding/transcript/resume/launch.d.ts +38 -0
  83. package/dist/coding/transcript/resume/launch.js +128 -0
  84. package/dist/coding/transcript/resume/session-file.d.ts +13 -0
  85. package/dist/coding/transcript/resume/session-file.js +79 -0
  86. package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
  87. package/dist/coding/transcript/resume/stand-in.js +49 -0
  88. package/dist/coding-worker/artifact.d.ts +16 -3
  89. package/dist/coding-worker/artifact.js +5 -3
  90. package/dist/coding-worker/debug-trace.d.ts +6 -5
  91. package/dist/coding-worker/debug-trace.js +13 -18
  92. package/dist/coding-worker/dependency-cache.d.mts +229 -0
  93. package/dist/coding-worker/dependency-cache.mjs +2123 -0
  94. package/dist/coding-worker/driver.d.ts +4 -3
  95. package/dist/coding-worker/driver.js +118 -38
  96. package/dist/coding-worker/errors.d.ts +1 -0
  97. package/dist/coding-worker/errors.js +32 -0
  98. package/dist/coding-worker/sdk.d.ts +6 -0
  99. package/dist/coding-worker/sdk.js +1 -0
  100. package/dist/coding-worker/skills.d.ts +23 -0
  101. package/dist/coding-worker/skills.js +117 -0
  102. package/dist/coding-worker/task-note.d.ts +11 -0
  103. package/dist/coding-worker/task-note.js +13 -0
  104. package/dist/coding-worker/types.d.ts +13 -0
  105. package/dist/config/dependency-cache.d.ts +23 -0
  106. package/dist/config/dependency-cache.js +32 -0
  107. package/dist/config/github-allowed-accounts.d.ts +15 -0
  108. package/dist/config/github-allowed-accounts.js +36 -0
  109. package/dist/config/low-power.d.ts +12 -0
  110. package/dist/config/low-power.js +18 -0
  111. package/dist/config/mobile.d.ts +12 -0
  112. package/dist/config/mobile.js +18 -0
  113. package/dist/config/providers.d.ts +65 -3
  114. package/dist/config/providers.js +147 -11
  115. package/dist/config/test-simulators.d.ts +82 -0
  116. package/dist/config/test-simulators.js +305 -0
  117. package/dist/core/async-context.d.ts +2 -0
  118. package/dist/core/async-context.js +12 -0
  119. package/dist/core/budget-events.d.ts +108 -0
  120. package/dist/core/budget-events.js +346 -0
  121. package/dist/core/budget-groups.d.ts +50 -1
  122. package/dist/core/budget-groups.js +236 -27
  123. package/dist/core/budget-stopped-head.d.ts +46 -0
  124. package/dist/core/budget-stopped-head.js +81 -0
  125. package/dist/core/budget-topup.d.ts +51 -0
  126. package/dist/core/budget-topup.js +156 -0
  127. package/dist/core/budget-wording.d.ts +16 -2
  128. package/dist/core/budget-wording.js +40 -2
  129. package/dist/core/coding-queue.d.ts +2 -1
  130. package/dist/core/coding-queue.js +7 -0
  131. package/dist/core/cron.d.ts +19 -1
  132. package/dist/core/cron.js +17 -0
  133. package/dist/core/datastores.js +1 -1
  134. package/dist/core/db.d.ts +16 -6
  135. package/dist/core/db.js +12 -10
  136. package/dist/core/deferred-coding.d.ts +14 -0
  137. package/dist/core/deferred-coding.js +62 -0
  138. package/dist/core/delegation-child.d.ts +25 -0
  139. package/dist/core/delegation-child.js +37 -0
  140. package/dist/core/dispatch.d.ts +53 -0
  141. package/dist/core/dispatch.js +167 -57
  142. package/dist/core/engine-native.js +10 -6
  143. package/dist/core/error-code.d.ts +38 -0
  144. package/dist/core/error-code.js +168 -0
  145. package/dist/core/grants.d.ts +19 -6
  146. package/dist/core/grants.js +55 -6
  147. package/dist/core/host-events.d.ts +67 -5
  148. package/dist/core/host-events.js +571 -37
  149. package/dist/core/host-status.d.ts +85 -3
  150. package/dist/core/host-status.js +298 -20
  151. package/dist/core/issue-bridge.d.ts +50 -6
  152. package/dist/core/issue-bridge.js +151 -20
  153. package/dist/core/issue-events.d.ts +1 -1
  154. package/dist/core/issue-events.js +16 -11
  155. package/dist/core/issue-status.d.ts +1 -1
  156. package/dist/core/issue-status.js +68 -29
  157. package/dist/core/logger.d.ts +5 -0
  158. package/dist/core/logger.js +14 -1
  159. package/dist/core/lost-run-children.d.ts +6 -0
  160. package/dist/core/lost-run-children.js +32 -0
  161. package/dist/core/mark-ready.d.ts +34 -0
  162. package/dist/core/mark-ready.js +152 -0
  163. package/dist/core/markdown-code.d.ts +8 -0
  164. package/dist/core/markdown-code.js +107 -0
  165. package/dist/core/memory-tools.js +7 -0
  166. package/dist/core/merge-order-check.d.ts +130 -0
  167. package/dist/core/merge-order-check.js +343 -0
  168. package/dist/core/notification-dispatcher.d.ts +70 -0
  169. package/dist/core/notification-dispatcher.js +368 -0
  170. package/dist/core/notification-templates.d.ts +19 -0
  171. package/dist/core/notification-templates.js +139 -0
  172. package/dist/core/notifications.d.ts +10 -0
  173. package/dist/core/notifications.js +38 -0
  174. package/dist/core/pg-auth.d.ts +22 -0
  175. package/dist/core/pg-auth.js +152 -0
  176. package/dist/core/power-composition.d.ts +16 -0
  177. package/dist/core/power-composition.js +37 -0
  178. package/dist/core/power-idle.d.ts +14 -0
  179. package/dist/core/power-idle.js +30 -0
  180. package/dist/core/power.d.ts +71 -0
  181. package/dist/core/power.js +202 -0
  182. package/dist/core/pull-request-state-sync.js +2 -2
  183. package/dist/core/reconciler.d.ts +8 -5
  184. package/dist/core/reconciler.js +37 -6
  185. package/dist/core/related-pull-requests.d.ts +59 -7
  186. package/dist/core/related-pull-requests.js +140 -25
  187. package/dist/core/reply-parts.d.ts +21 -0
  188. package/dist/core/reply-parts.js +73 -0
  189. package/dist/core/repo-access.d.ts +15 -0
  190. package/dist/core/repo-access.js +66 -0
  191. package/dist/core/review-fix.d.ts +38 -1
  192. package/dist/core/review-fix.js +209 -7
  193. package/dist/core/review-host-checks.d.ts +1 -1
  194. package/dist/core/review-host-tools.d.ts +23 -0
  195. package/dist/core/review-host-tools.js +156 -14
  196. package/dist/core/review-reads.d.ts +55 -0
  197. package/dist/core/review-reads.js +233 -0
  198. package/dist/core/run-status.d.ts +12 -0
  199. package/dist/core/run-status.js +12 -0
  200. package/dist/core/runner.d.ts +384 -5
  201. package/dist/core/runner.js +1244 -372
  202. package/dist/core/schedule-start.d.ts +12 -0
  203. package/dist/core/schedule-start.js +14 -0
  204. package/dist/core/secret-broker-config.d.ts +39 -0
  205. package/dist/core/secret-broker-config.js +112 -0
  206. package/dist/core/secret-guard.d.ts +46 -0
  207. package/dist/core/secret-guard.js +104 -0
  208. package/dist/core/secret-guarded-stores.d.ts +12 -0
  209. package/dist/core/secret-guarded-stores.js +41 -0
  210. package/dist/core/secret-spans.d.ts +50 -0
  211. package/dist/core/secret-spans.js +94 -0
  212. package/dist/core/secrets.d.ts +39 -4
  213. package/dist/core/secrets.js +148 -40
  214. package/dist/core/stop-run.d.ts +46 -0
  215. package/dist/core/stop-run.js +61 -0
  216. package/dist/core/workflow-event-recorder.d.ts +14 -0
  217. package/dist/core/workflow-event-recorder.js +120 -0
  218. package/dist/core/workflow-events.d.ts +94 -0
  219. package/dist/core/workflow-events.js +48 -0
  220. package/dist/core/workflow-run-events.d.ts +18 -0
  221. package/dist/core/workflow-run-events.js +75 -0
  222. package/dist/core/zod-json-schema.d.ts +4 -0
  223. package/dist/core/zod-json-schema.js +39 -0
  224. package/dist/core/zod3-window.d.ts +35 -0
  225. package/dist/core/zod3-window.js +124 -0
  226. package/dist/generated/prisma/browser.d.ts +92 -3
  227. package/dist/generated/prisma/client.d.ts +92 -3
  228. package/dist/generated/prisma/commonInputTypes.d.ts +364 -54
  229. package/dist/generated/prisma/enums.d.ts +37 -0
  230. package/dist/generated/prisma/enums.js +31 -0
  231. package/dist/generated/prisma/internal/class.d.ts +132 -0
  232. package/dist/generated/prisma/internal/class.js +4 -4
  233. package/dist/generated/prisma/internal/prismaNamespace.d.ts +1332 -142
  234. package/dist/generated/prisma/internal/prismaNamespace.js +227 -5
  235. package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +234 -0
  236. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +227 -5
  237. package/dist/generated/prisma/models/Agent.d.ts +464 -7
  238. package/dist/generated/prisma/models/AgentRepository.d.ts +42 -1
  239. package/dist/generated/prisma/models/CodingAgentProfile.d.ts +301 -1
  240. package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
  241. package/dist/generated/prisma/models/CodingProxySession.d.ts +114 -1
  242. package/dist/generated/prisma/models/CodingRun.d.ts +1841 -1
  243. package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
  244. package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
  245. package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
  246. package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
  247. package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
  248. package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1713 -0
  249. package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
  250. package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1551 -0
  251. package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
  252. package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
  253. package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
  254. package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
  255. package/dist/generated/prisma/models/NotificationChannel.js +1 -0
  256. package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
  257. package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
  258. package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
  259. package/dist/generated/prisma/models/NotificationThread.js +1 -0
  260. package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
  261. package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
  262. package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
  263. package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
  264. package/dist/generated/prisma/models/Run.d.ts +1619 -58
  265. package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
  266. package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
  267. package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
  268. package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
  269. package/dist/generated/prisma/models/RunTranscript.js +1 -0
  270. package/dist/generated/prisma/models/Secret.d.ts +37 -1
  271. package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
  272. package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
  273. package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
  274. package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
  275. package/dist/generated/prisma/models.d.ts +12 -0
  276. package/dist/help/build.js +4 -2
  277. package/dist/help/catalog.d.ts +1 -1
  278. package/dist/help/catalog.js +31 -6
  279. package/dist/help-index.json +2584 -146
  280. package/dist/import/create.js +49 -3
  281. package/dist/import/neutral-schema.d.ts +50 -277
  282. package/dist/import/neutral-schema.js +7 -4
  283. package/dist/knowledge/check.d.ts +1 -1
  284. package/dist/knowledge/cli.d.ts +11 -1
  285. package/dist/knowledge/cli.js +37 -4
  286. package/dist/knowledge/concept.d.ts +3 -19
  287. package/dist/knowledge/location.d.ts +31 -0
  288. package/dist/knowledge/location.js +78 -0
  289. package/dist/mcp/auth/access.d.ts +11 -2
  290. package/dist/mcp/auth/access.js +15 -1
  291. package/dist/mcp/auth/ownership.d.ts +7 -7
  292. package/dist/mcp/auth/repo-authorization.js +14 -0
  293. package/dist/mcp/auth/resource-server.d.ts +2 -1
  294. package/dist/mcp/auth/resource-server.js +7 -2
  295. package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
  296. package/dist/mcp/auth/self-hosted/browser.js +19 -6
  297. package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
  298. package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
  299. package/dist/mcp/context.d.ts +6 -0
  300. package/dist/mcp/host-events/github-ingress.d.ts +25 -1
  301. package/dist/mcp/host-events/github-ingress.js +70 -1
  302. package/dist/mcp/index.d.ts +19 -0
  303. package/dist/mcp/index.js +117 -20
  304. package/dist/mcp/server.d.ts +13 -0
  305. package/dist/mcp/server.js +33 -14
  306. package/dist/mcp/tools/agents.d.ts +4 -0
  307. package/dist/mcp/tools/agents.js +277 -24
  308. package/dist/mcp/tools/datastore.js +17 -8
  309. package/dist/mcp/tools/grants.js +9 -3
  310. package/dist/mcp/tools/memory.js +11 -1
  311. package/dist/mcp/tools/notification-channels.d.ts +2 -0
  312. package/dist/mcp/tools/notification-channels.js +293 -0
  313. package/dist/mcp/tools/packages.d.ts +2 -0
  314. package/dist/mcp/tools/packages.js +195 -0
  315. package/dist/mcp/tools/power.d.ts +2 -0
  316. package/dist/mcp/tools/power.js +77 -0
  317. package/dist/mcp/tools/repositories.js +18 -5
  318. package/dist/mcp/tools/run-access.d.ts +16 -0
  319. package/dist/mcp/tools/run-access.js +25 -0
  320. package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
  321. package/dist/mcp/tools/run-transcript-download.js +129 -0
  322. package/dist/mcp/tools/run-transcript.d.ts +19 -0
  323. package/dist/mcp/tools/run-transcript.js +70 -0
  324. package/dist/mcp/tools/runs.d.ts +0 -6
  325. package/dist/mcp/tools/runs.js +41 -14
  326. package/dist/mcp/tools/scheduling.js +3 -1
  327. package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
  328. package/dist/mcp/tools/secret-broker-compat.js +23 -0
  329. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
  330. package/dist/mcp/tools/secret-elicitation-form.js +205 -10
  331. package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
  332. package/dist/mcp/tools/secret-elicitation-server.js +10 -54
  333. package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
  334. package/dist/mcp/tools/secret-elicitation.js +110 -12
  335. package/dist/mcp/tools/secrets.js +186 -9
  336. package/dist/mcp/tools/stop-run.d.ts +2 -0
  337. package/dist/mcp/tools/stop-run.js +82 -0
  338. package/dist/mcp/tools/subagents.js +2 -2
  339. package/dist/mcp/tools/tools.d.ts +2 -2
  340. package/dist/mcp/tools/tools.js +47 -11
  341. package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
  342. package/dist/mcp/transport/stdio-link-host.js +67 -0
  343. package/dist/mcp/transport/streamable-http.d.ts +13 -0
  344. package/dist/mcp/transport/streamable-http.js +41 -1
  345. package/dist/native-worker/composition.d.ts +23 -0
  346. package/dist/native-worker/composition.js +77 -0
  347. package/dist/native-worker/docker-isolation.d.ts +65 -0
  348. package/dist/native-worker/docker-isolation.js +183 -0
  349. package/dist/native-worker/docker-launcher.d.ts +110 -0
  350. package/dist/native-worker/docker-launcher.js +297 -0
  351. package/dist/native-worker/gateway-server.d.ts +77 -0
  352. package/dist/native-worker/gateway-server.js +412 -0
  353. package/dist/native-worker/gateway.d.ts +70 -0
  354. package/dist/native-worker/gateway.js +263 -0
  355. package/dist/native-worker/http-server.d.ts +24 -0
  356. package/dist/native-worker/http-server.js +113 -0
  357. package/dist/native-worker/http-transport.d.ts +17 -0
  358. package/dist/native-worker/http-transport.js +88 -0
  359. package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
  360. package/dist/native-worker/kubernetes-isolation.js +218 -0
  361. package/dist/native-worker/kubernetes-launcher.d.ts +106 -0
  362. package/dist/native-worker/kubernetes-launcher.js +375 -0
  363. package/dist/native-worker/launch.d.ts +62 -0
  364. package/dist/native-worker/launch.js +49 -0
  365. package/dist/native-worker/ledger.d.ts +125 -0
  366. package/dist/native-worker/ledger.js +245 -0
  367. package/dist/native-worker/loopback.d.ts +12 -0
  368. package/dist/native-worker/loopback.js +44 -0
  369. package/dist/native-worker/main.d.ts +8 -0
  370. package/dist/native-worker/main.js +85 -0
  371. package/dist/native-worker/protocol.d.ts +296 -0
  372. package/dist/native-worker/protocol.js +246 -0
  373. package/dist/native-worker/sandbox-executor.d.ts +83 -0
  374. package/dist/native-worker/sandbox-executor.js +284 -0
  375. package/dist/native-worker/stderr-redaction.d.ts +77 -0
  376. package/dist/native-worker/stderr-redaction.js +237 -0
  377. package/dist/native-worker/stdio.d.ts +29 -0
  378. package/dist/native-worker/stdio.js +189 -0
  379. package/dist/native-worker/warm-delivery.d.ts +16 -0
  380. package/dist/native-worker/warm-delivery.js +33 -0
  381. package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
  382. package/dist/native-worker/warm-pool-ledger.js +73 -0
  383. package/dist/native-worker/warm-pool.d.ts +107 -0
  384. package/dist/native-worker/warm-pool.js +283 -0
  385. package/dist/native-worker/worker.d.ts +17 -0
  386. package/dist/native-worker/worker.js +141 -0
  387. package/dist/observability/metrics.js +6 -1
  388. package/dist/providers/auth/authorization-server.d.ts +3 -0
  389. package/dist/providers/auth/index.js +2 -0
  390. package/dist/providers/auth/self-hosted.d.ts +14 -2
  391. package/dist/providers/auth/self-hosted.js +54 -4
  392. package/dist/providers/chat/fake.d.ts +46 -0
  393. package/dist/providers/chat/fake.js +39 -0
  394. package/dist/providers/chat/index.d.ts +4 -0
  395. package/dist/providers/chat/index.js +8 -0
  396. package/dist/providers/chat/slack.d.ts +37 -0
  397. package/dist/providers/chat/slack.js +105 -0
  398. package/dist/providers/chat/types.d.ts +42 -0
  399. package/dist/providers/chat/types.js +19 -0
  400. package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
  401. package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
  402. package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
  403. package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
  404. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
  405. package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
  406. package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
  407. package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
  408. package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
  409. package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
  410. package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
  411. package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
  412. package/dist/providers/coding-proxy/hold.d.ts +32 -0
  413. package/dist/providers/coding-proxy/hold.js +86 -0
  414. package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
  415. package/dist/providers/coding-proxy/interrupted.js +104 -0
  416. package/dist/providers/coding-proxy/memory-ledger.d.ts +15 -2
  417. package/dist/providers/coding-proxy/memory-ledger.js +84 -8
  418. package/dist/providers/coding-proxy/metering.d.ts +16 -0
  419. package/dist/providers/coding-proxy/metering.js +27 -4
  420. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -2
  421. package/dist/providers/coding-proxy/prisma-ledger.js +179 -67
  422. package/dist/providers/coding-proxy/proxy.d.ts +14 -1
  423. package/dist/providers/coding-proxy/proxy.js +166 -14
  424. package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
  425. package/dist/providers/coding-proxy/registry/audit.js +94 -17
  426. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
  427. package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
  428. package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
  429. package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
  430. package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
  431. package/dist/providers/coding-proxy/registry/plan.js +201 -48
  432. package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
  433. package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
  434. package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
  435. package/dist/providers/coding-proxy/registry/service.js +579 -112
  436. package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
  437. package/dist/providers/coding-proxy/registry/store.js +54 -1
  438. package/dist/providers/coding-proxy/runtime.d.ts +4 -0
  439. package/dist/providers/coding-proxy/runtime.js +78 -16
  440. package/dist/providers/coding-proxy/server.d.ts +6 -1
  441. package/dist/providers/coding-proxy/server.js +45 -1
  442. package/dist/providers/coding-proxy/types.d.ts +65 -1
  443. package/dist/providers/datastore/types.d.ts +5 -0
  444. package/dist/providers/engine/types.d.ts +36 -2
  445. package/dist/providers/engine/types.js +39 -0
  446. package/dist/providers/executor/composition.d.ts +31 -1
  447. package/dist/providers/executor/composition.js +81 -8
  448. package/dist/providers/executor/container.d.ts +385 -9
  449. package/dist/providers/executor/container.js +1234 -99
  450. package/dist/providers/executor/dbos-status.d.ts +31 -0
  451. package/dist/providers/executor/dbos-status.js +64 -0
  452. package/dist/providers/executor/dbos.d.ts +91 -0
  453. package/dist/providers/executor/dbos.js +319 -26
  454. package/dist/providers/executor/deferred.d.ts +44 -0
  455. package/dist/providers/executor/deferred.js +100 -0
  456. package/dist/providers/executor/in-process.d.ts +9 -1
  457. package/dist/providers/executor/in-process.js +14 -4
  458. package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
  459. package/dist/providers/executor/linked-issue-reader.js +30 -0
  460. package/dist/providers/executor/routing.d.ts +39 -10
  461. package/dist/providers/executor/routing.js +77 -32
  462. package/dist/providers/executor/types.d.ts +25 -0
  463. package/dist/providers/index.d.ts +2 -1
  464. package/dist/providers/issue-tracker/types.d.ts +17 -0
  465. package/dist/providers/issue-tracker/types.js +39 -1
  466. package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
  467. package/dist/providers/jobs/claude-tool-setup.js +5 -2
  468. package/dist/providers/jobs/docker-isolation.d.ts +8 -0
  469. package/dist/providers/jobs/docker-isolation.js +17 -0
  470. package/dist/providers/jobs/docker.d.ts +1 -0
  471. package/dist/providers/jobs/docker.js +29 -4
  472. package/dist/providers/jobs/fake-kubernetes-api.d.ts +23 -2
  473. package/dist/providers/jobs/fake-kubernetes-api.js +45 -1
  474. package/dist/providers/jobs/kubernetes-api.d.ts +25 -1
  475. package/dist/providers/jobs/kubernetes-api.js +17 -0
  476. package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
  477. package/dist/providers/jobs/kubernetes-client.js +61 -3
  478. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
  479. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
  480. package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
  481. package/dist/providers/jobs/kubernetes-isolation.js +23 -1
  482. package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
  483. package/dist/providers/jobs/kubernetes-platform.js +38 -1
  484. package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
  485. package/dist/providers/jobs/kubernetes-preflight.js +4 -2
  486. package/dist/providers/jobs/kubernetes.d.ts +42 -2
  487. package/dist/providers/jobs/kubernetes.js +178 -19
  488. package/dist/providers/jobs/metadata-probes.d.ts +11 -0
  489. package/dist/providers/jobs/metadata-probes.js +13 -0
  490. package/dist/providers/jobs/types.d.ts +42 -0
  491. package/dist/providers/jobs/types.js +13 -1
  492. package/dist/providers/llm/anthropic.js +5 -1
  493. package/dist/providers/llm/bedrock.d.ts +0 -12
  494. package/dist/providers/llm/bedrock.js +4 -0
  495. package/dist/providers/llm/claude-messages.d.ts +3 -1
  496. package/dist/providers/llm/claude-messages.js +4 -1
  497. package/dist/providers/llm/claude-provider.d.ts +2 -2
  498. package/dist/providers/llm/claude-provider.js +2 -2
  499. package/dist/providers/llm/openai.d.ts +2 -2
  500. package/dist/providers/llm/openai.js +6 -2
  501. package/dist/providers/llm/routing.d.ts +2 -2
  502. package/dist/providers/llm/routing.js +2 -2
  503. package/dist/providers/llm/types.d.ts +12 -2
  504. package/dist/providers/review-host/github-events.d.ts +9 -1
  505. package/dist/providers/review-host/github-events.js +34 -12
  506. package/dist/providers/review-host/github.d.ts +39 -2
  507. package/dist/providers/review-host/github.js +274 -29
  508. package/dist/providers/review-host/local.d.ts +8 -4
  509. package/dist/providers/review-host/local.js +49 -31
  510. package/dist/providers/review-host/patch-pages.d.ts +41 -0
  511. package/dist/providers/review-host/patch-pages.js +176 -0
  512. package/dist/providers/review-host/review-format.d.ts +19 -1
  513. package/dist/providers/review-host/review-format.js +38 -7
  514. package/dist/providers/review-host/types.d.ts +157 -2
  515. package/dist/providers/review-host/types.js +8 -0
  516. package/dist/providers/storage/gcs.d.ts +63 -0
  517. package/dist/providers/storage/gcs.js +69 -0
  518. package/dist/providers/storage/index.d.ts +15 -0
  519. package/dist/providers/storage/index.js +14 -0
  520. package/dist/providers/storage/local.d.ts +24 -0
  521. package/dist/providers/storage/local.js +92 -0
  522. package/dist/providers/storage/meter.d.ts +14 -0
  523. package/dist/providers/storage/meter.js +34 -0
  524. package/dist/providers/storage/s3.d.ts +41 -0
  525. package/dist/providers/storage/s3.js +107 -0
  526. package/dist/providers/storage/types.d.ts +37 -3
  527. package/dist/providers/storage/types.js +21 -4
  528. package/dist/providers/vcs/git.d.ts +33 -2
  529. package/dist/providers/vcs/git.js +324 -22
  530. package/dist/providers/vcs/github-remote.d.ts +26 -3
  531. package/dist/providers/vcs/github-remote.js +124 -14
  532. package/dist/providers/vcs/github.d.ts +246 -12
  533. package/dist/providers/vcs/github.js +521 -61
  534. package/dist/providers/vcs/index.js +8 -1
  535. package/dist/providers/vcs/pr-description.d.ts +127 -0
  536. package/dist/providers/vcs/pr-description.js +270 -0
  537. package/dist/providers/vcs/remote.d.ts +33 -1
  538. package/dist/providers/vcs/routing.d.ts +4 -2
  539. package/dist/providers/vcs/routing.js +6 -0
  540. package/dist/providers/vcs/types.d.ts +80 -3
  541. package/dist/quickstart/coding-seed.d.ts +21 -3
  542. package/dist/quickstart/coding-seed.js +283 -3
  543. package/dist/quickstart/images.d.ts +2 -0
  544. package/dist/quickstart/images.js +7 -1
  545. package/dist/quickstart/reviewer-prompt.d.ts +1 -1
  546. package/dist/quickstart/reviewer-prompt.js +6 -6
  547. package/dist/quickstart-images.json +1 -1
  548. package/dist/sandbox/brokered-fetch.d.ts +23 -0
  549. package/dist/sandbox/brokered-fetch.js +37 -0
  550. package/dist/sandbox/generated/zod.bundle.js +62 -1
  551. package/dist/sandbox/generated/zod3.bundle.js +5 -0
  552. package/dist/sandbox/host-functions.d.ts +35 -0
  553. package/dist/sandbox/host-functions.js +150 -91
  554. package/dist/sandbox/prelude.js +7 -1
  555. package/dist/sandbox/run-in-sandbox.d.ts +19 -0
  556. package/dist/sandbox/run-in-sandbox.js +28 -10
  557. package/dist/sandbox/safe-fetch.d.ts +2 -0
  558. package/dist/sandbox/safe-fetch.js +3 -1
  559. package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
  560. package/dist/sandbox/secret-broker-sigv4.js +49 -0
  561. package/dist/sandbox/secret-broker.d.ts +34 -0
  562. package/dist/sandbox/secret-broker.js +161 -0
  563. package/dist/sandbox/tool-capabilities.d.ts +10 -30
  564. package/dist/sandbox/user-tool.d.ts +14 -0
  565. package/dist/sandbox/user-tool.js +32 -0
  566. package/dist/sandbox/zod-params.d.ts +37 -5
  567. package/dist/sandbox/zod-params.js +181 -26
  568. package/dist/serve.js +25 -0
  569. package/dist/viewer/api-schema.d.ts +372 -2454
  570. package/dist/viewer/api-schema.js +29 -0
  571. package/dist/viewer/build-schemas.js +10 -3
  572. package/dist/viewer/event-bus.d.ts +6 -0
  573. package/dist/viewer/event-bus.js +16 -7
  574. package/dist/viewer/graph.d.ts +5 -2
  575. package/dist/viewer/graph.js +7 -2
  576. package/dist/viewer/http.d.ts +0 -1
  577. package/dist/viewer/http.js +2 -2
  578. package/dist/viewer/infra.js +25 -2
  579. package/dist/viewer/limits.d.ts +4 -0
  580. package/dist/viewer/limits.js +4 -0
  581. package/dist/viewer/openapi.d.ts +15 -0
  582. package/dist/viewer/openapi.js +170 -0
  583. package/dist/wardby-bin.js +10 -0
  584. package/docs/README.md +7 -0
  585. package/docs/agent-recipes.md +114 -27
  586. package/docs/architecture-runtime.md +16 -1
  587. package/docs/code-review-agents.md +689 -45
  588. package/docs/coding-agent-setup.md +602 -12
  589. package/docs/coding-packages.md +1037 -92
  590. package/docs/coding-services.md +30 -13
  591. package/docs/coding-worker-byo-images.md +218 -6
  592. package/docs/coding-worker-isolation.md +173 -44
  593. package/docs/getting-started-gke.md +332 -129
  594. package/docs/getting-started-identity-provider.md +31 -11
  595. package/docs/getting-started.md +14 -4
  596. package/docs/jira-agents.md +22 -9
  597. package/docs/knowledge/blob-not-found-semantics.md +41 -0
  598. package/docs/knowledge/bounded-file-descriptor.md +52 -0
  599. package/docs/knowledge/delegation-admission-slots.md +52 -0
  600. package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
  601. package/docs/knowledge/import-rename-target.md +52 -0
  602. package/docs/knowledge/index.md +57 -0
  603. package/docs/knowledge/log.md +9 -0
  604. package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
  605. package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
  606. package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
  607. package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
  608. package/docs/knowledge/overview-cli.md +74 -0
  609. package/docs/knowledge/overview-coding-proxy.md +72 -0
  610. package/docs/knowledge/overview-coding.md +72 -0
  611. package/docs/knowledge/overview-config.md +60 -0
  612. package/docs/knowledge/overview-core.md +72 -0
  613. package/docs/knowledge/overview-deploy.md +83 -0
  614. package/docs/knowledge/overview-mcp.md +61 -0
  615. package/docs/knowledge/overview-prisma.md +72 -0
  616. package/docs/knowledge/overview-providers.md +89 -0
  617. package/docs/knowledge/overview-sandbox.md +83 -0
  618. package/docs/knowledge/overview-surfaces.md +83 -0
  619. package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
  620. package/docs/knowledge/proxy-settlement-projections.md +41 -0
  621. package/docs/knowledge/run-pricing-first-writer.md +43 -0
  622. package/docs/knowledge/schedule-claim-transaction.md +41 -0
  623. package/docs/knowledge/secret-entry-replica-contract.md +52 -0
  624. package/docs/knowledge/terminal-run-first-writer.md +41 -0
  625. package/docs/knowledge/transactional-agent-authorization.md +52 -0
  626. package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
  627. package/docs/knowledge/warm-input-publication.md +30 -0
  628. package/docs/knowledge/workspace-staging-failure.md +54 -0
  629. package/docs/knowledge.md +54 -14
  630. package/docs/native-sandbox.md +731 -0
  631. package/docs/observability.md +4 -0
  632. package/docs/release-verification.md +9 -0
  633. package/docs/security-deployment.md +146 -14
  634. package/docs/slack-notifications.md +268 -0
  635. package/docs/tool-secrets.md +284 -0
  636. package/docs/viewer-api.md +46 -5
  637. package/docs/viewer-api.openapi.yml +1404 -0
  638. package/help/admin-viewer.md +29 -3
  639. package/help/agent-recipes.md +27 -0
  640. package/help/architecture-agent.md +11 -6
  641. package/help/brokered-secrets.md +79 -0
  642. package/help/build-claude-code-image.md +131 -0
  643. package/help/build-worker-image.md +6 -7
  644. package/help/builder-agent.md +19 -6
  645. package/help/code-review-agents.md +243 -10
  646. package/help/coding-packages.md +156 -6
  647. package/help/cost-attribution.md +9 -5
  648. package/help/creating-agents.md +14 -1
  649. package/help/dependency-cache.md +143 -0
  650. package/help/deploy-gke.md +23 -9
  651. package/help/deployment-targets.md +25 -14
  652. package/help/errors/budget-exhausted.md +187 -0
  653. package/help/errors/budget-group-exhausted.md +5 -1
  654. package/help/errors/coding-provider-not-configured.md +2 -2
  655. package/help/errors/coding-stream-quota-exceeded.md +33 -0
  656. package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
  657. package/help/errors/continuation-closed.md +9 -12
  658. package/help/errors/database-auth-invalid.md +28 -0
  659. package/help/errors/delegation-conflict.md +24 -0
  660. package/help/errors/file-list-truncated.md +45 -0
  661. package/help/errors/full-read-required.md +49 -0
  662. package/help/errors/github-account-not-allowed.md +29 -0
  663. package/help/errors/graph-incomplete.md +43 -0
  664. package/help/errors/graph-limit.md +43 -0
  665. package/help/errors/low-power-disabled.md +29 -0
  666. package/help/errors/low-power-scale-forbidden.md +35 -0
  667. package/help/errors/low-power-wake-timeout.md +30 -0
  668. package/help/errors/merge-conflict.md +49 -0
  669. package/help/errors/mobile-disabled.md +31 -0
  670. package/help/errors/native-sandbox-capacity.md +22 -0
  671. package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
  672. package/help/errors/native-sandbox-docker-failed.md +20 -0
  673. package/help/errors/native-sandbox-gateway-error.md +20 -0
  674. package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
  675. package/help/errors/native-sandbox-image-not-pinned.md +19 -0
  676. package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
  677. package/help/errors/native-sandbox-launch-abandoned.md +21 -0
  678. package/help/errors/native-sandbox-network-unenforced.md +22 -0
  679. package/help/errors/native-sandbox-requires-catalog.md +31 -0
  680. package/help/errors/native-sandbox-unavailable.md +19 -0
  681. package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
  682. package/help/errors/native-sandbox-worker-exited.md +21 -0
  683. package/help/errors/native-sandbox-worker-lost.md +20 -0
  684. package/help/errors/native-sandbox-worker-unready.md +22 -0
  685. package/help/errors/package-not-allowed-pending.md +52 -0
  686. package/help/errors/package-not-allowed.md +51 -0
  687. package/help/errors/package-refusals.md +43 -0
  688. package/help/errors/patch-cursor-malformed.md +31 -0
  689. package/help/errors/run-lost.md +39 -0
  690. package/help/errors/run-transcript-download.md +44 -0
  691. package/help/errors/secret-broker-body-invalid.md +26 -0
  692. package/help/errors/secret-broker-changed.md +20 -0
  693. package/help/errors/secret-broker-config-invalid.md +30 -0
  694. package/help/errors/secret-broker-conflict.md +27 -0
  695. package/help/errors/secret-broker-destination-denied.md +28 -0
  696. package/help/errors/secret-broker-value-invalid.md +28 -0
  697. package/help/errors/secret-brokered.md +24 -0
  698. package/help/errors/secret-in-value.md +69 -0
  699. package/help/errors/secret-not-brokered.md +25 -0
  700. package/help/errors/slack-auth-failed.md +48 -0
  701. package/help/errors/slack-channel-unreachable.md +39 -0
  702. package/help/errors/slack-not-configured.md +33 -0
  703. package/help/errors/target-merge.md +40 -0
  704. package/help/fix-merge-conflicts.md +73 -0
  705. package/help/getting-started.md +4 -5
  706. package/help/github-app-setup.md +132 -0
  707. package/help/github.md +40 -1
  708. package/help/identity-and-access.md +7 -1
  709. package/help/jira.md +23 -6
  710. package/help/knowledge.md +16 -7
  711. package/help/local-repositories.md +3 -4
  712. package/help/low-power-mode.md +131 -0
  713. package/help/merge-order-check.md +122 -0
  714. package/help/mobile-app.md +54 -0
  715. package/help/native-capabilities.md +29 -1
  716. package/help/native-sandbox.md +150 -0
  717. package/help/observability.md +8 -0
  718. package/help/operating-agents.md +5 -0
  719. package/help/package-audit-mode.md +91 -0
  720. package/help/related-pull-requests.md +80 -16
  721. package/help/repo-instructions-and-skills.md +91 -0
  722. package/help/resume-runs-locally.md +131 -0
  723. package/help/review-fix-rounds.md +43 -1
  724. package/help/sharing-agents.md +59 -0
  725. package/help/slack-notifications.md +76 -0
  726. package/help/status-comments.md +31 -0
  727. package/help/stop-run.md +58 -0
  728. package/help/troubleshooting/budgets.md +28 -0
  729. package/help/troubleshooting/coding-workers.md +99 -7
  730. package/package.json +27 -13
  731. package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
  732. package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
  733. package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
  734. package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
  735. package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
  736. package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
  737. package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
  738. package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
  739. package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
  740. package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
  741. package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
  742. package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
  743. package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
  744. package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
  745. package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
  746. package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
  747. package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
  748. package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
  749. package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
  750. package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
  751. package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
  752. package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
  753. package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
  754. package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
  755. package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
  756. package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
  757. package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
  758. package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
  759. package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
  760. package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
  761. package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
  762. package/prisma/schema.prisma +631 -146
  763. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
@@ -2,7 +2,9 @@ import { createHash, randomBytes, randomUUID } from "node:crypto";
2
2
  import { shippedCatalog } from "../llm/catalog.js";
3
3
  import { SHIPPED_CATALOG_VERSION } from "../llm/catalog-shipped.js";
4
4
  import { deriveRegistryToken } from "../../coding/registry/token.js";
5
- import { AnthropicSseUsageTracker, actualCostUsd, estimateReservationUsd, fingerprintRequest, parseAnthropicAuthoritativeUsage, parseAuthoritativeUsage, pricingSnapshot, safeUpstreamErrorCode, terminalUsageFromSseFrame, } from "./metering.js";
5
+ import { AnthropicSseUsageTracker, actualCostUsd, fingerprintRequest, parseAnthropicAuthoritativeUsage, parseAuthoritativeUsage, pricingSnapshot, safeUpstreamErrorCode, terminalUsageFromSseFrame, } from "./metering.js";
6
+ import { conversationKey, estimateHold } from "./hold.js";
7
+ import { estimateInterrupted, previousInput } from "./interrupted.js";
6
8
  import { createPinnedProxyFetch } from "./secure-fetch.js";
7
9
  export const PROXY_MAX_BODY_BYTES = 8 * 1024 * 1024;
8
10
  export const PROXY_MAX_OUTPUT_TOKENS = 1_000_000;
@@ -818,8 +820,10 @@ export class CodingProxy {
818
820
  getPricing;
819
821
  priceVersion;
820
822
  activeRequests = new Map();
823
+ onModelRequest;
821
824
  constructor(options) {
822
825
  this.ledger = options.ledger;
826
+ this.onModelRequest = options.onModelRequest;
823
827
  this.credentials = options.credentials;
824
828
  this.upstreamUrls = {
825
829
  "openai-responses": options.upstreamUrl ?? "https://api.openai.com/v1/responses",
@@ -905,12 +909,19 @@ export class CodingProxy {
905
909
  budgetExhausted(sessionId) {
906
910
  return this.ledger.budgetExhausted(sessionId);
907
911
  }
912
+ /** The numbers behind this session's first budget refusal, if any. */
913
+ budgetRefusal(sessionId) {
914
+ return this.ledger.budgetRefusal(sessionId);
915
+ }
908
916
  /** The code of the first upstream failure relayed for this session's run, if any. */
909
917
  upstreamFailure(sessionId) {
910
918
  return this.ledger.upstreamFailure(sessionId);
911
919
  }
912
920
  async execute(input, sink) {
913
921
  const session = await this.authenticate(input.bearer);
922
+ // The run's agent exists from its first model request on (both protocols arrive here).
923
+ if (this.onModelRequest)
924
+ await this.onModelRequest(session.runId).catch(() => undefined);
914
925
  if (session.protocol !== input.protocol) {
915
926
  this.audit({ type: "request.rejected", runId: session.runId, reason: "protocol_mismatch" });
916
927
  throw new CodingProxyError(403, "protocol_mismatch");
@@ -948,7 +959,32 @@ export class CodingProxy {
948
959
  }
949
960
  const requestKey = safeRequestKey(input.requestKey, parsed.fingerprint);
950
961
  const snapshot = pricingSnapshot(terms.version, terms.pricing);
951
- const reservationUsd = estimateReservationUsd(Buffer.byteLength(parsed.encoded), parsed.maxOutputTokens, snapshot);
962
+ const bodyBytes = Buffer.byteLength(parsed.encoded);
963
+ const conversation = conversationKey(session.protocol, parsed.body);
964
+ // A failed lookup holds the ceiling: never a reason to fail the request.
965
+ const previous = conversation ? await this.ledger.previousReply(session.id, conversation).catch(() => null) : null;
966
+ const holdNow = this.now();
967
+ const hold = estimateHold({
968
+ protocol: session.protocol,
969
+ model: parsed.model,
970
+ bodyBytes,
971
+ maxOutputTokens: parsed.maxOutputTokens,
972
+ pricing: snapshot,
973
+ previous,
974
+ now: holdNow,
975
+ });
976
+ // An interrupted reply's input, from the same previous reply and clock as the hold.
977
+ const previousPrompt = previousInput({ model: parsed.model, bodyBytes, previous, pricing: snapshot, now: holdNow });
978
+ const reservationUsd = hold.holdUsd;
979
+ const holdAudit = {
980
+ reservationUsd,
981
+ ceilingUsd: hold.ceilingUsd,
982
+ reservationBasis: hold.basis,
983
+ ...(hold.fallback ? { holdFallback: hold.fallback } : {}),
984
+ ...(hold.cachedTokens !== undefined
985
+ ? { holdCachedTokens: hold.cachedTokens, holdUncachedTokens: hold.uncachedTokens }
986
+ : {}),
987
+ };
952
988
  const reservation = await this.ledger.reserve({
953
989
  id: randomUUID(),
954
990
  sessionId: session.id,
@@ -956,6 +992,10 @@ export class CodingProxy {
956
992
  requestFingerprint: parsed.fingerprint,
957
993
  model: parsed.model,
958
994
  reservationUsd,
995
+ requestBytes: bodyBytes,
996
+ ceilingUsd: hold.ceilingUsd,
997
+ reservationBasis: hold.basis,
998
+ conversationKey: conversation,
959
999
  pricing: snapshot,
960
1000
  now: this.now(),
961
1001
  });
@@ -969,7 +1009,12 @@ export class CodingProxy {
969
1009
  runId: session.runId,
970
1010
  model: parsed.model,
971
1011
  reason: "budget_exhausted",
972
- reservationUsd,
1012
+ ...holdAudit,
1013
+ budgetUsd: reservation.details.budgetUsd,
1014
+ spentUsd: reservation.details.spentUsd,
1015
+ heldReservedUsd: reservation.details.heldReservedUsd,
1016
+ heldUncertainUsd: reservation.details.heldUncertainUsd,
1017
+ turn: reservation.details.turn,
973
1018
  });
974
1019
  throw new CodingProxyError(429, "wardby_budget_exhausted");
975
1020
  }
@@ -982,7 +1027,7 @@ export class CodingProxy {
982
1027
  runId: session.runId,
983
1028
  requestId: request.id,
984
1029
  model: request.model,
985
- reservationUsd,
1030
+ ...holdAudit,
986
1031
  });
987
1032
  let key;
988
1033
  try {
@@ -1010,6 +1055,13 @@ export class CodingProxy {
1010
1055
  const deadlineTimer = setTimeout(() => controller.abort(), remainingMs);
1011
1056
  deadlineTimer.unref();
1012
1057
  this.trackActive(session.id, controller);
1058
+ const progress = {
1059
+ maxOutputTokens: parsed.maxOutputTokens,
1060
+ stream: parsed.stream,
1061
+ bodyBytes,
1062
+ ...(previousPrompt ? { previousInput: previousPrompt } : {}),
1063
+ relayedOutputBytes: 0,
1064
+ };
1013
1065
  const cleanupActive = () => {
1014
1066
  clearTimeout(deadlineTimer);
1015
1067
  const active = this.activeRequests.get(session.id);
@@ -1042,10 +1094,11 @@ export class CodingProxy {
1042
1094
  redirect: "error",
1043
1095
  signal: controller.signal,
1044
1096
  });
1097
+ progress.responseStarted = true;
1045
1098
  }
1046
1099
  catch {
1047
1100
  cleanupActive();
1048
- await this.markUncertain(session, request, undefined, controller.signal.aborted ? "upstream_aborted" : "upstream_transport");
1101
+ await this.markUncertain(session, request, undefined, controller.signal.aborted ? "upstream_aborted" : "upstream_transport", {}, progress);
1049
1102
  throw new CodingProxyError(502, controller.signal.aborted ? "upstream_aborted" : "upstream_transport_error");
1050
1103
  }
1051
1104
  if (!upstream.ok) {
@@ -1068,12 +1121,12 @@ export class CodingProxy {
1068
1121
  }
1069
1122
  try {
1070
1123
  if (parsed.stream)
1071
- await this.forwardStream(session, request, upstream, sink);
1124
+ await this.forwardStream(session, request, upstream, sink, progress);
1072
1125
  else
1073
1126
  await this.forwardJson(session, request, upstream, sink);
1074
1127
  }
1075
1128
  catch (error) {
1076
- await this.markUncertain(session, request, upstream.status, failureReason(error), responseHeadersOf(upstream));
1129
+ await this.markUncertain(session, request, upstream.status, failureReason(error), responseHeadersOf(upstream), progress);
1077
1130
  sink.destroy();
1078
1131
  throw error instanceof CodingProxyError ? error : new CodingProxyError(502, "invalid_upstream_response");
1079
1132
  }
@@ -1117,6 +1170,7 @@ export class CodingProxy {
1117
1170
  async complete(session, request, usage, upstreamStatus) {
1118
1171
  const costUsd = actualCostUsd(usage, request.pricing);
1119
1172
  await this.ledger.complete(request.id, usage, costUsd, upstreamStatus);
1173
+ const overshootUsd = costUsd - request.reservationUsd;
1120
1174
  this.audit({
1121
1175
  type: "response.completed",
1122
1176
  runId: session.runId,
@@ -1124,13 +1178,17 @@ export class CodingProxy {
1124
1178
  model: request.model,
1125
1179
  status: upstreamStatus,
1126
1180
  costUsd,
1181
+ reservationUsd: request.reservationUsd,
1182
+ ...(overshootUsd > Number.EPSILON ? { reason: "reservation_exceeded", overshootUsd } : {}),
1127
1183
  inputTokens: usage.inputTokens,
1128
1184
  outputTokens: usage.outputTokens,
1129
1185
  cachedInputTokens: usage.cachedInputTokens,
1130
1186
  cacheWriteTokens: usage.cacheWriteTokens,
1131
1187
  reasoningTokens: usage.reasoningTokens,
1132
1188
  });
1133
- if (costUsd > request.reservationUsd + Number.EPSILON) {
1189
+ // A cached hold may be exceeded when the cache misses (settled, audited above); the ceiling may not.
1190
+ const ceilingUsd = request.ceilingUsd ?? request.reservationUsd;
1191
+ if (costUsd > ceilingUsd + Number.EPSILON) {
1134
1192
  await this.ledger.cancelSession(session.id);
1135
1193
  throw new CodingProxyError(502, "reservation_invariant_violated");
1136
1194
  }
@@ -1156,7 +1214,7 @@ export class CodingProxy {
1156
1214
  await safeWrite(sink, bytes, { value: true });
1157
1215
  sink.end();
1158
1216
  }
1159
- async forwardStream(session, request, upstream, sink) {
1217
+ async forwardStream(session, request, upstream, sink, progress) {
1160
1218
  if (!upstream.body)
1161
1219
  throw new Error("missing_upstream_body");
1162
1220
  sink.start(upstream.status, { "content-type": "text/event-stream", "cache-control": "no-store" });
@@ -1166,7 +1224,7 @@ export class CodingProxy {
1166
1224
  let receivedBytes = 0;
1167
1225
  let completed = false;
1168
1226
  let failedWithoutUsage = false;
1169
- const anthropicUsage = session.protocol === "anthropic-messages" ? new AnthropicSseUsageTracker() : undefined;
1227
+ const anthropicUsage = session.protocol === "anthropic-messages" ? (progress.anthropic = new AnthropicSseUsageTracker()) : undefined;
1170
1228
  const body = upstream.body;
1171
1229
  for await (const chunk of body) {
1172
1230
  receivedBytes += chunk.byteLength;
@@ -1181,6 +1239,7 @@ export class CodingProxy {
1181
1239
  buffer = buffer.slice(boundary + 2);
1182
1240
  const terminal = anthropicUsage ? anthropicUsage.consume(frame) : terminalUsageFromSseFrame(frame);
1183
1241
  if (!terminal.terminal) {
1242
+ progress.relayedOutputBytes += relayedTextBytes(frame, session.protocol);
1184
1243
  await safeWrite(sink, Buffer.from(`${frame}\n\n`), connected);
1185
1244
  continue;
1186
1245
  }
@@ -1191,7 +1250,7 @@ export class CodingProxy {
1191
1250
  // client sees the real error instead of a cut connection; the reservation stays held.
1192
1251
  await this.recordUpstreamFailure(session, terminal.failure);
1193
1252
  if (!completed) {
1194
- await this.markUncertain(session, request, upstream.status, `upstream_failed:${terminal.failure}`, responseHeadersOf(upstream));
1253
+ await this.markUncertain(session, request, upstream.status, `upstream_failed:${terminal.failure}`, responseHeadersOf(upstream), progress);
1195
1254
  }
1196
1255
  failedWithoutUsage = true;
1197
1256
  await safeWrite(sink, Buffer.from(`${frame}\n\n`), connected);
@@ -1214,9 +1273,102 @@ export class CodingProxy {
1214
1273
  async recordUpstreamFailure(session, code) {
1215
1274
  await this.ledger.recordUpstreamFailure(session.id, code).catch(() => undefined);
1216
1275
  }
1217
- async markUncertain(session, request, status, reason, headers = {}) {
1218
- await this.ledger.markUncertain(request.id, status);
1219
- this.audit({ type: "request.uncertain", runId: session.runId, requestId: request.id, status, reason, ...headers });
1276
+ async markUncertain(session, request, status, reason, headers, progress) {
1277
+ if (progress.marked)
1278
+ return;
1279
+ progress.marked = true;
1280
+ let estimate = await this.estimateInterrupted(session, request, progress);
1281
+ if (estimate) {
1282
+ try {
1283
+ await this.ledger.markUncertain(request.id, status, estimate);
1284
+ }
1285
+ catch {
1286
+ // Settling at the estimate failed: mark it uncertain without one, so it keeps its full hold.
1287
+ estimate = undefined;
1288
+ }
1289
+ }
1290
+ if (!estimate)
1291
+ await this.ledger.markUncertain(request.id, status);
1292
+ this.audit({
1293
+ type: "request.uncertain",
1294
+ runId: session.runId,
1295
+ requestId: request.id,
1296
+ status,
1297
+ reason,
1298
+ ...(estimate ? { estimatedCostUsd: estimate.costUsd } : {}),
1299
+ ...headers,
1300
+ });
1301
+ }
1302
+ /**
1303
+ * The best known cost of a request that broke before its final usage (interrupted.ts), or
1304
+ * undefined when none can be made: the request then keeps its full hold. Never throws.
1305
+ */
1306
+ async estimateInterrupted(session, request, progress) {
1307
+ try {
1308
+ const hints = await this.ledger.settlementHints(session.id, request.model);
1309
+ const estimate = estimateInterrupted({
1310
+ ...progress.anthropic?.partial(),
1311
+ beforeResponse: progress.stream && !progress.responseStarted,
1312
+ relayedOutputBytes: progress.relayedOutputBytes,
1313
+ ...hints,
1314
+ ...(progress.previousInput ? { previous: progress.previousInput } : {}),
1315
+ bodyBytes: progress.bodyBytes,
1316
+ reservationUsd: request.reservationUsd,
1317
+ maxOutputTokens: progress.maxOutputTokens,
1318
+ ceilingUsd: request.ceilingUsd ?? request.reservationUsd,
1319
+ }, request.pricing);
1320
+ return Number.isFinite(estimate.costUsd) ? estimate : undefined;
1321
+ }
1322
+ catch {
1323
+ return undefined;
1324
+ }
1325
+ }
1326
+ }
1327
+ /** OpenAI Responses events whose string `delta` is generated output: text, tool input, reasoning. */
1328
+ const OPENAI_OUTPUT_DELTAS = new Set([
1329
+ "response.output_text.delta",
1330
+ "response.refusal.delta",
1331
+ "response.function_call_arguments.delta",
1332
+ "response.custom_tool_call_input.delta",
1333
+ "response.reasoning_text.delta",
1334
+ "response.reasoning_summary_text.delta",
1335
+ ]);
1336
+ /** The generated-output field of each Anthropic content_block_delta type (signatures are not output). */
1337
+ const ANTHROPIC_OUTPUT_DELTAS = {
1338
+ text_delta: "text",
1339
+ input_json_delta: "partial_json",
1340
+ thinking_delta: "thinking",
1341
+ };
1342
+ /**
1343
+ * UTF-8 bytes of generated output in a relayed SSE frame: text, tool-call input and thinking or
1344
+ * reasoning deltas, which are most of a coding agent's output.
1345
+ */
1346
+ function relayedTextBytes(frame, protocol) {
1347
+ if (!frame.includes(protocol === "anthropic-messages" ? "content_block_delta" : ".delta"))
1348
+ return 0;
1349
+ try {
1350
+ const data = frame
1351
+ .split("\n")
1352
+ .filter((line) => line.startsWith("data:"))
1353
+ .map((line) => line.slice(5).trimStart())
1354
+ .join("\n");
1355
+ const value = JSON.parse(data);
1356
+ if (!value || typeof value.type !== "string")
1357
+ return 0;
1358
+ if (protocol === "openai-responses") {
1359
+ return OPENAI_OUTPUT_DELTAS.has(value.type) && typeof value.delta === "string"
1360
+ ? Buffer.byteLength(value.delta)
1361
+ : 0;
1362
+ }
1363
+ if (value.type !== "content_block_delta")
1364
+ return 0;
1365
+ const delta = value.delta;
1366
+ const field = typeof delta?.type === "string" ? ANTHROPIC_OUTPUT_DELTAS[delta.type] : undefined;
1367
+ const text = field ? delta?.[field] : undefined;
1368
+ return typeof text === "string" ? Buffer.byteLength(text) : 0;
1369
+ }
1370
+ catch {
1371
+ return 0;
1220
1372
  }
1221
1373
  }
1222
1374
  /** The safe error code in a rejected upstream's JSON body, or undefined when it names none or cannot be read. */
@@ -16,6 +16,7 @@
16
16
  * - a version or event the comparator cannot parse counts as affected
17
17
  * (fail closed).
18
18
  */
19
+ import { type AuditAdvisory } from "../../../coding/registry/audit-mode.js";
19
20
  import { type RegistryAdapter, type UpstreamFetch } from "../../../coding/registry/types.js";
20
21
  export declare const DEFAULT_VULN_CACHE_ENTRIES = 10000;
21
22
  /** Exact versions whose querybatch results are cached. */
@@ -39,6 +40,7 @@ interface OsvAffected {
39
40
  }
40
41
  interface OsvVuln {
41
42
  id: string;
43
+ summary?: unknown;
42
44
  aliases?: string[];
43
45
  affected?: (OsvAffected & {
44
46
  database_specific?: Record<string, unknown>;
@@ -58,11 +60,50 @@ export declare function isMalware(vuln: OsvVuln): boolean;
58
60
  * names compare, and how versions order. */
59
61
  export type AuditAdapter = Pick<RegistryAdapter, "osvEcosystem" | "normalizeName" | "compareVersions">;
60
62
  export interface AdvisoryIndex {
61
- /** Advisory ids with HIGH or CRITICAL severity that affect `version`. */
62
- withheld(version: string): readonly string[];
63
+ /** Ids of the blocking advisories (HIGH, CRITICAL or malware) that affect
64
+ * `version`, minus those waived by `accepted` (see `isWaived`). Without
65
+ * `accepted`, or with an empty set, every blocking advisory. With
66
+ * `auditAll` (package audit mode `full`), only those that can never be
67
+ * served past: malware. */
68
+ withheld(version: string, accepted?: ReadonlySet<string>, auditAll?: boolean): readonly string[];
69
+ /** Ids of the blocking advisories affecting `version` that `accepted`
70
+ * waives: exactly those `withheld` subtracts. For reporting. */
71
+ waived(version: string, accepted: ReadonlySet<string>): readonly string[];
63
72
  /** Advisory ids of any other severity that affect `version`. */
64
73
  reported(version: string): readonly string[];
74
+ /** Blocking, non-malware, non-accepted advisories that `auditAll` lets
75
+ * through, with detail: what a full-mode run records when it serves `version`. */
76
+ audited?(version: string, accepted: ReadonlySet<string>): readonly AuditAdvisory[];
65
77
  }
78
+ /** A blocking advisory, with what deciding a waiver needs. */
79
+ export interface WithheldAdvisory {
80
+ id: string;
81
+ /** Reports malicious code (`isMalware`): never waived. */
82
+ malware: boolean;
83
+ /** The advisory's OSV aliases (CVE ids, other GHSA ids, …). */
84
+ aliases: readonly string[];
85
+ /** OSV severity, upper-cased (HIGH, CRITICAL, …); absent when OSV gives none (malware). */
86
+ severity?: string;
87
+ /** OSV summary as plain bounded text; absent when OSV gives none. */
88
+ summary?: string;
89
+ }
90
+ /** Whether `accepted` waives a blocking advisory: it is not malware, and
91
+ * its id or one of its aliases is accepted. Malware is never waived,
92
+ * whatever the accepted set lists. */
93
+ export declare function isWaived(advisory: WithheldAdvisory, accepted?: ReadonlySet<string>): boolean;
94
+ /** Splits the blocking advisories affecting one version into those still
95
+ * withholding it, those `accepted` waives, and (package audit mode `full`,
96
+ * `auditAll`) those served past and recorded. Malware is always withheld.
97
+ * The version is withheld while `withheld` is non-empty. */
98
+ export declare function splitWaived<T extends WithheldAdvisory>(advisories: readonly T[], accepted?: ReadonlySet<string>, options?: {
99
+ auditAll?: boolean;
100
+ }): {
101
+ withheld: T[];
102
+ waived: T[];
103
+ audited: T[];
104
+ };
105
+ /** A blocking advisory as package audit mode records it. */
106
+ export declare function auditAdvisoryOf(advisory: WithheldAdvisory): AuditAdvisory;
66
107
  type Compare = (a: string, b: string) => number;
67
108
  /** OSV range evaluation: sort events by version, then sweep. A version or
68
109
  * event the comparator cannot parse makes the version count as affected. */
@@ -73,9 +114,10 @@ export interface AuditedVersion {
73
114
  name: string;
74
115
  version: string;
75
116
  }
76
- /** `name@version` -> the HIGH/CRITICAL advisory ids affecting it; a
77
- * version with none is absent. */
78
- export type WithheldVersions = Map<string, string[]>;
117
+ /** `name@version` -> the blocking (HIGH/CRITICAL or malware) advisories
118
+ * affecting it; a version with none is absent. Independent of any
119
+ * accepted set: callers subtract waivers with `splitWaived`. */
120
+ export type WithheldVersions = Map<string, WithheldAdvisory[]>;
79
121
  export declare const versionKey: (name: string, version: string) => string;
80
122
  export declare class OsvAudit {
81
123
  private readonly options;
@@ -85,8 +127,8 @@ export declare class OsvAudit {
85
127
  private readonly cache;
86
128
  /** Single-flight: concurrent audits of one package share one OSV query. */
87
129
  private readonly loads;
88
- /** Advisory severities by id, with the OSV `modified` time they were
89
- * read at, least recently used first. */
130
+ /** Advisory severities (and malware flag and aliases) by id, with the
131
+ * OSV `modified` time they were read at, least recently used first. */
90
132
  private readonly vulns;
91
133
  /** Advisory ids (and their `modified` time) per exact version from
92
134
  * querybatch, for the audit TTL, least recently used first, so repeated
@@ -121,9 +163,10 @@ export declare class OsvAudit {
121
163
  auditVersions(adapter: AuditAdapter, versions: readonly AuditedVersion[], signal?: AbortSignal): Promise<WithheldVersions>;
122
164
  private loadVersions;
123
165
  private rememberBatch;
124
- /** Whether an advisory is HIGH or CRITICAL, cached by id while OSV's
125
- * `modified` time for it is unchanged. */
126
- private blocking;
166
+ /** Whether an advisory blocks (HIGH, CRITICAL or malware), whether it is
167
+ * malware, and its aliases, cached by id while OSV's `modified` time for
168
+ * it is unchanged. */
169
+ private detail;
127
170
  private remember;
128
171
  private load;
129
172
  private query;
@@ -16,6 +16,7 @@
16
16
  * - a version or event the comparator cannot parse counts as affected
17
17
  * (fail closed).
18
18
  */
19
+ import { sanitizeAuditSummary } from "../../../coding/registry/audit-mode.js";
19
20
  import { RegistryError } from "../../../coding/registry/types.js";
20
21
  import { boundedMetadataFetch, DEFAULT_MAX_METADATA_BYTES, DEFAULT_METADATA_TIMEOUT_MS } from "./bounded-fetch.js";
21
22
  const OSV_QUERY = "https://api.osv.dev/v1/query";
@@ -52,10 +53,59 @@ export function isMalware(vuln) {
52
53
  (typeof detail.source === "string" && detail.source.includes("/malicious-packages/")));
53
54
  });
54
55
  }
56
+ /** An advisory's OSV severity (database_specific.severity), upper-cased; "" when it has none. */
57
+ function severityOf(vuln) {
58
+ const severity = vuln.database_specific?.severity;
59
+ return typeof severity === "string" ? severity.toUpperCase() : "";
60
+ }
55
61
  /** Whether an advisory withholds the versions it affects. */
56
62
  function blocks(vuln) {
57
- return BLOCKING.has(vuln.database_specific?.severity?.toUpperCase() ?? "") || isMalware(vuln);
63
+ return BLOCKING.has(severityOf(vuln)) || isMalware(vuln);
64
+ }
65
+ /** What package audit mode records of an advisory: its severity, and its summary bounded at the source. */
66
+ function auditDetail(vuln) {
67
+ const severity = severityOf(vuln);
68
+ const summary = sanitizeAuditSummary(vuln.summary);
69
+ return { ...(severity ? { severity } : {}), ...(summary ? { summary } : {}) };
70
+ }
71
+ /** Whether `accepted` waives a blocking advisory: it is not malware, and
72
+ * its id or one of its aliases is accepted. Malware is never waived,
73
+ * whatever the accepted set lists. */
74
+ export function isWaived(advisory, accepted) {
75
+ if (advisory.malware || !accepted || accepted.size === 0)
76
+ return false;
77
+ // Belt and braces for entries not built from an OSV record here.
78
+ if ([advisory.id, ...advisory.aliases].some((id) => id.startsWith("MAL-")))
79
+ return false;
80
+ return accepted.has(advisory.id) || advisory.aliases.some((alias) => accepted.has(alias));
81
+ }
82
+ /** Whether a blocking advisory reports, or may report, malicious code: never served in any mode. */
83
+ function isMalwareAdvisory(advisory) {
84
+ return advisory.malware || [advisory.id, ...advisory.aliases].some((id) => id.startsWith("MAL-"));
58
85
  }
86
+ /** Splits the blocking advisories affecting one version into those still
87
+ * withholding it, those `accepted` waives, and (package audit mode `full`,
88
+ * `auditAll`) those served past and recorded. Malware is always withheld.
89
+ * The version is withheld while `withheld` is non-empty. */
90
+ export function splitWaived(advisories, accepted, options = {}) {
91
+ const withheld = [];
92
+ const waived = [];
93
+ const audited = [];
94
+ for (const advisory of advisories) {
95
+ if (isWaived(advisory, accepted))
96
+ waived.push(advisory);
97
+ else if (options.auditAll && !isMalwareAdvisory(advisory))
98
+ audited.push(advisory);
99
+ else
100
+ withheld.push(advisory);
101
+ }
102
+ return { withheld, waived, audited };
103
+ }
104
+ /** A blocking advisory as package audit mode records it. */
105
+ export function auditAdvisoryOf(advisory) {
106
+ return { id: advisory.id, severity: advisory.severity ?? "UNKNOWN", summary: advisory.summary ?? "" };
107
+ }
108
+ const aliasesOf = (vuln) => Array.isArray(vuln.aliases) ? vuln.aliases.filter((alias) => typeof alias === "string") : [];
59
109
  function eventVersion(event) {
60
110
  return event.introduced ?? event.fixed ?? event.last_affected ?? event.limit;
61
111
  }
@@ -122,11 +172,16 @@ function indexOf(advisories, adapter) {
122
172
  const compare = (a, b) => adapter.compareVersions(a, b);
123
173
  const matching = (version, blocking) => advisories
124
174
  .filter((advisory) => advisory.blocking === blocking)
125
- .filter((advisory) => advisory.affected.some((affected) => affects(version, affected, compare)))
126
- .map((advisory) => advisory.id);
127
- return { withheld: (version) => matching(version, true), reported: (version) => matching(version, false) };
175
+ .filter((advisory) => advisory.affected.some((affected) => affects(version, affected, compare)));
176
+ const ids = (list) => list.map((advisory) => advisory.id);
177
+ return {
178
+ withheld: (version, accepted, auditAll) => ids(splitWaived(matching(version, true), accepted, { auditAll }).withheld),
179
+ waived: (version, accepted) => ids(splitWaived(matching(version, true), accepted).waived),
180
+ reported: (version) => ids(matching(version, false)),
181
+ audited: (version, accepted) => splitWaived(matching(version, true), accepted, { auditAll: true }).audited.map(auditAdvisoryOf),
182
+ };
128
183
  }
129
- const EMPTY_INDEX = { withheld: () => [], reported: () => [] };
184
+ const EMPTY_INDEX = { withheld: () => [], waived: () => [], reported: () => [], audited: () => [] };
130
185
  export const DEFAULT_AUDIT_CACHE_ENTRIES = 5000;
131
186
  export const versionKey = (name, version) => `${name}@${version}`;
132
187
  export class OsvAudit {
@@ -137,8 +192,8 @@ export class OsvAudit {
137
192
  cache = new Map();
138
193
  /** Single-flight: concurrent audits of one package share one OSV query. */
139
194
  loads = new Map();
140
- /** Advisory severities by id, with the OSV `modified` time they were
141
- * read at, least recently used first. */
195
+ /** Advisory severities (and malware flag and aliases) by id, with the
196
+ * OSV `modified` time they were read at, least recently used first. */
142
197
  vulns = new Map();
143
198
  /** Advisory ids (and their `modified` time) per exact version from
144
199
  * querybatch, for the audit TTL, least recently used first, so repeated
@@ -286,10 +341,18 @@ export class OsvAudit {
286
341
  while (cursor < ids.length) {
287
342
  const id = ids[cursor++];
288
343
  const advisory = found.get(id);
289
- if (!(await this.blocking(id, advisory.modified, signal)))
344
+ const detail = await this.detail(id, advisory.modified, signal);
345
+ if (!detail.blocking)
290
346
  continue;
347
+ const entry = {
348
+ id,
349
+ malware: detail.malware,
350
+ aliases: detail.aliases,
351
+ ...(detail.severity ? { severity: detail.severity } : {}),
352
+ ...(detail.summary ? { summary: detail.summary } : {}),
353
+ };
291
354
  for (const key of advisory.versions)
292
- withheld.set(key, [...(withheld.get(key) ?? []), id]);
355
+ withheld.set(key, [...(withheld.get(key) ?? []), entry]);
293
356
  }
294
357
  };
295
358
  await Promise.all(Array.from({ length: Math.min(OSV_VULN_CONCURRENCY, ids.length) }, worker));
@@ -307,14 +370,15 @@ export class OsvAudit {
307
370
  }
308
371
  this.batchCache.set(key, { expires: now + this.ttlMs, vulns });
309
372
  }
310
- /** Whether an advisory is HIGH or CRITICAL, cached by id while OSV's
311
- * `modified` time for it is unchanged. */
312
- async blocking(id, modified, signal) {
373
+ /** Whether an advisory blocks (HIGH, CRITICAL or malware), whether it is
374
+ * malware, and its aliases, cached by id while OSV's `modified` time for
375
+ * it is unchanged. */
376
+ async detail(id, modified, signal) {
313
377
  const cached = this.vulns.get(id);
314
378
  if (cached && modified !== "" && cached.modified === modified) {
315
379
  this.vulns.delete(id);
316
380
  this.vulns.set(id, cached); // most recently used
317
- return cached.blocking;
381
+ return cached;
318
382
  }
319
383
  const response = await this.fetch(`${OSV_VULN}${encodeURIComponent(id)}`, { accept: "application/json", signal });
320
384
  if (!response.ok)
@@ -322,7 +386,13 @@ export class OsvAudit {
322
386
  const vuln = (await response.json());
323
387
  if (typeof vuln.id !== "string")
324
388
  throw new Error("osv_vuln_invalid");
325
- const blocking = blocks(vuln);
389
+ const detail = {
390
+ modified: typeof vuln.modified === "string" ? vuln.modified : modified,
391
+ blocking: blocks(vuln),
392
+ malware: isMalware(vuln),
393
+ aliases: aliasesOf(vuln),
394
+ ...auditDetail(vuln),
395
+ };
326
396
  this.vulns.delete(id);
327
397
  while (this.vulns.size >= (this.options.maxVulnEntries ?? DEFAULT_VULN_CACHE_ENTRIES)) {
328
398
  const oldest = this.vulns.keys().next();
@@ -330,8 +400,8 @@ export class OsvAudit {
330
400
  break;
331
401
  this.vulns.delete(oldest.value);
332
402
  }
333
- this.vulns.set(id, { modified: typeof vuln.modified === "string" ? vuln.modified : modified, blocking });
334
- return blocking;
403
+ this.vulns.set(id, detail);
404
+ return detail;
335
405
  }
336
406
  remember(key, advisories) {
337
407
  const now = this.now();
@@ -356,7 +426,14 @@ export class OsvAudit {
356
426
  adapter.normalizeName(entry.package.name) === wanted);
357
427
  if (affected.length === 0)
358
428
  continue;
359
- advisories.push({ id: vuln.id, blocking: blocks(vuln), affected });
429
+ advisories.push({
430
+ id: vuln.id,
431
+ blocking: blocks(vuln),
432
+ malware: isMalware(vuln),
433
+ aliases: aliasesOf(vuln),
434
+ ...auditDetail(vuln),
435
+ affected,
436
+ });
360
437
  }
361
438
  return advisories;
362
439
  }
@@ -0,0 +1,36 @@
1
+ import { type ParsedLockfile } from "../../../coding/registry/types.js";
2
+ export interface ParseRequest {
3
+ ecosystem: string;
4
+ body: string;
5
+ maxEntries: number;
6
+ proxyRegistryUrl: string;
7
+ }
8
+ /** A ParsedLockfile without its functions: `edges[i]` lists, for
9
+ * `entries[i]`, each dependency key the lockfile records that resolves to
10
+ * an entry, with that entry's index; `projectEdges[i]` the same for
11
+ * `projects[i]`. */
12
+ export interface ShippedLockfile {
13
+ entries: ParsedLockfile["entries"];
14
+ projects: ParsedLockfile["projects"];
15
+ integrity?: ParsedLockfile["integrity"];
16
+ edges: [key: string, target: number][][];
17
+ projectEdges: [key: string, target: number][][];
18
+ }
19
+ export type ParseResponse = {
20
+ ok: true;
21
+ lockfile: ShippedLockfile;
22
+ } | {
23
+ ok: false;
24
+ status: number;
25
+ code: string;
26
+ message: string;
27
+ } | {
28
+ ok: false;
29
+ unexpected: true;
30
+ message: string;
31
+ };
32
+ export declare function parseAndShip(request: ParseRequest): ShippedLockfile;
33
+ /** The answer for one parse: the lockfile, the parser's refusal, or (a bug,
34
+ * not a verdict about the lockfile) the unexpected error's message, which
35
+ * the main thread logs. */
36
+ export declare function responseFor(parse: () => ShippedLockfile): ParseResponse;