@wardby/cli 0.1.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 (412) hide show
  1. package/.env.example +131 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +2 -0
  4. package/README.md +282 -0
  5. package/bin/wardby.js +3 -0
  6. package/deploy/local/docker-compose.yml +19 -0
  7. package/dist/claude-coding-worker/driver.d.ts +70 -0
  8. package/dist/claude-coding-worker/driver.js +128 -0
  9. package/dist/claude-coding-worker/main.d.ts +2 -0
  10. package/dist/claude-coding-worker/main.js +41 -0
  11. package/dist/claude-coding-worker/sdk.d.ts +4 -0
  12. package/dist/claude-coding-worker/sdk.js +43 -0
  13. package/dist/claude-coding-worker/tool-relay.d.ts +1 -0
  14. package/dist/claude-coding-worker/tool-relay.js +9 -0
  15. package/dist/cli-help.d.ts +1 -0
  16. package/dist/cli-help.js +20 -0
  17. package/dist/cli.d.ts +18 -0
  18. package/dist/cli.js +629 -0
  19. package/dist/coding/observability.d.ts +59 -0
  20. package/dist/coding/observability.js +77 -0
  21. package/dist/coding/profile.d.ts +88 -0
  22. package/dist/coding/profile.js +137 -0
  23. package/dist/coding/protocol.d.ts +345 -0
  24. package/dist/coding/protocol.js +445 -0
  25. package/dist/coding/provider.d.ts +4 -0
  26. package/dist/coding/provider.js +18 -0
  27. package/dist/coding-proxy/main.d.ts +1 -0
  28. package/dist/coding-proxy/main.js +51 -0
  29. package/dist/coding-worker/artifact.d.ts +16 -0
  30. package/dist/coding-worker/artifact.js +37 -0
  31. package/dist/coding-worker/driver.d.ts +46 -0
  32. package/dist/coding-worker/driver.js +158 -0
  33. package/dist/coding-worker/errors.d.ts +1 -0
  34. package/dist/coding-worker/errors.js +23 -0
  35. package/dist/coding-worker/isolation-probe.d.ts +1 -0
  36. package/dist/coding-worker/isolation-probe.js +146 -0
  37. package/dist/coding-worker/keeper.d.ts +4 -0
  38. package/dist/coding-worker/keeper.js +29 -0
  39. package/dist/coding-worker/main.d.ts +2 -0
  40. package/dist/coding-worker/main.js +43 -0
  41. package/dist/coding-worker/sdk.d.ts +26 -0
  42. package/dist/coding-worker/sdk.js +28 -0
  43. package/dist/coding-worker/types.d.ts +64 -0
  44. package/dist/coding-worker/types.js +1 -0
  45. package/dist/config/providers.d.ts +158 -0
  46. package/dist/config/providers.js +162 -0
  47. package/dist/core/budget-groups.d.ts +72 -0
  48. package/dist/core/budget-groups.js +149 -0
  49. package/dist/core/budget.d.ts +63 -0
  50. package/dist/core/budget.js +69 -0
  51. package/dist/core/coding-queue.d.ts +32 -0
  52. package/dist/core/coding-queue.js +54 -0
  53. package/dist/core/cron.d.ts +31 -0
  54. package/dist/core/cron.js +43 -0
  55. package/dist/core/datastores.d.ts +41 -0
  56. package/dist/core/datastores.js +105 -0
  57. package/dist/core/db.d.ts +2 -0
  58. package/dist/core/db.js +2 -0
  59. package/dist/core/dispatch.d.ts +81 -0
  60. package/dist/core/dispatch.js +184 -0
  61. package/dist/core/engine-native.d.ts +29 -0
  62. package/dist/core/engine-native.js +259 -0
  63. package/dist/core/http-runtime.d.ts +7 -0
  64. package/dist/core/http-runtime.js +101 -0
  65. package/dist/core/lease.d.ts +13 -0
  66. package/dist/core/lease.js +22 -0
  67. package/dist/core/logger.d.ts +13 -0
  68. package/dist/core/logger.js +45 -0
  69. package/dist/core/memory-tools.d.ts +11 -0
  70. package/dist/core/memory-tools.js +122 -0
  71. package/dist/core/reconciler.d.ts +45 -0
  72. package/dist/core/reconciler.js +152 -0
  73. package/dist/core/runner.d.ts +87 -0
  74. package/dist/core/runner.js +529 -0
  75. package/dist/core/scheduler.d.ts +47 -0
  76. package/dist/core/scheduler.js +121 -0
  77. package/dist/core/secrets.d.ts +46 -0
  78. package/dist/core/secrets.js +100 -0
  79. package/dist/core/subagent-memory-tools.d.ts +18 -0
  80. package/dist/core/subagent-memory-tools.js +121 -0
  81. package/dist/core/timing.d.ts +7 -0
  82. package/dist/core/timing.js +7 -0
  83. package/dist/core/webhooks.d.ts +23 -0
  84. package/dist/core/webhooks.js +113 -0
  85. package/dist/env.d.ts +11 -0
  86. package/dist/env.js +13 -0
  87. package/dist/import/budgets.d.ts +16 -0
  88. package/dist/import/budgets.js +21 -0
  89. package/dist/import/bundle.d.ts +16 -0
  90. package/dist/import/bundle.js +61 -0
  91. package/dist/import/cli-args.d.ts +2 -0
  92. package/dist/import/cli-args.js +44 -0
  93. package/dist/import/create.d.ts +34 -0
  94. package/dist/import/create.js +363 -0
  95. package/dist/import/index.d.ts +25 -0
  96. package/dist/import/index.js +130 -0
  97. package/dist/import/model-gate.d.ts +1 -0
  98. package/dist/import/model-gate.js +3 -0
  99. package/dist/import/neutral-schema.d.ts +369 -0
  100. package/dist/import/neutral-schema.js +109 -0
  101. package/dist/import/preflight.d.ts +41 -0
  102. package/dist/import/preflight.js +71 -0
  103. package/dist/import/report.d.ts +5 -0
  104. package/dist/import/report.js +98 -0
  105. package/dist/import/tool-scan.d.ts +8 -0
  106. package/dist/import/tool-scan.js +20 -0
  107. package/dist/mcp/auth/ownership.d.ts +113 -0
  108. package/dist/mcp/auth/ownership.js +87 -0
  109. package/dist/mcp/auth/principal.d.ts +9 -0
  110. package/dist/mcp/auth/principal.js +9 -0
  111. package/dist/mcp/auth/resource-server.d.ts +47 -0
  112. package/dist/mcp/auth/resource-server.js +82 -0
  113. package/dist/mcp/auth/self-hosted/browser.d.ts +3 -0
  114. package/dist/mcp/auth/self-hosted/browser.js +273 -0
  115. package/dist/mcp/auth/self-hosted/cli.d.ts +2 -0
  116. package/dist/mcp/auth/self-hosted/cli.js +39 -0
  117. package/dist/mcp/auth/self-hosted/credentials.d.ts +58 -0
  118. package/dist/mcp/auth/self-hosted/credentials.js +106 -0
  119. package/dist/mcp/auth/self-hosted/rate-limit.d.ts +13 -0
  120. package/dist/mcp/auth/self-hosted/rate-limit.js +20 -0
  121. package/dist/mcp/auth/self-hosted/session.d.ts +36 -0
  122. package/dist/mcp/auth/self-hosted/session.js +110 -0
  123. package/dist/mcp/capabilities.d.ts +11 -0
  124. package/dist/mcp/capabilities.js +10 -0
  125. package/dist/mcp/context.d.ts +46 -0
  126. package/dist/mcp/context.js +1 -0
  127. package/dist/mcp/errors.d.ts +13 -0
  128. package/dist/mcp/errors.js +22 -0
  129. package/dist/mcp/index.d.ts +32 -0
  130. package/dist/mcp/index.js +187 -0
  131. package/dist/mcp/jsonrpc.d.ts +8 -0
  132. package/dist/mcp/jsonrpc.js +1 -0
  133. package/dist/mcp/server.d.ts +107 -0
  134. package/dist/mcp/server.js +203 -0
  135. package/dist/mcp/tasks/manager.d.ts +63 -0
  136. package/dist/mcp/tasks/manager.js +103 -0
  137. package/dist/mcp/tools/agents.d.ts +2 -0
  138. package/dist/mcp/tools/agents.js +375 -0
  139. package/dist/mcp/tools/budget-groups.d.ts +2 -0
  140. package/dist/mcp/tools/budget-groups.js +136 -0
  141. package/dist/mcp/tools/datastore.d.ts +2 -0
  142. package/dist/mcp/tools/datastore.js +217 -0
  143. package/dist/mcp/tools/memory.d.ts +3 -0
  144. package/dist/mcp/tools/memory.js +60 -0
  145. package/dist/mcp/tools/models.d.ts +8 -0
  146. package/dist/mcp/tools/models.js +15 -0
  147. package/dist/mcp/tools/runs.d.ts +2 -0
  148. package/dist/mcp/tools/runs.js +61 -0
  149. package/dist/mcp/tools/scheduling.d.ts +2 -0
  150. package/dist/mcp/tools/scheduling.js +48 -0
  151. package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -0
  152. package/dist/mcp/tools/secret-elicitation-form.js +93 -0
  153. package/dist/mcp/tools/secret-elicitation-server.d.ts +5 -0
  154. package/dist/mcp/tools/secret-elicitation-server.js +57 -0
  155. package/dist/mcp/tools/secret-elicitation.d.ts +38 -0
  156. package/dist/mcp/tools/secret-elicitation.js +52 -0
  157. package/dist/mcp/tools/secrets.d.ts +13 -0
  158. package/dist/mcp/tools/secrets.js +124 -0
  159. package/dist/mcp/tools/subagents.d.ts +2 -0
  160. package/dist/mcp/tools/subagents.js +133 -0
  161. package/dist/mcp/tools/text-result.d.ts +6 -0
  162. package/dist/mcp/tools/text-result.js +3 -0
  163. package/dist/mcp/tools/tools.d.ts +2 -0
  164. package/dist/mcp/tools/tools.js +211 -0
  165. package/dist/mcp/tools/trigger.d.ts +2 -0
  166. package/dist/mcp/tools/trigger.js +120 -0
  167. package/dist/mcp/tools/webhooks.d.ts +2 -0
  168. package/dist/mcp/tools/webhooks.js +34 -0
  169. package/dist/mcp/transport/http-limits.d.ts +17 -0
  170. package/dist/mcp/transport/http-limits.js +92 -0
  171. package/dist/mcp/transport/stdio.d.ts +23 -0
  172. package/dist/mcp/transport/stdio.js +6 -0
  173. package/dist/mcp/transport/streamable-http.d.ts +34 -0
  174. package/dist/mcp/transport/streamable-http.js +158 -0
  175. package/dist/mcp/unattended-schedules.d.ts +15 -0
  176. package/dist/mcp/unattended-schedules.js +21 -0
  177. package/dist/mcp/webhooks/ingress.d.ts +17 -0
  178. package/dist/mcp/webhooks/ingress.js +33 -0
  179. package/dist/observability/config.d.ts +6 -0
  180. package/dist/observability/config.js +20 -0
  181. package/dist/observability/metrics-server.d.ts +11 -0
  182. package/dist/observability/metrics-server.js +47 -0
  183. package/dist/observability/metrics.d.ts +36 -0
  184. package/dist/observability/metrics.js +158 -0
  185. package/dist/providers/auth/authorization-server.d.ts +41 -0
  186. package/dist/providers/auth/authorization-server.js +1 -0
  187. package/dist/providers/auth/delegating.d.ts +44 -0
  188. package/dist/providers/auth/delegating.js +105 -0
  189. package/dist/providers/auth/index.d.ts +11 -0
  190. package/dist/providers/auth/index.js +20 -0
  191. package/dist/providers/auth/release-gate.d.ts +1 -0
  192. package/dist/providers/auth/release-gate.js +4 -0
  193. package/dist/providers/auth/self-hosted.d.ts +78 -0
  194. package/dist/providers/auth/self-hosted.js +377 -0
  195. package/dist/providers/auth/subject.d.ts +1 -0
  196. package/dist/providers/auth/subject.js +6 -0
  197. package/dist/providers/auth/types.d.ts +63 -0
  198. package/dist/providers/auth/types.js +22 -0
  199. package/dist/providers/coding-proxy/deny-port.d.ts +5 -0
  200. package/dist/providers/coding-proxy/deny-port.js +45 -0
  201. package/dist/providers/coding-proxy/environment-credentials.d.ts +7 -0
  202. package/dist/providers/coding-proxy/environment-credentials.js +16 -0
  203. package/dist/providers/coding-proxy/index.d.ts +7 -0
  204. package/dist/providers/coding-proxy/index.js +7 -0
  205. package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -0
  206. package/dist/providers/coding-proxy/memory-ledger.js +103 -0
  207. package/dist/providers/coding-proxy/metering.d.ts +20 -0
  208. package/dist/providers/coding-proxy/metering.js +161 -0
  209. package/dist/providers/coding-proxy/prisma-ledger.d.ts +15 -0
  210. package/dist/providers/coding-proxy/prisma-ledger.js +213 -0
  211. package/dist/providers/coding-proxy/proxy.d.ts +75 -0
  212. package/dist/providers/coding-proxy/proxy.js +721 -0
  213. package/dist/providers/coding-proxy/runtime.d.ts +18 -0
  214. package/dist/providers/coding-proxy/runtime.js +39 -0
  215. package/dist/providers/coding-proxy/secure-fetch.d.ts +9 -0
  216. package/dist/providers/coding-proxy/secure-fetch.js +72 -0
  217. package/dist/providers/coding-proxy/server.d.ts +17 -0
  218. package/dist/providers/coding-proxy/server.js +139 -0
  219. package/dist/providers/coding-proxy/types.d.ts +99 -0
  220. package/dist/providers/coding-proxy/types.js +1 -0
  221. package/dist/providers/datastore/index.d.ts +2 -0
  222. package/dist/providers/datastore/index.js +2 -0
  223. package/dist/providers/datastore/postgres.d.ts +20 -0
  224. package/dist/providers/datastore/postgres.js +130 -0
  225. package/dist/providers/datastore/scoped.d.ts +10 -0
  226. package/dist/providers/datastore/scoped.js +46 -0
  227. package/dist/providers/datastore/types.d.ts +31 -0
  228. package/dist/providers/datastore/types.js +7 -0
  229. package/dist/providers/email/types.d.ts +46 -0
  230. package/dist/providers/email/types.js +8 -0
  231. package/dist/providers/engine/index.d.ts +1 -0
  232. package/dist/providers/engine/index.js +1 -0
  233. package/dist/providers/engine/types.d.ts +67 -0
  234. package/dist/providers/engine/types.js +16 -0
  235. package/dist/providers/executor/build.d.ts +6 -0
  236. package/dist/providers/executor/build.js +15 -0
  237. package/dist/providers/executor/composition.d.ts +14 -0
  238. package/dist/providers/executor/composition.js +123 -0
  239. package/dist/providers/executor/container.d.ts +184 -0
  240. package/dist/providers/executor/container.js +936 -0
  241. package/dist/providers/executor/dbos-status.d.ts +50 -0
  242. package/dist/providers/executor/dbos-status.js +64 -0
  243. package/dist/providers/executor/dbos.d.ts +53 -0
  244. package/dist/providers/executor/dbos.js +269 -0
  245. package/dist/providers/executor/in-process.d.ts +18 -0
  246. package/dist/providers/executor/in-process.js +38 -0
  247. package/dist/providers/executor/index.d.ts +8 -0
  248. package/dist/providers/executor/index.js +8 -0
  249. package/dist/providers/executor/routing.d.ts +48 -0
  250. package/dist/providers/executor/routing.js +70 -0
  251. package/dist/providers/executor/types.d.ts +55 -0
  252. package/dist/providers/executor/types.js +1 -0
  253. package/dist/providers/index.d.ts +43 -0
  254. package/dist/providers/index.js +18 -0
  255. package/dist/providers/jobs/docker-isolation.d.ts +166 -0
  256. package/dist/providers/jobs/docker-isolation.js +724 -0
  257. package/dist/providers/jobs/docker.d.ts +127 -0
  258. package/dist/providers/jobs/docker.js +1027 -0
  259. package/dist/providers/jobs/fake-kubernetes-api.d.ts +98 -0
  260. package/dist/providers/jobs/fake-kubernetes-api.js +142 -0
  261. package/dist/providers/jobs/fake.d.ts +23 -0
  262. package/dist/providers/jobs/fake.js +132 -0
  263. package/dist/providers/jobs/kubernetes-api.d.ts +60 -0
  264. package/dist/providers/jobs/kubernetes-api.js +20 -0
  265. package/dist/providers/jobs/kubernetes-client.d.ts +36 -0
  266. package/dist/providers/jobs/kubernetes-client.js +171 -0
  267. package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +49 -0
  268. package/dist/providers/jobs/kubernetes-dry-run-fixture.js +141 -0
  269. package/dist/providers/jobs/kubernetes-isolation.d.ts +147 -0
  270. package/dist/providers/jobs/kubernetes-isolation.js +607 -0
  271. package/dist/providers/jobs/kubernetes-platform.d.ts +177 -0
  272. package/dist/providers/jobs/kubernetes-platform.js +280 -0
  273. package/dist/providers/jobs/kubernetes-preflight.d.ts +59 -0
  274. package/dist/providers/jobs/kubernetes-preflight.js +339 -0
  275. package/dist/providers/jobs/kubernetes-witness.d.ts +10 -0
  276. package/dist/providers/jobs/kubernetes-witness.js +193 -0
  277. package/dist/providers/jobs/kubernetes.d.ts +127 -0
  278. package/dist/providers/jobs/kubernetes.js +874 -0
  279. package/dist/providers/jobs/safe-extract.d.ts +9 -0
  280. package/dist/providers/jobs/safe-extract.js +325 -0
  281. package/dist/providers/jobs/types.d.ts +78 -0
  282. package/dist/providers/jobs/types.js +6 -0
  283. package/dist/providers/jobs/workspace-swap.d.ts +2 -0
  284. package/dist/providers/jobs/workspace-swap.js +47 -0
  285. package/dist/providers/llm/anthropic.d.ts +13 -0
  286. package/dist/providers/llm/anthropic.js +21 -0
  287. package/dist/providers/llm/bedrock.d.ts +19 -0
  288. package/dist/providers/llm/bedrock.js +33 -0
  289. package/dist/providers/llm/claude-messages.d.ts +106 -0
  290. package/dist/providers/llm/claude-messages.js +157 -0
  291. package/dist/providers/llm/claude-provider.d.ts +40 -0
  292. package/dist/providers/llm/claude-provider.js +31 -0
  293. package/dist/providers/llm/index.d.ts +10 -0
  294. package/dist/providers/llm/index.js +10 -0
  295. package/dist/providers/llm/openai.d.ts +23 -0
  296. package/dist/providers/llm/openai.js +156 -0
  297. package/dist/providers/llm/pricing-anthropic.d.ts +4 -0
  298. package/dist/providers/llm/pricing-anthropic.js +30 -0
  299. package/dist/providers/llm/pricing-bedrock-claude.d.ts +12 -0
  300. package/dist/providers/llm/pricing-bedrock-claude.js +37 -0
  301. package/dist/providers/llm/pricing-core.d.ts +26 -0
  302. package/dist/providers/llm/pricing-core.js +17 -0
  303. package/dist/providers/llm/pricing.d.ts +30 -0
  304. package/dist/providers/llm/pricing.js +74 -0
  305. package/dist/providers/llm/registration.d.ts +8 -0
  306. package/dist/providers/llm/registration.js +39 -0
  307. package/dist/providers/llm/routing.d.ts +25 -0
  308. package/dist/providers/llm/routing.js +32 -0
  309. package/dist/providers/llm/types.d.ts +85 -0
  310. package/dist/providers/llm/types.js +12 -0
  311. package/dist/providers/memory/index.d.ts +2 -0
  312. package/dist/providers/memory/index.js +2 -0
  313. package/dist/providers/memory/postgres.d.ts +20 -0
  314. package/dist/providers/memory/postgres.js +72 -0
  315. package/dist/providers/memory/types.d.ts +32 -0
  316. package/dist/providers/memory/types.js +17 -0
  317. package/dist/providers/secrets/app-key.d.ts +8 -0
  318. package/dist/providers/secrets/app-key.js +50 -0
  319. package/dist/providers/secrets/index.d.ts +10 -0
  320. package/dist/providers/secrets/index.js +13 -0
  321. package/dist/providers/secrets/transfer-envelope.d.ts +12 -0
  322. package/dist/providers/secrets/transfer-envelope.js +35 -0
  323. package/dist/providers/secrets/types.d.ts +18 -0
  324. package/dist/providers/secrets/types.js +12 -0
  325. package/dist/providers/storage/types.d.ts +18 -0
  326. package/dist/providers/storage/types.js +7 -0
  327. package/dist/providers/vcs/git.d.ts +105 -0
  328. package/dist/providers/vcs/git.js +710 -0
  329. package/dist/providers/vcs/github.d.ts +105 -0
  330. package/dist/providers/vcs/github.js +394 -0
  331. package/dist/providers/vcs/index.d.ts +6 -0
  332. package/dist/providers/vcs/index.js +26 -0
  333. package/dist/providers/vcs/types.d.ts +118 -0
  334. package/dist/providers/vcs/types.js +1 -0
  335. package/dist/sandbox/bounded-json.d.ts +2 -0
  336. package/dist/sandbox/bounded-json.js +36 -0
  337. package/dist/sandbox/bridge.d.ts +15 -0
  338. package/dist/sandbox/bridge.js +78 -0
  339. package/dist/sandbox/eval-core.d.ts +37 -0
  340. package/dist/sandbox/eval-core.js +159 -0
  341. package/dist/sandbox/fetch-policy.d.ts +24 -0
  342. package/dist/sandbox/fetch-policy.js +96 -0
  343. package/dist/sandbox/generated/zod-to-json-schema.bundle.js +5 -0
  344. package/dist/sandbox/generated/zod.bundle.js +1 -0
  345. package/dist/sandbox/host-functions.d.ts +29 -0
  346. package/dist/sandbox/host-functions.js +168 -0
  347. package/dist/sandbox/limits.d.ts +39 -0
  348. package/dist/sandbox/limits.js +39 -0
  349. package/dist/sandbox/parser-worker/__fixtures__/crash.d.ts +1 -0
  350. package/dist/sandbox/parser-worker/__fixtures__/crash.js +6 -0
  351. package/dist/sandbox/parser-worker/__fixtures__/echo.d.ts +1 -0
  352. package/dist/sandbox/parser-worker/__fixtures__/echo.js +5 -0
  353. package/dist/sandbox/parser-worker/__fixtures__/reject.d.ts +1 -0
  354. package/dist/sandbox/parser-worker/__fixtures__/reject.js +5 -0
  355. package/dist/sandbox/parser-worker/__fixtures__/spin-forever.d.ts +1 -0
  356. package/dist/sandbox/parser-worker/__fixtures__/spin-forever.js +11 -0
  357. package/dist/sandbox/parser-worker/pool.d.ts +13 -0
  358. package/dist/sandbox/parser-worker/pool.js +111 -0
  359. package/dist/sandbox/parser-worker/worker.d.ts +14 -0
  360. package/dist/sandbox/parser-worker/worker.js +63 -0
  361. package/dist/sandbox/pii-redaction.d.ts +1 -0
  362. package/dist/sandbox/pii-redaction.js +29 -0
  363. package/dist/sandbox/prelude.d.ts +26 -0
  364. package/dist/sandbox/prelude.js +408 -0
  365. package/dist/sandbox/quickjs-module.d.ts +13 -0
  366. package/dist/sandbox/quickjs-module.js +19 -0
  367. package/dist/sandbox/run-in-sandbox.d.ts +34 -0
  368. package/dist/sandbox/run-in-sandbox.js +53 -0
  369. package/dist/sandbox/safe-fetch.d.ts +26 -0
  370. package/dist/sandbox/safe-fetch.js +140 -0
  371. package/dist/sandbox/tool-capabilities.d.ts +66 -0
  372. package/dist/sandbox/tool-capabilities.js +103 -0
  373. package/dist/sandbox/zod-params.d.ts +22 -0
  374. package/dist/sandbox/zod-params.js +60 -0
  375. package/dist/serve.d.ts +14 -0
  376. package/dist/serve.js +54 -0
  377. package/dist/wardby-bin.d.ts +2 -0
  378. package/dist/wardby-bin.js +20 -0
  379. package/package.json +123 -0
  380. package/prisma/migrations/20260905000000_init/migration.sql +34 -0
  381. package/prisma/migrations/20260905010000_scheduler_durability/migration.sql +31 -0
  382. package/prisma/migrations/20260905020000_tools_multiturn/migration.sql +47 -0
  383. package/prisma/migrations/20260905030000_cache_tool_json_schema/migration.sql +13 -0
  384. package/prisma/migrations/20260906000000_mcp_phase4/migration.sql +115 -0
  385. package/prisma/migrations/20260906010000_run_final_text/migration.sql +7 -0
  386. package/prisma/migrations/20260906020000_run_turns/migration.sql +6 -0
  387. package/prisma/migrations/20260906030000_task_principal_id/migration.sql +5 -0
  388. package/prisma/migrations/20260906040000_secure_self_hosted_oauth/migration.sql +67 -0
  389. package/prisma/migrations/20260906050000_phase5_coding_agents/migration.sql +52 -0
  390. package/prisma/migrations/20260906060000_tool_capability_scoping/migration.sql +22 -0
  391. package/prisma/migrations/20260906070000_datastore_pii_flag/migration.sql +6 -0
  392. package/prisma/migrations/20260906080000_secret_elicitation_outcomes/migration.sql +13 -0
  393. package/prisma/migrations/20260907010000_coding_proxy_ledger/migration.sql +57 -0
  394. package/prisma/migrations/20260907020000_budget_groups/migration.sql +24 -0
  395. package/prisma/migrations/20260907030000_coding_webhook_task_override/migration.sql +4 -0
  396. package/prisma/migrations/20260908010000_run_execution_backend/migration.sql +2 -0
  397. package/prisma/migrations/20260908020000_coding_run_audit_metadata/migration.sql +7 -0
  398. package/prisma/migrations/20260910010000_agent_secret_bound_name/migration.sql +16 -0
  399. package/prisma/migrations/20260911010000_coding_worker_toolchains/migration.sql +5 -0
  400. package/prisma/migrations/20260912010000_coding_provider_contract/migration.sql +24 -0
  401. package/prisma/migrations/20260912020000_coding_proxy_protocol/migration.sql +10 -0
  402. package/prisma/migrations/20260912030000_agent_memory/migration.sql +18 -0
  403. package/prisma/migrations/20260912040000_named_shared_datastores/migration.sql +68 -0
  404. package/prisma/migrations/20260913000000_run_trigger_webhook/migration.sql +2 -0
  405. package/prisma/migrations/20260913010000_agent_sub_agent/migration.sql +32 -0
  406. package/prisma/migrations/20260913020000_run_task_override/migration.sql +5 -0
  407. package/prisma/migrations/20260913030000_coding_run_root/migration.sql +11 -0
  408. package/prisma/migrations/20260922010000_coding_run_queued_at/migration.sql +8 -0
  409. package/prisma/migrations/20260922020000_coding_workspace_disk/migration.sql +8 -0
  410. package/prisma/migrations/migration_lock.toml +3 -0
  411. package/prisma/schema.prisma +723 -0
  412. package/scripts/git-askpass.sh +11 -0
@@ -0,0 +1,171 @@
1
+ /**
2
+ * KubernetesApi over @kubernetes/client-node 2.x. A thin mapping: each seam
3
+ * method is one client call plus HTTP-status translation into the seam's
4
+ * error classes. Proven against a real cluster by kubernetes.integration.test.ts.
5
+ */
6
+ import { ApiException, CoreV1Api, Exec, KubeConfig, NetworkingV1Api, VersionApi, } from "@kubernetes/client-node";
7
+ import { Writable } from "node:stream";
8
+ import { KubernetesAlreadyExistsError, KubernetesConflictError, KubernetesNotFoundError, } from "./kubernetes-api.js";
9
+ function statusCode(error) {
10
+ return error instanceof ApiException ? error.code : undefined;
11
+ }
12
+ /** Undefined for a 404; rethrows anything else. */
13
+ async function readOrUndefined(read) {
14
+ try {
15
+ return await read();
16
+ }
17
+ catch (error) {
18
+ if (statusCode(error) === 404)
19
+ return undefined;
20
+ throw error;
21
+ }
22
+ }
23
+ /** Swallows a 404 so deletes are idempotent. */
24
+ async function deleteIgnoringMissing(remove) {
25
+ try {
26
+ await remove();
27
+ }
28
+ catch (error) {
29
+ if (statusCode(error) === 404)
30
+ return;
31
+ throw error;
32
+ }
33
+ }
34
+ async function create(what, write) {
35
+ try {
36
+ return await write();
37
+ }
38
+ catch (error) {
39
+ const code = statusCode(error);
40
+ if (code === 409)
41
+ throw new KubernetesAlreadyExistsError(what);
42
+ if (code === 404)
43
+ throw new KubernetesNotFoundError(what);
44
+ throw error;
45
+ }
46
+ }
47
+ async function replace(what, write) {
48
+ try {
49
+ return await write();
50
+ }
51
+ catch (error) {
52
+ const code = statusCode(error);
53
+ if (code === 409)
54
+ throw new KubernetesConflictError(what);
55
+ if (code === 404)
56
+ throw new KubernetesNotFoundError(what);
57
+ throw error;
58
+ }
59
+ }
60
+ /** Exit code from the exec status channel: "Success" is 0, else the ExitCode cause, else 1. */
61
+ function exitCodeFromStatus(status) {
62
+ if (status.status === "Success")
63
+ return 0;
64
+ const cause = status.details?.causes?.find((c) => c.reason === "ExitCode");
65
+ const parsed = cause?.message === undefined ? Number.NaN : Number.parseInt(cause.message, 10);
66
+ return Number.isInteger(parsed) ? parsed : 1;
67
+ }
68
+ export class ClientNodeKubernetesApi {
69
+ config;
70
+ core;
71
+ networking;
72
+ version;
73
+ constructor(options = {}) {
74
+ this.config = new KubeConfig();
75
+ this.config.loadFromDefault();
76
+ if (options.context)
77
+ this.config.setCurrentContext(options.context);
78
+ this.core = this.config.makeApiClient(CoreV1Api);
79
+ this.networking = this.config.makeApiClient(NetworkingV1Api);
80
+ this.version = this.config.makeApiClient(VersionApi);
81
+ }
82
+ createConfigMap(namespace, body) {
83
+ return create(`configmap/${namespace}/${body.metadata?.name}`, () => this.core.createNamespacedConfigMap({ namespace, body }));
84
+ }
85
+ readConfigMap(namespace, name) {
86
+ return readOrUndefined(() => this.core.readNamespacedConfigMap({ namespace, name }));
87
+ }
88
+ replaceConfigMap(namespace, name, body) {
89
+ return replace(`configmap/${namespace}/${name}`, () => this.core.replaceNamespacedConfigMap({ namespace, name, body }));
90
+ }
91
+ createSecret(namespace, body) {
92
+ return create(`secret/${namespace}/${body.metadata?.name}`, () => this.core.createNamespacedSecret({ namespace, body }));
93
+ }
94
+ deleteSecret(namespace, name) {
95
+ return deleteIgnoringMissing(() => this.core.deleteNamespacedSecret({ namespace, name }));
96
+ }
97
+ createPod(namespace, body) {
98
+ return create(`pod/${namespace}/${body.metadata?.name}`, () => this.core.createNamespacedPod({ namespace, body }));
99
+ }
100
+ dryRunCreatePod(namespace, body) {
101
+ return create(`pod/${namespace}/${body.metadata?.name}?dryRun`, () => this.core.createNamespacedPod({ namespace, body, dryRun: "All" }));
102
+ }
103
+ readPod(namespace, name) {
104
+ return readOrUndefined(() => this.core.readNamespacedPod({ namespace, name }));
105
+ }
106
+ deletePod(namespace, name, gracePeriodSeconds) {
107
+ return deleteIgnoringMissing(() => this.core.deleteNamespacedPod({ namespace, name, gracePeriodSeconds }));
108
+ }
109
+ createNetworkPolicy(namespace, body) {
110
+ return create(`networkpolicy/${namespace}/${body.metadata?.name}`, () => this.networking.createNamespacedNetworkPolicy({ namespace, body }));
111
+ }
112
+ readNetworkPolicy(namespace, name) {
113
+ return readOrUndefined(() => this.networking.readNamespacedNetworkPolicy({ namespace, name }));
114
+ }
115
+ deleteNetworkPolicy(namespace, name) {
116
+ return deleteIgnoringMissing(() => this.networking.deleteNamespacedNetworkPolicy({ namespace, name }));
117
+ }
118
+ readService(namespace, name) {
119
+ return readOrUndefined(() => this.core.readNamespacedService({ namespace, name }));
120
+ }
121
+ readEndpoints(namespace, name) {
122
+ return readOrUndefined(() => this.core.readNamespacedEndpoints({ namespace, name }));
123
+ }
124
+ async readApiServerVersion() {
125
+ return (await this.version.getCode()).gitVersion;
126
+ }
127
+ async readNamespace(name) {
128
+ return (await readOrUndefined(() => this.core.readNamespace({ name }))) !== undefined;
129
+ }
130
+ exec(namespace, pod, container, command, options) {
131
+ // stderr is requested but discarded so it never reaches wardby's logs.
132
+ const stderr = new Writable({
133
+ write(_chunk, _encoding, callback) {
134
+ callback();
135
+ },
136
+ });
137
+ return new Promise((resolve, reject) => {
138
+ let settled = false;
139
+ let socket;
140
+ const settle = (outcome) => {
141
+ if (settled)
142
+ return;
143
+ settled = true;
144
+ clearTimeout(timer);
145
+ outcome();
146
+ };
147
+ const timer = setTimeout(() => {
148
+ settle(() => reject(new Error("kubernetes_exec_timeout")));
149
+ socket?.close();
150
+ }, options.timeoutMs);
151
+ new Exec(this.config)
152
+ .exec(namespace, pod, container, command, options.stdout ?? null, stderr, options.stdin ?? null, false, (status) => settle(() => resolve(exitCodeFromStatus(status))))
153
+ .then((ws) => {
154
+ socket = ws;
155
+ // Timed out while still connecting: close the late socket.
156
+ if (settled) {
157
+ socket.close();
158
+ return;
159
+ }
160
+ // The status callback fires before the library closes the socket, so a close
161
+ // that arrives first means the command's exit status was never reported.
162
+ socket.addEventListener("close", () => settle(() => reject(new Error("kubernetes_exec_closed_without_status"))));
163
+ },
164
+ // A failed WebSocket handshake rejects with a ws ErrorEvent, not an Error.
165
+ (error) => settle(() => reject(error instanceof Error ? error : new Error("kubernetes_exec_connect_failed", { cause: error }))));
166
+ });
167
+ }
168
+ readLogTail(namespace, pod, container, tailLines, limitBytes) {
169
+ return this.core.readNamespacedPodLog({ namespace, name: pod, container, tailLines, limitBytes });
170
+ }
171
+ }
@@ -0,0 +1,49 @@
1
+ import type { KubernetesPlatform } from "./kubernetes-platform.js";
2
+ export interface PodMutation {
3
+ op: "add" | "replace" | "remove";
4
+ /** JSON Pointer (RFC 6901): "/" separated, with ~1 for "/" and ~0 for "~". */
5
+ path: string;
6
+ value?: unknown;
7
+ }
8
+ export interface DryRunFixture {
9
+ capturedAt: string;
10
+ platform: KubernetesPlatform;
11
+ /** True until a real server-side dry run replaces this file. */
12
+ provisional: boolean;
13
+ source: string;
14
+ notes: string[];
15
+ mutations: PodMutation[];
16
+ }
17
+ export declare function loadDryRunFixture(): DryRunFixture;
18
+ /**
19
+ * Returns a copy of `document` with every mutation applied in order.
20
+ *
21
+ * `add` and `replace` assign at the pointer. `remove` deletes an object key,
22
+ * but SPLICES an array element: `delete array[2]` would leave a hole that
23
+ * serializes back as `null`, which would then be deep-compared against a real
24
+ * pod as a null list entry rather than as a removal. The differ only ever
25
+ * replaces arrays wholesale, so an array pointer can reach here only from a
26
+ * hand-written fixture entry — which is exactly when a silent `null` hole
27
+ * would be hardest to spot in review.
28
+ */
29
+ export declare function applyMutations<T>(document: T, mutations: readonly PodMutation[]): T;
30
+ /**
31
+ * The mutations that turn `before` into `after`. Objects are walked key by key;
32
+ * anything else (including arrays) is replaced wholesale, which keeps a
33
+ * toleration list or a container list readable as one op.
34
+ *
35
+ * The equality check for that wholesale case goes through `canonical()` (recursive key
36
+ * sort), not a raw `JSON.stringify`: a captured pod's nested objects come back from a real
37
+ * API server with different key insertion order than `buildRunPod`'s own literals even when
38
+ * every value is identical, and a raw string compare would misread that as a genuine change —
39
+ * replacing an entire container or volume list with an opaque, unreviewable blob that a real
40
+ * platform rewrite could hide inside just as easily. `canonical()` makes the comparison see
41
+ * only actual value differences, while still emitting one "replace" op per array so the fixture
42
+ * stays readable.
43
+ *
44
+ * Sorted by code point, not `localeCompare`: the result is committed to a file
45
+ * and reviewed as a diff, so the order must not depend on the capturing
46
+ * machine's locale (an ICU collation folds case together and orders
47
+ * `/spec/Foo` and `/spec/foo` by tie-break rules that differ between hosts).
48
+ */
49
+ export declare function diffMutations(before: unknown, after: unknown, prefix?: string): PodMutation[];
@@ -0,0 +1,141 @@
1
+ /**
2
+ * The recorded Autopilot admission mutations, and the two pure functions that
3
+ * produce and replay them.
4
+ *
5
+ * The fixture stores a *mutation list*, not a pair of whole pods, for two
6
+ * reasons: a reviewer can read the entire set of differences the platform
7
+ * introduces in a few lines, and the test rebuilds the submitted pod from the
8
+ * live builder rather than replaying a stored one, so the fixture can never
9
+ * carry a stale *pod*.
10
+ *
11
+ * That is a narrower guarantee than it sounds, and the difference matters.
12
+ * Because the attestation test derives BOTH operands from the same builder, it
13
+ * is structurally blind to a weakening of the builder itself: measured on this
14
+ * branch, setting `automountServiceAccountToken: true` or halving the worker's
15
+ * CPU leaves the whole suite green. Three other sabotages — dropping
16
+ * `runtimeClassName`, dropping the pod `seccompProfile`, `hostPID: true` — do
17
+ * fail it, but only incidentally: those exact fields appear in the "rejects one
18
+ * more mutation" tamper list, so a builder that already emits the tampered
19
+ * value turns that tamper into a no-op. That is luck, not coverage, and it is
20
+ * not a property to rely on.
21
+ *
22
+ * What this file guards is that the *platform's* mutation set is still exactly
23
+ * the set the profile forgives. The builder's own fields are guarded by
24
+ * kubernetes-isolation.test.ts and kubernetes-platform.test.ts, and must stay
25
+ * that way.
26
+ *
27
+ * `provisional` is true while the file is written from documentation rather
28
+ * than captured from a cluster. The attestation suite names that state in its
29
+ * report, so a forgotten capture cannot pass unnoticed.
30
+ *
31
+ * This is development data reviewed in a diff, never a runtime authority: the
32
+ * launcher never asks a cluster what it is allowed to change.
33
+ */
34
+ import { readFileSync } from "node:fs";
35
+ import { canonical } from "./kubernetes-isolation.js";
36
+ const FIXTURE_URL = new URL("./fixtures/gke-autopilot-dry-run.json", import.meta.url);
37
+ export function loadDryRunFixture() {
38
+ return JSON.parse(readFileSync(FIXTURE_URL, "utf8"));
39
+ }
40
+ function segments(path) {
41
+ if (path === "" || !path.startsWith("/"))
42
+ throw new Error(`dry_run_fixture_path: ${path}`);
43
+ return path
44
+ .slice(1)
45
+ .split("/")
46
+ .map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"));
47
+ }
48
+ function container(root, path) {
49
+ let node = root;
50
+ for (const key of path) {
51
+ if (node === null || typeof node !== "object")
52
+ throw new Error(`dry_run_fixture_path: /${path.join("/")}`);
53
+ node = node[key];
54
+ }
55
+ if (node === null || typeof node !== "object")
56
+ throw new Error(`dry_run_fixture_path: /${path.join("/")}`);
57
+ return node;
58
+ }
59
+ /**
60
+ * Returns a copy of `document` with every mutation applied in order.
61
+ *
62
+ * `add` and `replace` assign at the pointer. `remove` deletes an object key,
63
+ * but SPLICES an array element: `delete array[2]` would leave a hole that
64
+ * serializes back as `null`, which would then be deep-compared against a real
65
+ * pod as a null list entry rather than as a removal. The differ only ever
66
+ * replaces arrays wholesale, so an array pointer can reach here only from a
67
+ * hand-written fixture entry — which is exactly when a silent `null` hole
68
+ * would be hardest to spot in review.
69
+ */
70
+ export function applyMutations(document, mutations) {
71
+ const copy = structuredClone(document);
72
+ for (const mutation of mutations) {
73
+ const path = segments(mutation.path);
74
+ // `segments` always yields at least one element for a pointer starting with "/", so this
75
+ // never throws in practice; it narrows the type without a non-null assertion.
76
+ const key = path.pop();
77
+ if (key === undefined)
78
+ throw new Error(`dry_run_fixture_path: ${mutation.path}`);
79
+ const parent = container(copy, path);
80
+ if (Array.isArray(parent) && mutation.op === "remove") {
81
+ const index = /^(0|[1-9][0-9]*)$/.test(key) ? Number(key) : -1;
82
+ if (index < 0 || index >= parent.length)
83
+ throw new Error(`dry_run_fixture_path: ${mutation.path}`);
84
+ parent.splice(index, 1);
85
+ continue;
86
+ }
87
+ const bag = parent;
88
+ if (mutation.op === "remove")
89
+ delete bag[key];
90
+ else
91
+ bag[key] = structuredClone(mutation.value);
92
+ }
93
+ return copy;
94
+ }
95
+ function escape(key) {
96
+ return key.replaceAll("~", "~0").replaceAll("/", "~1");
97
+ }
98
+ /**
99
+ * The mutations that turn `before` into `after`. Objects are walked key by key;
100
+ * anything else (including arrays) is replaced wholesale, which keeps a
101
+ * toleration list or a container list readable as one op.
102
+ *
103
+ * The equality check for that wholesale case goes through `canonical()` (recursive key
104
+ * sort), not a raw `JSON.stringify`: a captured pod's nested objects come back from a real
105
+ * API server with different key insertion order than `buildRunPod`'s own literals even when
106
+ * every value is identical, and a raw string compare would misread that as a genuine change —
107
+ * replacing an entire container or volume list with an opaque, unreviewable blob that a real
108
+ * platform rewrite could hide inside just as easily. `canonical()` makes the comparison see
109
+ * only actual value differences, while still emitting one "replace" op per array so the fixture
110
+ * stays readable.
111
+ *
112
+ * Sorted by code point, not `localeCompare`: the result is committed to a file
113
+ * and reviewed as a diff, so the order must not depend on the capturing
114
+ * machine's locale (an ICU collation folds case together and orders
115
+ * `/spec/Foo` and `/spec/foo` by tie-break rules that differ between hosts).
116
+ */
117
+ export function diffMutations(before, after, prefix = "") {
118
+ const plain = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
119
+ if (!plain(before) || !plain(after)) {
120
+ return JSON.stringify(canonical(before)) === JSON.stringify(canonical(after))
121
+ ? []
122
+ : [{ op: "replace", path: prefix, value: after }];
123
+ }
124
+ const left = before;
125
+ const right = after;
126
+ const mutations = [];
127
+ for (const key of new Set([...Object.keys(left), ...Object.keys(right)])) {
128
+ const path = `${prefix}/${escape(key)}`;
129
+ if (!(key in right) || right[key] === undefined) {
130
+ if (left[key] !== undefined)
131
+ mutations.push({ op: "remove", path });
132
+ }
133
+ else if (!(key in left) || left[key] === undefined) {
134
+ mutations.push({ op: "add", path, value: right[key] });
135
+ }
136
+ else {
137
+ mutations.push(...diffMutations(left[key], right[key], path));
138
+ }
139
+ }
140
+ return mutations.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
141
+ }
@@ -0,0 +1,147 @@
1
+ import type { V1NetworkPolicy, V1Pod, V1Secret } from "@kubernetes/client-node";
2
+ import type { JobSpec } from "./types.js";
3
+ import { type KubernetesPlatform } from "./kubernetes-platform.js";
4
+ export declare const KUBERNETES_ISOLATION_ERROR = "kubernetes_isolation_unsupported";
5
+ export declare const KUBERNETES_PROVIDER_UNSUPPORTED = "kubernetes_provider_unsupported";
6
+ /** Extra seconds past timeoutSec before Kubernetes kills the pod (keeper included). */
7
+ export declare const POD_DEADLINE_GRACE_SECONDS = 300;
8
+ export declare const KEEPER_CONTAINER = "keeper";
9
+ export declare const STORAGE_INIT_CONTAINER = "storage-init";
10
+ export declare const WORKER_CONTAINER = "worker";
11
+ export declare const STORAGE_ROOT = "/run/wardby/storage";
12
+ export declare const KEEPER_SEEDED_MARKER = "/run/wardby/storage/input/.seeded";
13
+ export declare const PROXY_POD_LABEL: {
14
+ readonly "app.kubernetes.io/name": "wardby-coding-proxy";
15
+ };
16
+ /**
17
+ * What every run pod carries and what the proxy's own ingress rule must admit on the deny port.
18
+ * Single source: `runLabels` stamps it, `readProxyWitness` checks the proxy admits it.
19
+ */
20
+ export declare const RUN_COMPONENT_LABEL: {
21
+ readonly "wardby.io/component": "coding-run";
22
+ };
23
+ /** The probe proved enforcement: the proxy port connected and the deny port was blocked. */
24
+ export declare const ENFORCEMENT_PROBE_PROVEN = 0;
25
+ /** The deny port was reachable: no policy is blocking it, or the policy is not port-scoped. */
26
+ export declare const ENFORCEMENT_PROBE_DENY_REACHABLE = 3;
27
+ /** The proxy port itself was unreachable: nothing could be witnessed (proxy down, or only the namespace default-deny is programmed). */
28
+ export declare const ENFORCEMENT_PROBE_PROXY_UNREACHABLE = 4;
29
+ /**
30
+ * The deny port answered with an RST: the SYN reached the destination host, so nothing is
31
+ * blocking the path — the port is reachable-but-unserved and witnesses nothing.
32
+ */
33
+ export declare const ENFORCEMENT_PROBE_DENY_REFUSED = 5;
34
+ export interface KubernetesRunNames {
35
+ token: string;
36
+ runSha: string;
37
+ pod: string;
38
+ policy: string;
39
+ record: string;
40
+ secret: string;
41
+ }
42
+ /**
43
+ * The per-run object names for a run token. The only place the naming scheme lives: the launcher
44
+ * resolves a handle's token through this, so names can never drift between creation and cleanup.
45
+ */
46
+ export declare function kubernetesRunNamesForToken(token: string): Omit<KubernetesRunNames, "runSha">;
47
+ export declare function kubernetesRunNames(runId: string): KubernetesRunNames;
48
+ export declare function runLabels(runId: string): Record<string, string>;
49
+ /** Same grammar as Docker's repository digests; a cluster cannot pull a bare local image ID. */
50
+ export declare function isRegistryDigest(image: string): boolean;
51
+ export declare function validateKubernetesSpec(spec: JobSpec): void;
52
+ export interface RunPodOptions {
53
+ namespace: string;
54
+ proxyIp: string;
55
+ runtimeClassName?: string;
56
+ /** Which platform's admission rules the emitted resources must already satisfy. Default: "generic". */
57
+ platform?: KubernetesPlatform;
58
+ }
59
+ export declare function buildRunPod(spec: JobSpec, options: RunPodOptions): V1Pod;
60
+ export declare function buildRunNetworkPolicy(spec: JobSpec, namespace: string): V1NetworkPolicy;
61
+ export declare function buildCapabilitySecret(spec: JobSpec, namespace: string, capability: string): V1Secret;
62
+ /**
63
+ * A copy of `pod` with ONLY the API server's own defaulting and aliasing undone
64
+ * — the same `normalizeSpec` pass `assertRunPodMatches` runs, and nothing else.
65
+ *
66
+ * Exported for src/tools/capture-fixture.ts, which runs it over both the
67
+ * submitted and the returned pod before diffing them. Without it the diff is
68
+ * dominated by fields every API server fills in on every create
69
+ * (schedulerName, priority, terminationMessagePath on each container, probe
70
+ * defaults, `2048Mi` requantized to `2Gi`, ...); because the differ replaces
71
+ * arrays wholesale those collapse into opaque `replace /spec/containers`
72
+ * blobs, and a genuine platform rewrite *inside* a container would be
73
+ * indistinguishable from the noise.
74
+ *
75
+ * It deliberately does NOT apply `normalizePlatformMetadata`: that deletes
76
+ * exactly the platform-injected keys a capture exists to record. Fails closed
77
+ * (throws) on a spec the normalizer cannot make sense of.
78
+ */
79
+ export declare function undoApiServerDefaults(pod: V1Pod): V1Pod;
80
+ /**
81
+ * Recursively sorts object keys and drops `undefined` values so key order and API-omitted
82
+ * fields never matter; array order is preserved.
83
+ *
84
+ * Exported for kubernetes-dry-run-fixture.ts's `diffMutations`: a captured pod's nested objects
85
+ * (container resource requests, volume definitions, host aliases, ...) come back from a real
86
+ * cluster with different key insertion order than `buildRunPod`'s own object literals, even when
87
+ * every value is identical. Without canonicalizing first, `diffMutations`' array branch treats
88
+ * that key-order difference as a genuine change and replaces the WHOLE array (every container,
89
+ * every volume) with an opaque blob — exactly the failure mode its own doc comment warns a real
90
+ * platform rewrite could hide inside. `assertRunPodMatches` below is unaffected by this (it
91
+ * already canonicalizes before comparing); only the capture tool's mutation list was at risk.
92
+ */
93
+ export declare function canonical(value: unknown): unknown;
94
+ /**
95
+ * Deep-compares the pod the API server read back against the pod wardby built.
96
+ * ANY surviving difference fails the run closed.
97
+ *
98
+ * `platform` defaults to "generic" on purpose: a caller that forgets it gets the
99
+ * strictest behaviour, never the most permissive. A profile can only narrow what
100
+ * counts as an expected difference (by deleting named keys from both operands);
101
+ * it can never disable or short-circuit the comparison.
102
+ */
103
+ export declare function assertRunPodMatches(actual: V1Pod, expected: V1Pod, platform?: KubernetesPlatform): void;
104
+ export declare function assertRunNetworkPolicyMatches(actual: V1NetworkPolicy, expected: V1NetworkPolicy): void;
105
+ /**
106
+ * A `node -e` script (argv only, never a shell) that measures BOTH of the proxy's
107
+ * ports in one pass, with a 3 s connect timeout each (above Linux's 1 s initial
108
+ * SYN retransmission, so one dropped SYN on an allowed path still connects).
109
+ *
110
+ * Measuring both is what makes the result decisive. A NetworkPolicy denial drops
111
+ * the packet rather than rejecting it — GKE Dataplane V2, which Autopilot runs,
112
+ * always drops — so "the deny port did not answer" is equally consistent with
113
+ * "the proxy is gone and no policy exists at all". Requiring the proxy port to
114
+ * connect in the *same* probe turns "something is listening" from a control-plane
115
+ * inference into a fact this pod just observed.
116
+ *
117
+ * That pairing alone is still not enough, and this was reproduced on a live
118
+ * cluster: in a namespace with NO NetworkPolicy at all, against a pod listening
119
+ * on 8787 and serving nothing on 8788, a probe that collapsed `error` and
120
+ * `timeout` into one "not reachable" exited PROVEN while it had full internet
121
+ * egress. The pairing only rules out "the whole proxy pod is dead"; whenever the
122
+ * deny *listener specifically* is unserved, "blocked" and "nothing there" are
123
+ * the same observation. No control-plane read fixes this — Endpoints subset
124
+ * ports come from the Service's numeric targetPort, not from anything actually
125
+ * binding — so the distinction has to be made in the dataplane, here:
126
+ *
127
+ * - deny port **times out** → the packet was dropped somewhere on the path → the only outcome
128
+ * that can prove a policy. Note what it does NOT prove on its own: *which* hop dropped it. That
129
+ * it was the run pod's own egress policy follows from the proxy admitting run pods on the deny
130
+ * port at its own ingress, leaving no other hop that would drop it — a precondition the
131
+ * preflight's `proxy-service` check now verifies (readProxyWitness), after a live cluster
132
+ * falsified the assumption: with the drop moved to the destination, a prober holding no policy
133
+ * at all and with full internet egress read PROVEN.
134
+ * - deny port **refused** (RST / ECONNREFUSED) → the SYN reached the destination host, so
135
+ * nothing blocked the path. This holds on every dataplane, drop-based ones included, because
136
+ * a drop cannot produce an RST. Reported as ENFORCEMENT_PROBE_DENY_REFUSED, never as proven.
137
+ * - proxy port must still CONNECT for anything to count at all.
138
+ *
139
+ * Consequence, intended: on a **reject-style** CNI a genuine policy denial also arrives as an
140
+ * RST, so such a cluster now fails closed here rather than passing vacuously. Failing closed on
141
+ * a cluster whose refusals are ambiguous is the correct direction — a witness that cannot tell
142
+ * "denied" from "unserved" is not a witness — and such a cluster needs a different one.
143
+ *
144
+ * Exit codes are ENFORCEMENT_PROBE_PROVEN / _DENY_REACHABLE / _PROXY_UNREACHABLE / _DENY_REFUSED.
145
+ * The IP is validated and embedded as a JSON string literal.
146
+ */
147
+ export declare function enforcementProbeScript(proxyIp: string): string;