@stigmer/server 3.15.3-dev.20260914121148 → 3.16.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 (680) hide show
  1. package/README.md +3 -3
  2. package/dist/archive/content-store.d.ts +35 -0
  3. package/dist/archive/content-store.d.ts.map +1 -0
  4. package/dist/archive/content-store.js +98 -0
  5. package/dist/archive/content-store.js.map +1 -0
  6. package/dist/archive/inflate.d.ts +22 -0
  7. package/dist/archive/inflate.d.ts.map +1 -0
  8. package/dist/archive/inflate.js +75 -0
  9. package/dist/archive/inflate.js.map +1 -0
  10. package/dist/archive/limits.d.ts +33 -0
  11. package/dist/archive/limits.d.ts.map +1 -0
  12. package/dist/archive/limits.js +31 -0
  13. package/dist/archive/limits.js.map +1 -0
  14. package/dist/archive/open.d.ts +24 -0
  15. package/dist/archive/open.d.ts.map +1 -0
  16. package/dist/archive/open.js +93 -0
  17. package/dist/archive/open.js.map +1 -0
  18. package/dist/{domain/skill/storage → archive}/prefilter.d.ts +5 -0
  19. package/dist/archive/prefilter.d.ts.map +1 -0
  20. package/dist/archive/prefilter.js.map +1 -0
  21. package/dist/archive/write.d.ts +8 -0
  22. package/dist/archive/write.d.ts.map +1 -0
  23. package/dist/archive/write.js +44 -0
  24. package/dist/archive/write.js.map +1 -0
  25. package/dist/authorization/authorizer.d.ts +98 -0
  26. package/dist/authorization/authorizer.d.ts.map +1 -0
  27. package/dist/authorization/authorizer.js +156 -0
  28. package/dist/authorization/authorizer.js.map +1 -0
  29. package/dist/authorization/derived-tuples.d.ts +42 -0
  30. package/dist/authorization/derived-tuples.d.ts.map +1 -0
  31. package/dist/authorization/derived-tuples.js +240 -0
  32. package/dist/authorization/derived-tuples.js.map +1 -0
  33. package/dist/authorization/evaluator.d.ts +66 -0
  34. package/dist/authorization/evaluator.d.ts.map +1 -0
  35. package/dist/authorization/evaluator.js +153 -0
  36. package/dist/authorization/evaluator.js.map +1 -0
  37. package/dist/authorization/facts.d.ts +29 -0
  38. package/dist/authorization/facts.d.ts.map +1 -0
  39. package/dist/authorization/facts.js +17 -0
  40. package/dist/authorization/facts.js.map +1 -0
  41. package/dist/authorization/lane-admission.d.ts +50 -0
  42. package/dist/authorization/lane-admission.d.ts.map +1 -0
  43. package/dist/authorization/lane-admission.js +13 -0
  44. package/dist/authorization/lane-admission.js.map +1 -0
  45. package/dist/authorization/list-read-scope.d.ts +18 -0
  46. package/dist/authorization/list-read-scope.d.ts.map +1 -0
  47. package/dist/authorization/list-read-scope.js +155 -0
  48. package/dist/authorization/list-read-scope.js.map +1 -0
  49. package/dist/authorization/model/agent.d.ts +2 -0
  50. package/dist/authorization/model/agent.d.ts.map +1 -0
  51. package/dist/authorization/model/agent.js +42 -0
  52. package/dist/authorization/model/agent.js.map +1 -0
  53. package/dist/authorization/model/agent_channel.d.ts +2 -0
  54. package/dist/authorization/model/agent_channel.d.ts.map +1 -0
  55. package/dist/authorization/model/agent_channel.js +38 -0
  56. package/dist/authorization/model/agent_channel.js.map +1 -0
  57. package/dist/authorization/model/agent_execution.d.ts +2 -0
  58. package/dist/authorization/model/agent_execution.d.ts.map +1 -0
  59. package/dist/authorization/model/agent_execution.js +25 -0
  60. package/dist/authorization/model/agent_execution.js.map +1 -0
  61. package/dist/authorization/model/agent_instance.d.ts +2 -0
  62. package/dist/authorization/model/agent_instance.d.ts.map +1 -0
  63. package/dist/authorization/model/agent_instance.js +47 -0
  64. package/dist/authorization/model/agent_instance.js.map +1 -0
  65. package/dist/authorization/model/agent_share.d.ts +2 -0
  66. package/dist/authorization/model/agent_share.d.ts.map +1 -0
  67. package/dist/authorization/model/agent_share.js +29 -0
  68. package/dist/authorization/model/agent_share.js.map +1 -0
  69. package/dist/authorization/model/api_key.d.ts +2 -0
  70. package/dist/authorization/model/api_key.d.ts.map +1 -0
  71. package/dist/authorization/model/api_key.js +27 -0
  72. package/dist/authorization/model/api_key.js.map +1 -0
  73. package/dist/authorization/model/artifact.d.ts +2 -0
  74. package/dist/authorization/model/artifact.d.ts.map +1 -0
  75. package/dist/authorization/model/artifact.js +27 -0
  76. package/dist/authorization/model/artifact.js.map +1 -0
  77. package/dist/authorization/model/channel_app.d.ts +2 -0
  78. package/dist/authorization/model/channel_app.d.ts.map +1 -0
  79. package/dist/authorization/model/channel_app.js +28 -0
  80. package/dist/authorization/model/channel_app.js.map +1 -0
  81. package/dist/authorization/model/default-of.d.ts +38 -0
  82. package/dist/authorization/model/default-of.d.ts.map +1 -0
  83. package/dist/authorization/model/default-of.js +39 -0
  84. package/dist/authorization/model/default-of.js.map +1 -0
  85. package/dist/authorization/model/environment.d.ts +2 -0
  86. package/dist/authorization/model/environment.d.ts.map +1 -0
  87. package/dist/authorization/model/environment.js +33 -0
  88. package/dist/authorization/model/environment.js.map +1 -0
  89. package/dist/authorization/model/execution_context.d.ts +2 -0
  90. package/dist/authorization/model/execution_context.d.ts.map +1 -0
  91. package/dist/authorization/model/execution_context.js +19 -0
  92. package/dist/authorization/model/execution_context.js.map +1 -0
  93. package/dist/authorization/model/iam_policy.d.ts +2 -0
  94. package/dist/authorization/model/iam_policy.d.ts.map +1 -0
  95. package/dist/authorization/model/iam_policy.js +31 -0
  96. package/dist/authorization/model/iam_policy.js.map +1 -0
  97. package/dist/authorization/model/identity_account.d.ts +2 -0
  98. package/dist/authorization/model/identity_account.d.ts.map +1 -0
  99. package/dist/authorization/model/identity_account.js +25 -0
  100. package/dist/authorization/model/identity_account.js.map +1 -0
  101. package/dist/authorization/model/index.d.ts +36 -0
  102. package/dist/authorization/model/index.d.ts.map +1 -0
  103. package/dist/authorization/model/index.js +72 -0
  104. package/dist/authorization/model/index.js.map +1 -0
  105. package/dist/authorization/model/mcp_server.d.ts +2 -0
  106. package/dist/authorization/model/mcp_server.d.ts.map +1 -0
  107. package/dist/authorization/model/mcp_server.js +37 -0
  108. package/dist/authorization/model/mcp_server.js.map +1 -0
  109. package/dist/authorization/model/memory.d.ts +2 -0
  110. package/dist/authorization/model/memory.d.ts.map +1 -0
  111. package/dist/authorization/model/memory.js +26 -0
  112. package/dist/authorization/model/memory.js.map +1 -0
  113. package/dist/authorization/model/oauth_app.d.ts +2 -0
  114. package/dist/authorization/model/oauth_app.d.ts.map +1 -0
  115. package/dist/authorization/model/oauth_app.js +30 -0
  116. package/dist/authorization/model/oauth_app.js.map +1 -0
  117. package/dist/authorization/model/organization.d.ts +2 -0
  118. package/dist/authorization/model/organization.d.ts.map +1 -0
  119. package/dist/authorization/model/organization.js +54 -0
  120. package/dist/authorization/model/organization.js.map +1 -0
  121. package/dist/authorization/model/plugin.d.ts +2 -0
  122. package/dist/authorization/model/plugin.d.ts.map +1 -0
  123. package/dist/authorization/model/plugin.js +44 -0
  124. package/dist/authorization/model/plugin.js.map +1 -0
  125. package/dist/authorization/model/project.d.ts +2 -0
  126. package/dist/authorization/model/project.d.ts.map +1 -0
  127. package/dist/authorization/model/project.js +32 -0
  128. package/dist/authorization/model/project.js.map +1 -0
  129. package/dist/authorization/model/rewrite.d.ts +127 -0
  130. package/dist/authorization/model/rewrite.d.ts.map +1 -0
  131. package/dist/authorization/model/rewrite.js +82 -0
  132. package/dist/authorization/model/rewrite.js.map +1 -0
  133. package/dist/authorization/model/schedule.d.ts +2 -0
  134. package/dist/authorization/model/schedule.d.ts.map +1 -0
  135. package/dist/authorization/model/schedule.js +29 -0
  136. package/dist/authorization/model/schedule.js.map +1 -0
  137. package/dist/authorization/model/session.d.ts +2 -0
  138. package/dist/authorization/model/session.d.ts.map +1 -0
  139. package/dist/authorization/model/session.js +38 -0
  140. package/dist/authorization/model/session.js.map +1 -0
  141. package/dist/authorization/model/skill.d.ts +2 -0
  142. package/dist/authorization/model/skill.d.ts.map +1 -0
  143. package/dist/authorization/model/skill.js +38 -0
  144. package/dist/authorization/model/skill.js.map +1 -0
  145. package/dist/authorization/model/workflow.d.ts +2 -0
  146. package/dist/authorization/model/workflow.d.ts.map +1 -0
  147. package/dist/authorization/model/workflow.js +38 -0
  148. package/dist/authorization/model/workflow.js.map +1 -0
  149. package/dist/authorization/model/workflow_execution.d.ts +2 -0
  150. package/dist/authorization/model/workflow_execution.d.ts.map +1 -0
  151. package/dist/authorization/model/workflow_execution.js +32 -0
  152. package/dist/authorization/model/workflow_execution.js.map +1 -0
  153. package/dist/authorization/model/workflow_instance.d.ts +2 -0
  154. package/dist/authorization/model/workflow_instance.d.ts.map +1 -0
  155. package/dist/authorization/model/workflow_instance.js +92 -0
  156. package/dist/authorization/model/workflow_instance.js.map +1 -0
  157. package/dist/authorization/organization-directory.d.ts +13 -0
  158. package/dist/authorization/organization-directory.d.ts.map +1 -0
  159. package/dist/authorization/organization-directory.js +83 -0
  160. package/dist/authorization/organization-directory.js.map +1 -0
  161. package/dist/authorization/person.d.ts +42 -0
  162. package/dist/authorization/person.d.ts.map +1 -0
  163. package/dist/authorization/person.js +19 -0
  164. package/dist/authorization/person.js.map +1 -0
  165. package/dist/authorization/posture.d.ts +38 -0
  166. package/dist/authorization/posture.d.ts.map +1 -0
  167. package/dist/authorization/posture.js +7 -0
  168. package/dist/authorization/posture.js.map +1 -0
  169. package/dist/authorization/schedule-fire-caller.d.ts +12 -0
  170. package/dist/authorization/schedule-fire-caller.d.ts.map +1 -0
  171. package/dist/authorization/schedule-fire-caller.js +67 -0
  172. package/dist/authorization/schedule-fire-caller.js.map +1 -0
  173. package/dist/authorization/store-test-kit.d.ts +68 -0
  174. package/dist/authorization/store-test-kit.d.ts.map +1 -0
  175. package/dist/authorization/store-test-kit.js +311 -0
  176. package/dist/authorization/store-test-kit.js.map +1 -0
  177. package/dist/authorization/tuples.d.ts +115 -0
  178. package/dist/authorization/tuples.d.ts.map +1 -0
  179. package/dist/authorization/tuples.js +83 -0
  180. package/dist/authorization/tuples.js.map +1 -0
  181. package/dist/boot/compose.d.ts.map +1 -1
  182. package/dist/boot/compose.js +220 -43
  183. package/dist/boot/compose.js.map +1 -1
  184. package/dist/boot/inprocess.d.ts +12 -0
  185. package/dist/boot/inprocess.d.ts.map +1 -1
  186. package/dist/boot/inprocess.js +68 -21
  187. package/dist/boot/inprocess.js.map +1 -1
  188. package/dist/domain/agent/controller.d.ts.map +1 -1
  189. package/dist/domain/agent/controller.js +9 -0
  190. package/dist/domain/agent/controller.js.map +1 -1
  191. package/dist/domain/executioncontext/resolve-values-for-caller.d.ts +33 -14
  192. package/dist/domain/executioncontext/resolve-values-for-caller.d.ts.map +1 -1
  193. package/dist/domain/executioncontext/resolve-values-for-caller.js +32 -8
  194. package/dist/domain/executioncontext/resolve-values-for-caller.js.map +1 -1
  195. package/dist/domain/iampolicy/constants.d.ts +11 -0
  196. package/dist/domain/iampolicy/constants.d.ts.map +1 -1
  197. package/dist/domain/iampolicy/constants.js +11 -0
  198. package/dist/domain/iampolicy/constants.js.map +1 -1
  199. package/dist/domain/iampolicy/membership.d.ts +72 -1
  200. package/dist/domain/iampolicy/membership.d.ts.map +1 -1
  201. package/dist/domain/iampolicy/membership.js +141 -56
  202. package/dist/domain/iampolicy/membership.js.map +1 -1
  203. package/dist/domain/identityaccount/actor.d.ts +41 -0
  204. package/dist/domain/identityaccount/actor.d.ts.map +1 -0
  205. package/dist/domain/identityaccount/actor.js +34 -0
  206. package/dist/domain/identityaccount/actor.js.map +1 -0
  207. package/dist/domain/identityaccount/resolve.d.ts +19 -0
  208. package/dist/domain/identityaccount/resolve.d.ts.map +1 -1
  209. package/dist/domain/identityaccount/resolve.js +12 -0
  210. package/dist/domain/identityaccount/resolve.js.map +1 -1
  211. package/dist/domain/mcpserver/connect-execution-id.d.ts +5 -0
  212. package/dist/domain/mcpserver/connect-execution-id.d.ts.map +1 -0
  213. package/dist/domain/mcpserver/connect-execution-id.js +32 -0
  214. package/dist/domain/mcpserver/connect-execution-id.js.map +1 -0
  215. package/dist/domain/mcpserver/connect.d.ts +28 -2
  216. package/dist/domain/mcpserver/connect.d.ts.map +1 -1
  217. package/dist/domain/mcpserver/connect.js +27 -7
  218. package/dist/domain/mcpserver/connect.js.map +1 -1
  219. package/dist/domain/mcpserver/controller.d.ts.map +1 -1
  220. package/dist/domain/mcpserver/controller.js +9 -0
  221. package/dist/domain/mcpserver/controller.js.map +1 -1
  222. package/dist/domain/mcpserver/engine.d.ts +9 -3
  223. package/dist/domain/mcpserver/engine.d.ts.map +1 -1
  224. package/dist/domain/mcpserver/engine.js.map +1 -1
  225. package/dist/domain/mcpserver/start-connect.js +1 -1
  226. package/dist/domain/mcpserver/start-connect.js.map +1 -1
  227. package/dist/domain/platform/controller.d.ts +24 -11
  228. package/dist/domain/platform/controller.d.ts.map +1 -1
  229. package/dist/domain/platform/controller.js.map +1 -1
  230. package/dist/domain/plugin/archive.d.ts +37 -0
  231. package/dist/domain/plugin/archive.d.ts.map +1 -0
  232. package/dist/domain/plugin/archive.js +50 -0
  233. package/dist/domain/plugin/archive.js.map +1 -0
  234. package/dist/domain/plugin/constants.d.ts +38 -0
  235. package/dist/domain/plugin/constants.d.ts.map +1 -0
  236. package/dist/domain/plugin/constants.js +46 -0
  237. package/dist/domain/plugin/constants.js.map +1 -0
  238. package/dist/domain/plugin/controller.d.ts +25 -0
  239. package/dist/domain/plugin/controller.d.ts.map +1 -0
  240. package/dist/domain/plugin/controller.js +493 -0
  241. package/dist/domain/plugin/controller.js.map +1 -0
  242. package/dist/domain/plugin/materialize/agent.d.ts +13 -0
  243. package/dist/domain/plugin/materialize/agent.d.ts.map +1 -0
  244. package/dist/domain/plugin/materialize/agent.js +128 -0
  245. package/dist/domain/plugin/materialize/agent.js.map +1 -0
  246. package/dist/domain/plugin/materialize/default-agent-instructions.d.ts +22 -0
  247. package/dist/domain/plugin/materialize/default-agent-instructions.d.ts.map +1 -0
  248. package/dist/domain/plugin/materialize/default-agent-instructions.js +31 -0
  249. package/dist/domain/plugin/materialize/default-agent-instructions.js.map +1 -0
  250. package/dist/domain/plugin/materialize/identity.d.ts +28 -0
  251. package/dist/domain/plugin/materialize/identity.d.ts.map +1 -0
  252. package/dist/domain/plugin/materialize/identity.js +40 -0
  253. package/dist/domain/plugin/materialize/identity.js.map +1 -0
  254. package/dist/domain/plugin/materialize/mcp-servers.d.ts +15 -0
  255. package/dist/domain/plugin/materialize/mcp-servers.d.ts.map +1 -0
  256. package/dist/domain/plugin/materialize/mcp-servers.js +131 -0
  257. package/dist/domain/plugin/materialize/mcp-servers.js.map +1 -0
  258. package/dist/domain/plugin/materialize/plan.d.ts +24 -0
  259. package/dist/domain/plugin/materialize/plan.d.ts.map +1 -0
  260. package/dist/domain/plugin/materialize/plan.js +77 -0
  261. package/dist/domain/plugin/materialize/plan.js.map +1 -0
  262. package/dist/domain/plugin/materialize/ports.d.ts +42 -0
  263. package/dist/domain/plugin/materialize/ports.d.ts.map +1 -0
  264. package/dist/domain/plugin/materialize/ports.js +2 -0
  265. package/dist/domain/plugin/materialize/ports.js.map +1 -0
  266. package/dist/domain/plugin/materialize/skills.d.ts +12 -0
  267. package/dist/domain/plugin/materialize/skills.d.ts.map +1 -0
  268. package/dist/domain/plugin/materialize/skills.js +44 -0
  269. package/dist/domain/plugin/materialize/skills.js.map +1 -0
  270. package/dist/domain/plugin/materialize/workflows.d.ts +15 -0
  271. package/dist/domain/plugin/materialize/workflows.d.ts.map +1 -0
  272. package/dist/domain/plugin/materialize/workflows.js +31 -0
  273. package/dist/domain/plugin/materialize/workflows.js.map +1 -0
  274. package/dist/domain/plugin/members.d.ts +42 -0
  275. package/dist/domain/plugin/members.d.ts.map +1 -0
  276. package/dist/domain/plugin/members.js +97 -0
  277. package/dist/domain/plugin/members.js.map +1 -0
  278. package/dist/domain/plugin/overlay/documents.d.ts +31 -0
  279. package/dist/domain/plugin/overlay/documents.d.ts.map +1 -0
  280. package/dist/domain/plugin/overlay/documents.js +38 -0
  281. package/dist/domain/plugin/overlay/documents.js.map +1 -0
  282. package/dist/domain/plugin/overlay/parse.d.ts +16 -0
  283. package/dist/domain/plugin/overlay/parse.d.ts.map +1 -0
  284. package/dist/domain/plugin/overlay/parse.js +79 -0
  285. package/dist/domain/plugin/overlay/parse.js.map +1 -0
  286. package/dist/domain/plugin/overlay/sanitize.d.ts +10 -0
  287. package/dist/domain/plugin/overlay/sanitize.d.ts.map +1 -0
  288. package/dist/domain/plugin/overlay/sanitize.js +103 -0
  289. package/dist/domain/plugin/overlay/sanitize.js.map +1 -0
  290. package/dist/domain/plugin/push.d.ts +133 -0
  291. package/dist/domain/plugin/push.d.ts.map +1 -0
  292. package/dist/domain/plugin/push.js +800 -0
  293. package/dist/domain/plugin/push.js.map +1 -0
  294. package/dist/domain/plugin/search-extractor.d.ts +3 -0
  295. package/dist/domain/plugin/search-extractor.d.ts.map +1 -0
  296. package/dist/domain/plugin/search-extractor.js +41 -0
  297. package/dist/domain/plugin/search-extractor.js.map +1 -0
  298. package/dist/domain/skill/constants.d.ts +6 -11
  299. package/dist/domain/skill/constants.d.ts.map +1 -1
  300. package/dist/domain/skill/constants.js +6 -11
  301. package/dist/domain/skill/constants.js.map +1 -1
  302. package/dist/domain/skill/controller.d.ts.map +1 -1
  303. package/dist/domain/skill/controller.js +33 -30
  304. package/dist/domain/skill/controller.js.map +1 -1
  305. package/dist/domain/skill/push.d.ts +9 -10
  306. package/dist/domain/skill/push.d.ts.map +1 -1
  307. package/dist/domain/skill/push.js +53 -122
  308. package/dist/domain/skill/push.js.map +1 -1
  309. package/dist/domain/skill/search-extractor.d.ts.map +1 -1
  310. package/dist/domain/skill/search-extractor.js.map +1 -1
  311. package/dist/domain/skill/storage/artifact-storage.d.ts +26 -29
  312. package/dist/domain/skill/storage/artifact-storage.d.ts.map +1 -1
  313. package/dist/domain/skill/storage/artifact-storage.js +6 -103
  314. package/dist/domain/skill/storage/artifact-storage.js.map +1 -1
  315. package/dist/domain/skill/storage/zip-gate.d.ts +1 -2
  316. package/dist/domain/skill/storage/zip-gate.d.ts.map +1 -1
  317. package/dist/domain/skill/storage/zip-gate.js +56 -126
  318. package/dist/domain/skill/storage/zip-gate.js.map +1 -1
  319. package/dist/domain/skill/version-resolution.d.ts +5 -5
  320. package/dist/domain/skill/version-resolution.d.ts.map +1 -1
  321. package/dist/domain/skill/version-resolution.js +34 -216
  322. package/dist/domain/skill/version-resolution.js.map +1 -1
  323. package/dist/domain/workflow/controller.d.ts.map +1 -1
  324. package/dist/domain/workflow/controller.js +30 -3
  325. package/dist/domain/workflow/controller.js.map +1 -1
  326. package/dist/domain/workflow/registry/data/task-kind-registry.json +1 -0
  327. package/dist/domain/workflowexecution/phases.d.ts +21 -0
  328. package/dist/domain/workflowexecution/phases.d.ts.map +1 -0
  329. package/dist/domain/workflowexecution/phases.js +31 -0
  330. package/dist/domain/workflowexecution/phases.js.map +1 -0
  331. package/dist/extensions/authorizer.d.ts +10 -5
  332. package/dist/extensions/authorizer.d.ts.map +1 -1
  333. package/dist/extensions/drivers.d.ts +4 -1
  334. package/dist/extensions/drivers.d.ts.map +1 -1
  335. package/dist/extensions/list-read-scope.d.ts +47 -20
  336. package/dist/extensions/list-read-scope.d.ts.map +1 -1
  337. package/dist/extensions/list-read-scope.js +20 -24
  338. package/dist/extensions/list-read-scope.js.map +1 -1
  339. package/dist/extensions/organization-directory.d.ts +13 -9
  340. package/dist/extensions/organization-directory.d.ts.map +1 -1
  341. package/dist/extensions/organization-directory.js.map +1 -1
  342. package/dist/extensions/resource-authorization.d.ts +33 -0
  343. package/dist/extensions/resource-authorization.d.ts.map +1 -1
  344. package/dist/extensions/schedule-fire-caller.d.ts +45 -18
  345. package/dist/extensions/schedule-fire-caller.d.ts.map +1 -1
  346. package/dist/extensions/schedule-fire-caller.js +12 -1
  347. package/dist/extensions/schedule-fire-caller.js.map +1 -1
  348. package/dist/identity/oidc-verifier.js +8 -1
  349. package/dist/identity/oidc-verifier.js.map +1 -1
  350. package/dist/index.d.ts +10 -0
  351. package/dist/index.d.ts.map +1 -1
  352. package/dist/index.js +8 -0
  353. package/dist/index.js.map +1 -1
  354. package/dist/pipeline/apiresource-labels.d.ts +23 -3
  355. package/dist/pipeline/apiresource-labels.d.ts.map +1 -1
  356. package/dist/pipeline/apiresource-labels.js +20 -0
  357. package/dist/pipeline/apiresource-labels.js.map +1 -1
  358. package/dist/pipeline/apiresource-meta.d.ts +15 -0
  359. package/dist/pipeline/apiresource-meta.d.ts.map +1 -1
  360. package/dist/pipeline/apiresource-meta.js +34 -0
  361. package/dist/pipeline/apiresource-meta.js.map +1 -1
  362. package/dist/pipeline/errors.d.ts.map +1 -1
  363. package/dist/pipeline/errors.js.map +1 -1
  364. package/dist/pipeline/steps/authorization-facts.d.ts +12 -0
  365. package/dist/pipeline/steps/authorization-facts.d.ts.map +1 -0
  366. package/dist/pipeline/steps/authorization-facts.js +100 -0
  367. package/dist/pipeline/steps/authorization-facts.js.map +1 -0
  368. package/dist/pipeline/steps/delete.d.ts.map +1 -1
  369. package/dist/pipeline/steps/delete.js +1 -1
  370. package/dist/pipeline/steps/delete.js.map +1 -1
  371. package/dist/pipeline/steps/duplicate.d.ts.map +1 -1
  372. package/dist/pipeline/steps/duplicate.js.map +1 -1
  373. package/dist/pipeline/steps/guard-memory-capture.d.ts.map +1 -1
  374. package/dist/pipeline/steps/guard-memory-capture.js +5 -3
  375. package/dist/pipeline/steps/guard-memory-capture.js.map +1 -1
  376. package/dist/pipeline/steps/guard-plugin-managed.d.ts +12 -0
  377. package/dist/pipeline/steps/guard-plugin-managed.d.ts.map +1 -0
  378. package/dist/pipeline/steps/guard-plugin-managed.js +96 -0
  379. package/dist/pipeline/steps/guard-plugin-managed.js.map +1 -0
  380. package/dist/pipeline/steps/guard-reserved-labels.d.ts +16 -2
  381. package/dist/pipeline/steps/guard-reserved-labels.d.ts.map +1 -1
  382. package/dist/pipeline/steps/guard-reserved-labels.js +11 -7
  383. package/dist/pipeline/steps/guard-reserved-labels.js.map +1 -1
  384. package/dist/pipeline/steps/helpers.d.ts.map +1 -1
  385. package/dist/pipeline/steps/helpers.js.map +1 -1
  386. package/dist/pipeline/steps/index-search.d.ts.map +1 -1
  387. package/dist/pipeline/steps/index-search.js.map +1 -1
  388. package/dist/pipeline/steps/load-existing.d.ts.map +1 -1
  389. package/dist/pipeline/steps/load-existing.js +1 -1
  390. package/dist/pipeline/steps/load-existing.js.map +1 -1
  391. package/dist/pipeline/steps/references.d.ts +16 -0
  392. package/dist/pipeline/steps/references.d.ts.map +1 -1
  393. package/dist/pipeline/steps/references.js +18 -0
  394. package/dist/pipeline/steps/references.js.map +1 -1
  395. package/dist/pipeline/steps/resolve-artifact-source.d.ts +35 -0
  396. package/dist/pipeline/steps/resolve-artifact-source.d.ts.map +1 -0
  397. package/dist/pipeline/steps/resolve-artifact-source.js +27 -0
  398. package/dist/pipeline/steps/resolve-artifact-source.js.map +1 -0
  399. package/dist/pipeline/steps/server-stamped-reserved-labels.d.ts.map +1 -1
  400. package/dist/pipeline/steps/server-stamped-reserved-labels.js.map +1 -1
  401. package/dist/pipeline/steps/slug.d.ts.map +1 -1
  402. package/dist/pipeline/steps/slug.js.map +1 -1
  403. package/dist/pipeline/steps/validate-visibility.d.ts +9 -0
  404. package/dist/pipeline/steps/validate-visibility.d.ts.map +1 -1
  405. package/dist/pipeline/steps/validate-visibility.js +6 -1
  406. package/dist/pipeline/steps/validate-visibility.js.map +1 -1
  407. package/dist/pipeline/steps/validation.d.ts.map +1 -1
  408. package/dist/pipeline/steps/validation.js.map +1 -1
  409. package/dist/pipeline/steps/version-archive.d.ts +63 -0
  410. package/dist/pipeline/steps/version-archive.d.ts.map +1 -0
  411. package/dist/pipeline/steps/version-archive.js +129 -0
  412. package/dist/pipeline/steps/version-archive.js.map +1 -0
  413. package/dist/pipeline/steps/version-history.d.ts +49 -0
  414. package/dist/pipeline/steps/version-history.d.ts.map +1 -0
  415. package/dist/pipeline/steps/version-history.js +229 -0
  416. package/dist/pipeline/steps/version-history.js.map +1 -0
  417. package/dist/pipeline/steps/visibility-gates.d.ts +8 -0
  418. package/dist/pipeline/steps/visibility-gates.d.ts.map +1 -1
  419. package/dist/pipeline/steps/visibility-gates.js +7 -2
  420. package/dist/pipeline/steps/visibility-gates.js.map +1 -1
  421. package/dist/query/search/registry.d.ts.map +1 -1
  422. package/dist/query/search/registry.js +2 -0
  423. package/dist/query/search/registry.js.map +1 -1
  424. package/dist/runnerauth/bound-execution.d.ts +27 -0
  425. package/dist/runnerauth/bound-execution.d.ts.map +1 -0
  426. package/dist/runnerauth/bound-execution.js +137 -0
  427. package/dist/runnerauth/bound-execution.js.map +1 -0
  428. package/dist/runnerauth/built-in-runner-credential-provider.d.ts +28 -0
  429. package/dist/runnerauth/built-in-runner-credential-provider.d.ts.map +1 -0
  430. package/dist/runnerauth/built-in-runner-credential-provider.js +217 -0
  431. package/dist/runnerauth/built-in-runner-credential-provider.js.map +1 -0
  432. package/dist/runnerauth/constants.d.ts +63 -0
  433. package/dist/runnerauth/constants.d.ts.map +1 -0
  434. package/dist/runnerauth/constants.js +63 -0
  435. package/dist/runnerauth/constants.js.map +1 -0
  436. package/dist/runnerauth/dispatch-credential.d.ts +38 -0
  437. package/dist/runnerauth/dispatch-credential.d.ts.map +1 -0
  438. package/dist/runnerauth/dispatch-credential.js +17 -0
  439. package/dist/runnerauth/dispatch-credential.js.map +1 -0
  440. package/dist/runnerauth/runner-credential-provider.d.ts +49 -11
  441. package/dist/runnerauth/runner-credential-provider.d.ts.map +1 -1
  442. package/dist/runnerauth/runner-credential-provider.js +16 -4
  443. package/dist/runnerauth/runner-credential-provider.js.map +1 -1
  444. package/dist/runnerauth/runner-subject-verifier.d.ts +14 -0
  445. package/dist/runnerauth/runner-subject-verifier.d.ts.map +1 -0
  446. package/dist/runnerauth/runner-subject-verifier.js +115 -0
  447. package/dist/runnerauth/runner-subject-verifier.js.map +1 -0
  448. package/dist/runnerauth/runnerauth.d.ts +33 -4
  449. package/dist/runnerauth/runnerauth.d.ts.map +1 -1
  450. package/dist/runnerauth/runnerauth.js +131 -35
  451. package/dist/runnerauth/runnerauth.js.map +1 -1
  452. package/dist/temporal/agentexecution/engine-client.d.ts +13 -0
  453. package/dist/temporal/agentexecution/engine-client.d.ts.map +1 -1
  454. package/dist/temporal/agentexecution/engine-client.js +10 -2
  455. package/dist/temporal/agentexecution/engine-client.js.map +1 -1
  456. package/dist/temporal/agentexecution/workflow-input.d.ts +13 -0
  457. package/dist/temporal/agentexecution/workflow-input.d.ts.map +1 -1
  458. package/dist/temporal/agentexecution/workflows/invoke-agent-execution.d.ts.map +1 -1
  459. package/dist/temporal/agentexecution/workflows/invoke-agent-execution.js +35 -31
  460. package/dist/temporal/agentexecution/workflows/invoke-agent-execution.js.map +1 -1
  461. package/dist/temporal/schedule/run-starter.d.ts +1 -1
  462. package/dist/temporal/schedule/run-starter.d.ts.map +1 -1
  463. package/dist/temporal/schedule/run-starter.js +14 -1
  464. package/dist/temporal/schedule/run-starter.js.map +1 -1
  465. package/dist/temporal/workflowexecution/engine-client.d.ts +24 -0
  466. package/dist/temporal/workflowexecution/engine-client.d.ts.map +1 -1
  467. package/dist/temporal/workflowexecution/engine-client.js +26 -19
  468. package/dist/temporal/workflowexecution/engine-client.js.map +1 -1
  469. package/dist/temporal/workflowexecution/workflow-input.d.ts +14 -0
  470. package/dist/temporal/workflowexecution/workflow-input.d.ts.map +1 -1
  471. package/package.json +5 -4
  472. package/src/archive/__tests__/archive.test.ts +233 -0
  473. package/src/{domain/skill → archive}/__tests__/prefilter.test.ts +1 -1
  474. package/src/archive/content-store.ts +132 -0
  475. package/src/archive/inflate.ts +107 -0
  476. package/src/archive/limits.ts +42 -0
  477. package/src/archive/open.ts +131 -0
  478. package/src/{domain/skill/storage → archive}/prefilter.ts +5 -0
  479. package/src/archive/write.ts +54 -0
  480. package/src/authorization/README.md +124 -0
  481. package/src/authorization/__tests__/authorizer.test.ts +719 -0
  482. package/src/authorization/__tests__/derived-tuples.test.ts +802 -0
  483. package/src/authorization/__tests__/drivers.ts +70 -0
  484. package/src/authorization/__tests__/evaluator.test.ts +359 -0
  485. package/src/authorization/__tests__/facts.test.ts +155 -0
  486. package/src/authorization/__tests__/fixtures/fga/agent-channel-owner.fga.yaml +112 -0
  487. package/src/authorization/__tests__/fixtures/fga/agent-share-owner.fga.yaml +109 -0
  488. package/src/authorization/__tests__/fixtures/fga/artifact-org-and-owner.fga.yaml +128 -0
  489. package/src/authorization/__tests__/fixtures/fga/blueprint-private-visibility.fga.yaml +410 -0
  490. package/src/authorization/__tests__/fixtures/fga/channel-app-owner.fga.yaml +125 -0
  491. package/src/authorization/__tests__/fixtures/fga/channel-participation.fga.yaml +201 -0
  492. package/src/authorization/__tests__/fixtures/fga/channel-session-visibility.fga.yaml +187 -0
  493. package/src/authorization/__tests__/fixtures/fga/cross-org-share-creation.fga.yaml +98 -0
  494. package/src/authorization/__tests__/fixtures/fga/default-instance-inheritance.fga.yaml +271 -0
  495. package/src/authorization/__tests__/fixtures/fga/memory-subject-only.fga.yaml +72 -0
  496. package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +328 -0
  497. package/src/authorization/__tests__/fixtures/fga/org-shared-environment.fga.yaml +144 -0
  498. package/src/authorization/__tests__/fixtures/fga/platform-visibility.fga.yaml +223 -0
  499. package/src/authorization/__tests__/fixtures/fga/provider-standing-viewer.fga.yaml +40 -0
  500. package/src/authorization/__tests__/fixtures/fga/public-visibility-setter.fga.yaml +52 -0
  501. package/src/authorization/__tests__/fixtures/fga/reserved-label-writer.fga.yaml +41 -0
  502. package/src/authorization/__tests__/fixtures/fga/schedule-owner.fga.yaml +113 -0
  503. package/src/authorization/__tests__/fixtures/fga/schedule-session-visibility.fga.yaml +214 -0
  504. package/src/authorization/__tests__/fixtures/fga/session-personal-resource.fga.yaml +117 -0
  505. package/src/authorization/__tests__/fixtures/fga/workflow-execution-sharing.fga.yaml +192 -0
  506. package/src/authorization/__tests__/lane-admission.test.ts +115 -0
  507. package/src/authorization/__tests__/list-read-scope.measure.test.ts +317 -0
  508. package/src/authorization/__tests__/list-read-scope.test.ts +796 -0
  509. package/src/authorization/__tests__/organization-directory.test.ts +236 -0
  510. package/src/authorization/__tests__/person.test.ts +114 -0
  511. package/src/authorization/__tests__/posture.test.ts +25 -0
  512. package/src/authorization/__tests__/schedule-fire-caller.test.ts +134 -0
  513. package/src/authorization/__tests__/store-tests.test.ts +306 -0
  514. package/src/authorization/__tests__/support.ts +101 -0
  515. package/src/authorization/__tests__/tuples.test.ts +62 -0
  516. package/src/authorization/__tests__/wire-permissions.test.ts +154 -0
  517. package/src/authorization/authorizer.ts +208 -0
  518. package/src/authorization/derived-tuples.ts +384 -0
  519. package/src/authorization/evaluator.ts +283 -0
  520. package/src/authorization/facts.ts +47 -0
  521. package/src/authorization/lane-admission.ts +73 -0
  522. package/src/authorization/list-read-scope.ts +216 -0
  523. package/src/authorization/model/__tests__/registry.test.ts +317 -0
  524. package/src/authorization/model/agent.ts +64 -0
  525. package/src/authorization/model/agent_channel.ts +49 -0
  526. package/src/authorization/model/agent_execution.ts +33 -0
  527. package/src/authorization/model/agent_instance.ts +66 -0
  528. package/src/authorization/model/agent_share.ts +40 -0
  529. package/src/authorization/model/api_key.ts +28 -0
  530. package/src/authorization/model/artifact.ts +38 -0
  531. package/src/authorization/model/channel_app.ts +39 -0
  532. package/src/authorization/model/default-of.ts +99 -0
  533. package/src/authorization/model/environment.ts +48 -0
  534. package/src/authorization/model/execution_context.ts +20 -0
  535. package/src/authorization/model/iam_policy.ts +42 -0
  536. package/src/authorization/model/identity_account.ts +26 -0
  537. package/src/authorization/model/index.ts +108 -0
  538. package/src/authorization/model/mcp_server.ts +59 -0
  539. package/src/authorization/model/memory.ts +27 -0
  540. package/src/authorization/model/oauth_app.ts +42 -0
  541. package/src/authorization/model/organization.ts +55 -0
  542. package/src/authorization/model/plugin.ts +66 -0
  543. package/src/authorization/model/project.ts +47 -0
  544. package/src/authorization/model/rewrite.ts +213 -0
  545. package/src/authorization/model/schedule.ts +40 -0
  546. package/src/authorization/model/session.ts +50 -0
  547. package/src/authorization/model/skill.ts +60 -0
  548. package/src/authorization/model/workflow.ts +60 -0
  549. package/src/authorization/model/workflow_execution.ts +44 -0
  550. package/src/authorization/model/workflow_instance.ts +122 -0
  551. package/src/authorization/organization-directory.ts +114 -0
  552. package/src/authorization/person.ts +68 -0
  553. package/src/authorization/posture.ts +49 -0
  554. package/src/authorization/schedule-fire-caller.ts +87 -0
  555. package/src/authorization/store-test-kit.ts +454 -0
  556. package/src/authorization/tuples.ts +190 -0
  557. package/src/boot/compose.ts +246 -52
  558. package/src/boot/inprocess.ts +115 -31
  559. package/src/domain/agent/controller.ts +11 -0
  560. package/src/domain/executioncontext/__tests__/executioncontext.test.ts +104 -0
  561. package/src/domain/executioncontext/__tests__/resolve-values-capability.test.ts +33 -4
  562. package/src/domain/executioncontext/resolve-values-for-caller.ts +79 -22
  563. package/src/domain/iampolicy/__tests__/membership.test.ts +357 -3
  564. package/src/domain/iampolicy/constants.ts +12 -0
  565. package/src/domain/iampolicy/membership.ts +221 -66
  566. package/src/domain/identityaccount/__tests__/account-for-stamp.test.ts +111 -0
  567. package/src/domain/identityaccount/actor.ts +84 -0
  568. package/src/domain/identityaccount/resolve.ts +31 -0
  569. package/src/domain/mcpserver/__tests__/connect.test.ts +17 -2
  570. package/src/domain/mcpserver/connect-execution-id.ts +34 -0
  571. package/src/domain/mcpserver/connect.ts +38 -3
  572. package/src/domain/mcpserver/controller.ts +11 -0
  573. package/src/domain/mcpserver/engine.ts +9 -3
  574. package/src/domain/mcpserver/start-connect.ts +1 -1
  575. package/src/domain/platform/controller.ts +24 -11
  576. package/src/domain/plugin/__tests__/materialize.test.ts +303 -0
  577. package/src/domain/plugin/__tests__/overlay-parse.test.ts +85 -0
  578. package/src/domain/plugin/__tests__/plugin.test.ts +796 -0
  579. package/src/domain/plugin/__tests__/sanitize.test.ts +174 -0
  580. package/src/domain/plugin/archive.ts +89 -0
  581. package/src/domain/plugin/constants.ts +53 -0
  582. package/src/domain/plugin/controller.ts +913 -0
  583. package/src/domain/plugin/materialize/agent.ts +186 -0
  584. package/src/domain/plugin/materialize/default-agent-instructions.ts +59 -0
  585. package/src/domain/plugin/materialize/identity.ts +67 -0
  586. package/src/domain/plugin/materialize/mcp-servers.ts +175 -0
  587. package/src/domain/plugin/materialize/plan.ts +124 -0
  588. package/src/domain/plugin/materialize/ports.ts +53 -0
  589. package/src/domain/plugin/materialize/skills.ts +68 -0
  590. package/src/domain/plugin/materialize/workflows.ts +51 -0
  591. package/src/domain/plugin/members.ts +180 -0
  592. package/src/domain/plugin/overlay/documents.ts +78 -0
  593. package/src/domain/plugin/overlay/parse.ts +115 -0
  594. package/src/domain/plugin/overlay/sanitize.ts +151 -0
  595. package/src/domain/plugin/push.ts +1062 -0
  596. package/src/domain/plugin/search-extractor.ts +60 -0
  597. package/src/domain/skill/constants.ts +11 -14
  598. package/src/domain/skill/controller.ts +44 -36
  599. package/src/domain/skill/push.ts +61 -156
  600. package/src/domain/skill/search-extractor.ts +3 -1
  601. package/src/domain/skill/storage/artifact-storage.ts +23 -124
  602. package/src/domain/skill/storage/zip-gate.ts +58 -154
  603. package/src/domain/skill/version-resolution.ts +67 -269
  604. package/src/domain/workflow/controller.ts +38 -4
  605. package/src/domain/workflow/registry/data/task-kind-registry.json +1 -0
  606. package/src/domain/workflowexecution/__tests__/phases.test.ts +58 -0
  607. package/src/domain/workflowexecution/phases.ts +33 -0
  608. package/src/extensions/__tests__/built-in-authorization-composed.test.ts +835 -0
  609. package/src/extensions/__tests__/composed-support.ts +32 -1
  610. package/src/extensions/__tests__/extension-composition.test.ts +42 -1
  611. package/src/extensions/__tests__/list-read-scope.test.ts +137 -33
  612. package/src/extensions/__tests__/role-reconciliation-composed.test.ts +209 -0
  613. package/src/extensions/__tests__/tier-truthfulness.test.ts +6 -14
  614. package/src/extensions/authorizer.ts +10 -5
  615. package/src/extensions/drivers.ts +4 -1
  616. package/src/extensions/list-read-scope.ts +67 -45
  617. package/src/extensions/organization-directory.ts +13 -9
  618. package/src/extensions/resource-authorization.ts +34 -0
  619. package/src/extensions/schedule-fire-caller.ts +49 -18
  620. package/src/identity/__tests__/oidc-verifier.test.ts +22 -0
  621. package/src/identity/oidc-verifier.ts +8 -1
  622. package/src/index.ts +51 -1
  623. package/src/pipeline/__tests__/kind-by-id-prefix.test.ts +75 -0
  624. package/src/pipeline/__tests__/router-transport.test.ts +1 -3
  625. package/src/pipeline/apiresource-labels.ts +31 -3
  626. package/src/pipeline/apiresource-meta.ts +41 -0
  627. package/src/pipeline/errors.ts +5 -5
  628. package/src/pipeline/steps/__tests__/authorize-annotation-completeness.test.ts +1 -20
  629. package/src/pipeline/steps/__tests__/guard-memory-capture.test.ts +58 -44
  630. package/src/pipeline/steps/__tests__/guard-plugin-managed.test.ts +151 -0
  631. package/src/pipeline/steps/__tests__/guard-reserved-labels.test.ts +83 -8
  632. package/src/pipeline/steps/authorization-facts.ts +131 -0
  633. package/src/pipeline/steps/delete.ts +11 -3
  634. package/src/pipeline/steps/duplicate.ts +8 -2
  635. package/src/pipeline/steps/guard-memory-capture.ts +5 -3
  636. package/src/pipeline/steps/guard-plugin-managed.ts +133 -0
  637. package/src/pipeline/steps/guard-reserved-labels.ts +29 -8
  638. package/src/pipeline/steps/helpers.ts +4 -1
  639. package/src/pipeline/steps/index-search.ts +28 -15
  640. package/src/pipeline/steps/load-existing.ts +12 -3
  641. package/src/pipeline/steps/references.ts +36 -2
  642. package/src/pipeline/steps/resolve-artifact-source.ts +66 -0
  643. package/src/pipeline/steps/server-stamped-reserved-labels.ts +2 -1
  644. package/src/pipeline/steps/slug.ts +7 -2
  645. package/src/pipeline/steps/validate-visibility.ts +9 -2
  646. package/src/pipeline/steps/validation.ts +3 -1
  647. package/src/pipeline/steps/version-archive.ts +225 -0
  648. package/src/pipeline/steps/version-history.ts +362 -0
  649. package/src/pipeline/steps/visibility-gates.ts +12 -9
  650. package/src/query/README.md +1 -1
  651. package/src/query/search/__tests__/criteria.test.ts +6 -7
  652. package/src/query/search/__tests__/query-store.test.ts +9 -2
  653. package/src/query/search/__tests__/registry.test.ts +6 -4
  654. package/src/query/search/registry.ts +6 -1
  655. package/src/runnerauth/__tests__/bound-execution.test.ts +334 -0
  656. package/src/runnerauth/__tests__/built-in-runner-credential-provider.test.ts +516 -0
  657. package/src/runnerauth/__tests__/dispatch-credential.test.ts +94 -0
  658. package/src/runnerauth/__tests__/runner-credential-provider.test.ts +27 -0
  659. package/src/runnerauth/__tests__/runner-subject-composed.test.ts +497 -0
  660. package/src/runnerauth/__tests__/runner-subject-verifier.test.ts +541 -0
  661. package/src/runnerauth/bound-execution.ts +270 -0
  662. package/src/runnerauth/built-in-runner-credential-provider.ts +300 -0
  663. package/src/runnerauth/constants.ts +74 -0
  664. package/src/runnerauth/dispatch-credential.ts +63 -0
  665. package/src/runnerauth/runner-credential-provider.ts +60 -11
  666. package/src/runnerauth/runner-subject-verifier.ts +152 -0
  667. package/src/runnerauth/runnerauth.ts +148 -38
  668. package/src/temporal/agentexecution/__tests__/engine-client.test.ts +107 -38
  669. package/src/temporal/agentexecution/__tests__/invoke-workflow.test.ts +105 -2
  670. package/src/temporal/agentexecution/engine-client.ts +27 -2
  671. package/src/temporal/agentexecution/workflow-input.ts +13 -0
  672. package/src/temporal/agentexecution/workflows/invoke-agent-execution.ts +90 -44
  673. package/src/temporal/schedule/__tests__/run-starter.test.ts +86 -24
  674. package/src/temporal/schedule/run-starter.ts +31 -8
  675. package/src/temporal/workflowexecution/__tests__/engine-client.test.ts +139 -33
  676. package/src/temporal/workflowexecution/engine-client.ts +48 -21
  677. package/src/temporal/workflowexecution/workflow-input.ts +14 -0
  678. package/dist/domain/skill/storage/prefilter.d.ts.map +0 -1
  679. package/dist/domain/skill/storage/prefilter.js.map +0 -1
  680. /package/dist/{domain/skill/storage → archive}/prefilter.js +0 -0
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Pins the shared archive plumbing on its own, apart from the skill gate
3
+ * that composes it: the structural walk's sentences and their order, the
4
+ * capped inflate's typed outcomes, the writer's determinism (the same
5
+ * files twice are byte-equal, entry order is irrelevant, the result reads
6
+ * back through the server's own reader), and the content-addressed
7
+ * store's key shape and traversal collapse under a second prefix. The
8
+ * skill gate's zip-gate.test.ts proves the composition keeps its pinned
9
+ * copy; this file proves the pieces a plugin builds on.
10
+ */
11
+ import { mkdtempSync, rmSync } from "node:fs";
12
+ import { tmpdir } from "node:os";
13
+ import path from "node:path";
14
+
15
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
16
+
17
+ import { parseZipStructure } from "@stigmer/zip-structure";
18
+ import { buildZip } from "@stigmer/zip-structure/testing";
19
+
20
+ import { LocalArtifactStorage } from "../../artifactstorage/artifact-storage.js";
21
+ import {
22
+ ArtifactNotFoundError,
23
+ newContentAddressedArchiveStore,
24
+ } from "../content-store.js";
25
+ import { InflateError, inflateEntry } from "../inflate.js";
26
+ import { PLATFORM_ARCHIVE_LIMITS } from "../limits.js";
27
+ import {
28
+ calculateHash,
29
+ openArchive,
30
+ validateArchiveStructure,
31
+ } from "../open.js";
32
+ import { writeArchive } from "../write.js";
33
+
34
+ const encoder = new TextEncoder();
35
+
36
+ describe("openArchive", () => {
37
+ it("hashes the bytes and pre-filters the entries", () => {
38
+ const zip = buildZip([{ name: "./a/../plugin.json", content: "{}" }]);
39
+ const opened = openArchive(zip);
40
+ expect(opened.hash).toBe(calculateHash(zip));
41
+ expect(opened.entries.map((e) => e.name)).toEqual(["plugin.json"]);
42
+ });
43
+
44
+ it("refuses an over-limit archive before parsing, naming the limit", () => {
45
+ expect(() => openArchive(new Uint8Array(11), 10)).toThrow(
46
+ "ZIP file too large: 11 bytes (max: 10)",
47
+ );
48
+ });
49
+
50
+ it("refuses bytes that are not a zip with the stdlib text", () => {
51
+ expect(() => openArchive(encoder.encode("not a zip"))).toThrow(
52
+ "invalid ZIP file: zip: not a valid zip file",
53
+ );
54
+ });
55
+ });
56
+
57
+ describe("validateArchiveStructure", () => {
58
+ it("refuses an empty archive first", () => {
59
+ expect(() => validateArchiveStructure([], PLATFORM_ARCHIVE_LIMITS)).toThrow(
60
+ "ZIP file is empty",
61
+ );
62
+ });
63
+
64
+ it("refuses too many files, then a control character, then the budget", () => {
65
+ const one = openArchive(buildZip([{ name: "a", content: "x" }])).entries;
66
+ expect(() =>
67
+ validateArchiveStructure(one, {
68
+ ...PLATFORM_ARCHIVE_LIMITS,
69
+ maxFiles: 0,
70
+ }),
71
+ ).toThrow("too many files in ZIP: 1 (max: 0)");
72
+
73
+ const control = openArchive(
74
+ buildZip([{ name: "bad\u0001name", content: "x" }]),
75
+ ).entries;
76
+ expect(() =>
77
+ validateArchiveStructure(control, PLATFORM_ARCHIVE_LIMITS),
78
+ ).toThrow("invalid character in filename: bad\u0001name");
79
+
80
+ const big = openArchive(
81
+ buildZip([{ name: "a", content: "x".repeat(64) }]),
82
+ ).entries;
83
+ expect(() =>
84
+ validateArchiveStructure(big, {
85
+ ...PLATFORM_ARCHIVE_LIMITS,
86
+ maxUncompressedSize: 10,
87
+ }),
88
+ ).toThrow("total uncompressed size too large: 64 bytes (max: 10)");
89
+ });
90
+
91
+ it("hands every sanitised name to the observer in order", () => {
92
+ const entries = openArchive(
93
+ buildZip([
94
+ { name: "skills/x/SKILL.md", content: "---\nname: x\n---" },
95
+ { name: "plugin.json", content: "{}" },
96
+ ]),
97
+ ).entries;
98
+ const seen: string[] = [];
99
+ validateArchiveStructure(entries, PLATFORM_ARCHIVE_LIMITS, (name) =>
100
+ seen.push(name),
101
+ );
102
+ expect(seen).toEqual(["skills/x/SKILL.md", "plugin.json"]);
103
+ });
104
+ });
105
+
106
+ describe("inflateEntry", () => {
107
+ it("returns stored and deflated payloads under the cap", () => {
108
+ const zip = buildZip([
109
+ { name: "s", content: "stored" },
110
+ { name: "d", content: "deflated".repeat(20), method: "deflated" },
111
+ ]);
112
+ const [stored, deflated] = parseZipStructure(zip);
113
+ expect(new TextDecoder().decode(inflateEntry(stored!, 1024))).toBe(
114
+ "stored",
115
+ );
116
+ expect(new TextDecoder().decode(inflateEntry(deflated!, 1024))).toBe(
117
+ "deflated".repeat(20),
118
+ );
119
+ });
120
+
121
+ it("refuses output past the cap as too-large, judged on the real bytes", () => {
122
+ const zip = buildZip([
123
+ { name: "d", content: "a".repeat(4096), method: "deflated" },
124
+ ]);
125
+ const [entry] = parseZipStructure(zip);
126
+ let failure: InflateError | undefined;
127
+ try {
128
+ inflateEntry(entry!, 100);
129
+ } catch (error) {
130
+ failure = error instanceof InflateError ? error : undefined;
131
+ }
132
+ expect(failure?.kind).toBe("too-large");
133
+ });
134
+
135
+ it("refuses a corrupt payload as a checksum failure", () => {
136
+ const zip = buildZip([{ name: "s", content: "hello" }]);
137
+ const [entry] = parseZipStructure(zip);
138
+ const corrupted = { ...entry!, compressedData: encoder.encode("jello") };
139
+ let failure: InflateError | undefined;
140
+ try {
141
+ inflateEntry(corrupted, 1024);
142
+ } catch (error) {
143
+ failure = error instanceof InflateError ? error : undefined;
144
+ }
145
+ expect(failure?.kind).toBe("checksum");
146
+ expect(failure?.detail).toBe("zip: checksum error");
147
+ });
148
+
149
+ it("refuses a compression method the platform does not register", () => {
150
+ const zip = buildZip([{ name: "s", content: "hello" }]);
151
+ const [entry] = parseZipStructure(zip);
152
+ const bzip2 = { ...entry!, compressionMethod: 12 };
153
+ expect(() => inflateEntry(bzip2, 1024)).toThrow(
154
+ "unsupported-method: zip: unsupported compression algorithm",
155
+ );
156
+ });
157
+ });
158
+
159
+ describe("writeArchive", () => {
160
+ const files = [
161
+ {
162
+ path: "skills/x/SKILL.md",
163
+ bytes: encoder.encode("---\nname: x\n---\nbody"),
164
+ },
165
+ { path: "plugin.json", bytes: encoder.encode('{"name":"x"}') },
166
+ ];
167
+
168
+ it("is byte-deterministic and independent of entry order", () => {
169
+ const first = writeArchive(files);
170
+ const second = writeArchive([...files].reverse());
171
+ expect(Buffer.from(first).equals(Buffer.from(second))).toBe(true);
172
+ expect(calculateHash(first)).toBe(calculateHash(second));
173
+ });
174
+
175
+ it("round-trips through the server's own reader", () => {
176
+ const opened = openArchive(writeArchive(files));
177
+ expect(opened.entries.map((e) => e.name)).toEqual([
178
+ "plugin.json",
179
+ "skills/x/SKILL.md",
180
+ ]);
181
+ const skill = opened.entries.find((e) => e.name === "skills/x/SKILL.md")!;
182
+ expect(new TextDecoder().decode(inflateEntry(skill.entry, 1024))).toBe(
183
+ "---\nname: x\n---\nbody",
184
+ );
185
+ });
186
+
187
+ it("refuses a path listed twice", () => {
188
+ expect(() => writeArchive([files[0]!, files[0]!])).toThrow(
189
+ "archive path 'skills/x/SKILL.md' listed twice",
190
+ );
191
+ });
192
+ });
193
+
194
+ describe("newContentAddressedArchiveStore", () => {
195
+ let dir: string;
196
+ beforeEach(() => {
197
+ dir = mkdtempSync(path.join(tmpdir(), "archive-store-test-"));
198
+ });
199
+ afterEach(() => {
200
+ rmSync(dir, { recursive: true, force: true });
201
+ });
202
+
203
+ it("keys under its prefix and round-trips bytes", async () => {
204
+ const store = newContentAddressedArchiveStore(
205
+ new LocalArtifactStorage(dir, ""),
206
+ "plugins/",
207
+ );
208
+ const hash = "a".repeat(64);
209
+ expect(store.getStorageKey(hash)).toBe(`plugins/${hash}.zip`);
210
+ expect(await store.exists(hash)).toBe(false);
211
+ const key = await store.store(hash, encoder.encode("zip"));
212
+ expect(key).toBe(`plugins/${hash}.zip`);
213
+ expect(await store.exists(hash)).toBe(true);
214
+ expect(new TextDecoder().decode(await store.get(key))).toBe("zip");
215
+ expect(await store.size(key)).toBe(3);
216
+ });
217
+
218
+ it("collapses a traversal-shaped key and a missing key to one not-found", async () => {
219
+ const store = newContentAddressedArchiveStore(
220
+ new LocalArtifactStorage(dir, ""),
221
+ "plugins/",
222
+ );
223
+ await expect(store.get("../../etc/passwd")).rejects.toBeInstanceOf(
224
+ ArtifactNotFoundError,
225
+ );
226
+ await expect(store.get("plugins/missing.zip")).rejects.toBeInstanceOf(
227
+ ArtifactNotFoundError,
228
+ );
229
+ await expect(store.size("../x")).rejects.toThrow(
230
+ "artifact not found: ../x",
231
+ );
232
+ });
233
+ });
@@ -15,7 +15,7 @@ import {
15
15
  entryTypeBits,
16
16
  hasWindowsShortFilenames,
17
17
  sanitizePath,
18
- } from "../storage/prefilter.js";
18
+ } from "../prefilter.js";
19
19
 
20
20
  // versionMadeBy high byte 3 = Unix creator; POSIX mode rides the attribute
21
21
  // high 16 bits (how zip writers encode symlinks and special files).
@@ -0,0 +1,132 @@
1
+ /**
2
+ * The content-addressed archive store — a domain port over the one
3
+ * ArtifactStorage blob driver: keys are `<prefix><sha256>.zip`, writes are
4
+ * once and never garbage-collected (historical versions stay downloadable
5
+ * through the keys a version history exposes), and a key that addresses
6
+ * nothing inside the store collapses to one not-found before the driver
7
+ * sees it. Skills shipped this shape first
8
+ * (pkg/domain/skill/storage/artifact_storage.go, then the TS port under
9
+ * domain/skill/storage); plugins need the identical port under another
10
+ * prefix, so the implementation lives here and each domain names its
11
+ * instance (`skills/`, `plugins/`).
12
+ *
13
+ * Why the traversal guard is the port's, not the driver's: a
14
+ * client-supplied storage key that resolves outside the store must read
15
+ * exactly like a missing file — the driver's own containment refusal is a
16
+ * distinguishable error, and distinguishing them would tell a probing
17
+ * caller which escapes exist. Lexical, against a fixed virtual root, so
18
+ * the judgment is identical on every backend.
19
+ *
20
+ * Key shape: a LITERAL forward-slash join, never path.join — the key is a
21
+ * wire-visible identifier (status.artifact_storage_key, download URLs, the
22
+ * lane's prefix check) and Windows support arrives only through this server
23
+ * (#24); path.join would mint backslash keys there.
24
+ *
25
+ * Proven by the skill store's __tests__/artifact-storage.test.ts (the
26
+ * `skills/` instance) and by __tests__/content-store.test.ts.
27
+ */
28
+ import path from "node:path";
29
+
30
+ import type { ArtifactStorage } from "../artifactstorage/artifact-storage.js";
31
+ import { ArtifactStorageNotFoundError } from "../artifactstorage/artifact-storage.js";
32
+
33
+ /**
34
+ * Storage abstraction for content-addressed archives. The interface exists
35
+ * for the same reason Go's did: the cloud edition uses R2 behind the
36
+ * identical surface, and a controller must not know which one it holds.
37
+ */
38
+ export interface ContentAddressedArchiveStore {
39
+ /** Saves an archive under its content hash; returns the storage key. */
40
+ store(hash: string, data: Uint8Array): Promise<string>;
41
+ /** Loads an archive by storage key; throws ArtifactNotFoundError if absent. */
42
+ get(storageKey: string): Promise<Uint8Array>;
43
+ /** Whether an archive with this content hash already exists (dedupe). */
44
+ exists(hash: string): Promise<boolean>;
45
+ /** The storage key for a hash, without storing ("<prefix><hash>.zip"). */
46
+ getStorageKey(hash: string): string;
47
+ /** The stored archive's byte size via stat — never loads content. */
48
+ size(storageKey: string): Promise<number>;
49
+ }
50
+
51
+ /**
52
+ * A storage key that addresses nothing inside the store — missing file OR
53
+ * a traversal-shaped key (both render as Go's "artifact not found: %s").
54
+ */
55
+ export class ArtifactNotFoundError extends Error {
56
+ constructor(storageKey: string) {
57
+ super(`artifact not found: ${storageKey}`);
58
+ this.name = "ArtifactNotFoundError";
59
+ }
60
+ }
61
+
62
+ /** Archives are zip files; the driver stores the honest type. */
63
+ const ARCHIVE_CONTENT_TYPE = "application/zip";
64
+
65
+ /**
66
+ * The store over a blob driver. Object-literal factory rather than a class:
67
+ * all state is the captured driver and prefix, and the seam-adapter shape
68
+ * matches runner-credential-provider.ts (the house style for ports).
69
+ *
70
+ * `keyPrefix` ends with a slash (`skills/`); it is also the download lane's
71
+ * containment prefix, so the two agree by construction.
72
+ */
73
+ export function newContentAddressedArchiveStore(
74
+ driver: ArtifactStorage,
75
+ keyPrefix: string,
76
+ ): ContentAddressedArchiveStore {
77
+ const virtualRoot = path.resolve(path.sep, "archive-store");
78
+ const keyEscapesStore = (storageKey: string): boolean => {
79
+ const resolved = path.resolve(virtualRoot, storageKey);
80
+ return (
81
+ resolved !== virtualRoot && !resolved.startsWith(virtualRoot + path.sep)
82
+ );
83
+ };
84
+
85
+ return {
86
+ getStorageKey(hash: string): string {
87
+ return `${keyPrefix}${hash}.zip`;
88
+ },
89
+
90
+ async store(hash: string, data: Uint8Array): Promise<string> {
91
+ const storageKey = this.getStorageKey(hash);
92
+ await driver.upload(storageKey, data, ARCHIVE_CONTENT_TYPE);
93
+ return storageKey;
94
+ },
95
+
96
+ async get(storageKey: string): Promise<Uint8Array> {
97
+ if (keyEscapesStore(storageKey)) {
98
+ throw new ArtifactNotFoundError(storageKey);
99
+ }
100
+ try {
101
+ return await driver.download(storageKey);
102
+ } catch (error) {
103
+ if (error instanceof ArtifactStorageNotFoundError) {
104
+ throw new ArtifactNotFoundError(storageKey);
105
+ }
106
+ throw new Error(
107
+ `failed to read artifact: ${error instanceof Error ? error.message : String(error)}`,
108
+ );
109
+ }
110
+ },
111
+
112
+ async exists(hash: string): Promise<boolean> {
113
+ return driver.exists(this.getStorageKey(hash));
114
+ },
115
+
116
+ async size(storageKey: string): Promise<number> {
117
+ if (keyEscapesStore(storageKey)) {
118
+ throw new ArtifactNotFoundError(storageKey);
119
+ }
120
+ try {
121
+ return await driver.size(storageKey);
122
+ } catch (error) {
123
+ if (error instanceof ArtifactStorageNotFoundError) {
124
+ throw new ArtifactNotFoundError(storageKey);
125
+ }
126
+ throw new Error(
127
+ `failed to stat artifact: ${error instanceof Error ? error.message : String(error)}`,
128
+ );
129
+ }
130
+ },
131
+ };
132
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Reading one archive entry under a real cap. Declared sizes are client
3
+ * claims, so every gate that opens an entry bounds the ACTUAL inflated
4
+ * output (`maxOutputLength`), verifies the CRC the way Go's checksumReader
5
+ * does on every read, and opens only the two methods the platform
6
+ * registers (stored, deflated). The skill gate did this for SKILL.md alone;
7
+ * a plugin reads many documents through the same discipline, so the read
8
+ * lives here and each kind keeps its own sentences: the outcome is a typed
9
+ * failure, never prose, because the skill's copy is byte-pinned wire
10
+ * contract and a plugin's names a different document.
11
+ *
12
+ * Proven by __tests__/inflate.test.ts and, through composition, by the
13
+ * skill gate's zip-gate.test.ts.
14
+ */
15
+ import { inflateRawSync } from "node:zlib";
16
+
17
+ import { crc32 } from "@stigmer/zip-structure";
18
+ import type { ZipStructuralEntry } from "@stigmer/zip-structure";
19
+
20
+ /** ZIP compression methods the gate can open (Go registers the same two). */
21
+ const METHOD_STORED = 0;
22
+ const METHOD_DEFLATED = 8;
23
+
24
+ export type InflateFailureKind =
25
+ /** The inflated output passed `maxSize`. */
26
+ | "too-large"
27
+ /** zlib refused the payload; `detail` carries its message. */
28
+ | "read-failed"
29
+ /** A compression method neither Go nor this gate registers. */
30
+ | "unsupported-method"
31
+ /** The inflated bytes do not match the entry's CRC. */
32
+ | "checksum";
33
+
34
+ /** A typed refusal; the kind that called maps it to its pinned sentence. */
35
+ export class InflateError extends Error {
36
+ constructor(
37
+ readonly kind: InflateFailureKind,
38
+ readonly detail: string,
39
+ ) {
40
+ super(`${kind}: ${detail}`);
41
+ this.name = "InflateError";
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Inflates one entry to at most `maxSize` bytes and verifies its CRC.
47
+ * The cap bounds the actual output, not the declaration.
48
+ */
49
+ export function inflateEntry(
50
+ entry: ZipStructuralEntry,
51
+ maxSize: number,
52
+ ): Uint8Array {
53
+ let content: Uint8Array;
54
+ switch (entry.compressionMethod) {
55
+ case METHOD_STORED:
56
+ content = entry.compressedData;
57
+ break;
58
+ case METHOD_DEFLATED:
59
+ try {
60
+ content = new Uint8Array(
61
+ inflateRawSync(entry.compressedData, {
62
+ maxOutputLength: maxSize + 1,
63
+ }),
64
+ );
65
+ } catch (error) {
66
+ if (isOutputLengthError(error)) {
67
+ throw new InflateError(
68
+ "too-large",
69
+ `output exceeds ${maxSize} bytes`,
70
+ );
71
+ }
72
+ throw new InflateError(
73
+ "read-failed",
74
+ error instanceof Error ? error.message : String(error),
75
+ );
76
+ }
77
+ break;
78
+ default:
79
+ // Go: File.Open returns ErrAlgorithm for methods without a registered
80
+ // decompressor; each kind pins the text via its own %w-shaped arm.
81
+ throw new InflateError(
82
+ "unsupported-method",
83
+ "zip: unsupported compression algorithm",
84
+ );
85
+ }
86
+
87
+ if (content.length > maxSize) {
88
+ throw new InflateError("too-large", `output exceeds ${maxSize} bytes`);
89
+ }
90
+
91
+ if (crc32(content) !== entry.crc32) {
92
+ // Go's checksumReader: stdlib ErrChecksum via the read-error arm.
93
+ throw new InflateError("checksum", "zip: checksum error");
94
+ }
95
+
96
+ return content;
97
+ }
98
+
99
+ /** node:zlib's maxOutputLength violation (the output-cap arm). */
100
+ function isOutputLengthError(error: unknown): boolean {
101
+ return (
102
+ error instanceof Error &&
103
+ (("code" in error &&
104
+ (error as { code?: string }).code === "ERR_BUFFER_TOO_LARGE") ||
105
+ error.message.includes("maxOutputLength"))
106
+ );
107
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The platform's archive limits — one home for every ZIP-bomb budget the
3
+ * server applies to a pushed archive, whichever kind it becomes. Skills
4
+ * carried these alone until plugins arrived (also pushed as a ZIP); the
5
+ * values stay byte-pinned to the retired Go gate's (pkg/domain/skill/storage/
6
+ * zip_extractor.go), because every sentence quoting them is wire contract
7
+ * and the transfer lane refuses over-limit declarations by them before a
8
+ * byte moves.
9
+ *
10
+ * A per-kind cap that is NOT an archive budget (the 1 MB SKILL.md
11
+ * extraction cap) stays with its kind: it bounds one document, not the
12
+ * archive.
13
+ */
14
+
15
+ /**
16
+ * The compressed-archive ceiling. The platform's artifact size limit, not
17
+ * just an extraction guard: createArtifactUploadUrl enforces it before any
18
+ * bytes move and clients quote it in fail-loud size errors (#675).
19
+ */
20
+ export const MAX_ZIP_SIZE = 100 * 1024 * 1024;
21
+
22
+ /** Total declared-uncompressed budget across all entries (ZIP-bomb guard). */
23
+ export const MAX_UNCOMPRESSED_SIZE = 500 * 1024 * 1024;
24
+
25
+ /** Per-file declared compression ratio ceiling (ZIP-bomb guard). */
26
+ export const MAX_COMPRESSION_RATIO = 100;
27
+
28
+ /** Entry-count ceiling. */
29
+ export const MAX_FILES = 10_000;
30
+
31
+ /** The budgets `validateArchiveStructure` applies; the platform's by default. */
32
+ export interface ArchiveLimits {
33
+ readonly maxFiles: number;
34
+ readonly maxUncompressedSize: number;
35
+ readonly maxCompressionRatio: number;
36
+ }
37
+
38
+ export const PLATFORM_ARCHIVE_LIMITS: ArchiveLimits = {
39
+ maxFiles: MAX_FILES,
40
+ maxUncompressedSize: MAX_UNCOMPRESSED_SIZE,
41
+ maxCompressionRatio: MAX_COMPRESSION_RATIO,
42
+ };
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Opening a pushed archive — the kind-agnostic half of the ZIP gate every
3
+ * archive-shaped push runs (skills, plugins). Two steps, both pure over the
4
+ * bytes: `openArchive` bounds the compressed size, hashes the bytes (the
5
+ * content-addressed version identity), parses the central directory and
6
+ * applies the safearchive prefilter; `validateArchiveStructure` walks the
7
+ * pre-filtered entries in the retired Go gate's exact order (empty
8
+ * archive, file count, then per entry the filename control-character rule,
9
+ * the running declared-uncompressed budget and the per-file ratio cap).
10
+ *
11
+ * What a KIND requires of the entries (a root SKILL.md, a plugin manifest)
12
+ * is not here: the walk accepts an `onEntry` observer so a kind tracks what
13
+ * it needs in the same pass and rules on it afterwards, which keeps the
14
+ * observable error order the skill gate's tests pin.
15
+ *
16
+ * Error text is wire-visible contract: the sentences below are the Go
17
+ * gate's verbatim, wrapped by each kind's push step into its own
18
+ * InvalidArgument arm. Only declared sizes are judged here; inflating an
19
+ * entry under a real cap is `inflate.ts`'s job.
20
+ *
21
+ * Proven by the skill gate's __tests__/zip-gate.test.ts (which composes
22
+ * these) and by __tests__/open.test.ts for the plugin-shaped path.
23
+ */
24
+ import { createHash } from "node:crypto";
25
+
26
+ import { parseZipStructure } from "@stigmer/zip-structure";
27
+ import type { ZipStructuralEntry } from "@stigmer/zip-structure";
28
+
29
+ import type { ArchiveLimits } from "./limits.js";
30
+ import { MAX_ZIP_SIZE } from "./limits.js";
31
+ import { applyEntryPrefilter } from "./prefilter.js";
32
+ import type { PrefilteredEntry } from "./prefilter.js";
33
+
34
+ /** A parsed, pre-filtered archive with its content-addressed identity. */
35
+ export interface OpenedArchive {
36
+ /** SHA-256 hex of the archive bytes. */
37
+ readonly hash: string;
38
+ /** The entries a kind may read, names sanitised, shadows dropped. */
39
+ readonly entries: readonly PrefilteredEntry[];
40
+ }
41
+
42
+ /**
43
+ * Bounds, hashes, parses and pre-filters. Throws plain Errors with
44
+ * byte-pinned messages; the caller owns the gRPC code.
45
+ */
46
+ export function openArchive(
47
+ bytes: Uint8Array,
48
+ maxZipSize: number = MAX_ZIP_SIZE,
49
+ ): OpenedArchive {
50
+ if (bytes.length > maxZipSize) {
51
+ throw new Error(
52
+ `ZIP file too large: ${bytes.length} bytes (max: ${maxZipSize})`,
53
+ );
54
+ }
55
+
56
+ const hash = calculateHash(bytes);
57
+
58
+ let entries: readonly ZipStructuralEntry[];
59
+ try {
60
+ entries = parseZipStructure(bytes);
61
+ } catch {
62
+ // Go's zip.NewReader surfaces stdlib ErrFormat here; its text is what
63
+ // clients see via the %w chain, so it is pinned verbatim.
64
+ throw new Error("invalid ZIP file: zip: not a valid zip file");
65
+ }
66
+
67
+ // safearchive MaximumSecurityMode rewrites the entry list before any
68
+ // validation sees it — sanitized names, shadowed/special/8.3 entries
69
+ // dropped.
70
+ return { hash, entries: applyEntryPrefilter(entries) };
71
+ }
72
+
73
+ /**
74
+ * The structural walk: empty archive, file-count cap, then per entry the
75
+ * control-character rule, the running declared-uncompressed budget
76
+ * (fail-fast) and the per-file compression-ratio cap. `onEntry` sees each
77
+ * sanitised name in order so a kind can track its own requirements.
78
+ */
79
+ export function validateArchiveStructure(
80
+ entries: readonly PrefilteredEntry[],
81
+ limits: ArchiveLimits,
82
+ onEntry?: (name: string) => void,
83
+ ): void {
84
+ if (entries.length === 0) {
85
+ throw new Error("ZIP file is empty");
86
+ }
87
+
88
+ if (entries.length > limits.maxFiles) {
89
+ throw new Error(
90
+ `too many files in ZIP: ${entries.length} (max: ${limits.maxFiles})`,
91
+ );
92
+ }
93
+
94
+ let totalUncompressedSize = 0;
95
+
96
+ for (const { name, entry } of entries) {
97
+ onEntry?.(name);
98
+
99
+ // Reject null bytes and control characters in entry names (code
100
+ // points, not UTF-16 units — Go ranges over runes).
101
+ for (const ch of name) {
102
+ const codePoint = ch.codePointAt(0)!;
103
+ if (codePoint < 32 || codePoint === 127) {
104
+ throw new Error(`invalid character in filename: ${name}`);
105
+ }
106
+ }
107
+
108
+ // Track the declared uncompressed total (fail fast once exceeded).
109
+ totalUncompressedSize += entry.uncompressedSize;
110
+ if (totalUncompressedSize > limits.maxUncompressedSize) {
111
+ throw new Error(
112
+ `total uncompressed size too large: ${totalUncompressedSize} bytes (max: ${limits.maxUncompressedSize})`,
113
+ );
114
+ }
115
+
116
+ // Per-file compression ratio (ZIP-bomb guard); integer division as Go.
117
+ if (entry.compressedSize > 0) {
118
+ const ratio = Math.floor(entry.uncompressedSize / entry.compressedSize);
119
+ if (ratio > limits.maxCompressionRatio) {
120
+ throw new Error(
121
+ `suspicious compression ratio in ${name}: ${ratio}:1 (max: ${limits.maxCompressionRatio}:1)`,
122
+ );
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ /** SHA-256 hex of the archive bytes (Go CalculateHash). */
129
+ export function calculateHash(data: Uint8Array): string {
130
+ return createHash("sha256").update(data).digest("hex");
131
+ }
@@ -28,6 +28,11 @@
28
28
  * bits; FAT/NTFS/VFAT creators carry MSDOS bits that can never encode a
29
29
  * symlink or special file; unknown creators decode to a regular file.
30
30
  *
31
+ * Shared by every archive gate the server runs (skills, plugins): the
32
+ * filter describes what an archive IS before any kind reads it, so it
33
+ * lives with the archive plumbing rather than with the first kind that
34
+ * needed it.
35
+ *
31
36
  * Proven by __tests__/prefilter.test.ts (byte-crafted fixtures per DD-001).
32
37
  */
33
38
  import type { ZipStructuralEntry } from "@stigmer/zip-structure";