@empire-builder-kit/nx 1.0.0-beta.9 → 1.0.0-rc.2

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 (824) hide show
  1. package/NOTICE +6 -0
  2. package/README.md +113 -3
  3. package/executors.json +30 -0
  4. package/package.json +84 -6
  5. package/src/api-contract/baseline-update.d.ts +82 -0
  6. package/src/api-contract/baseline-update.js +225 -0
  7. package/src/api-contract/baseline-update.js.map +1 -0
  8. package/src/api-contract/compatibility.d.ts +30 -0
  9. package/src/api-contract/compatibility.js +643 -0
  10. package/src/api-contract/compatibility.js.map +1 -0
  11. package/src/api-contract/contract-graph.d.ts +35 -0
  12. package/src/api-contract/contract-graph.js +141 -0
  13. package/src/api-contract/contract-graph.js.map +1 -0
  14. package/src/api-contract/evidence.d.ts +23 -0
  15. package/src/api-contract/evidence.js +87 -0
  16. package/src/api-contract/evidence.js.map +1 -0
  17. package/src/api-contract/index.d.ts +6 -0
  18. package/src/api-contract/index.js +10 -0
  19. package/src/api-contract/index.js.map +1 -0
  20. package/src/api-contract/model.d.ts +144 -0
  21. package/src/api-contract/model.fixtures.d.ts +2 -0
  22. package/src/api-contract/model.fixtures.js +81 -0
  23. package/src/api-contract/model.fixtures.js.map +1 -0
  24. package/src/api-contract/model.js +993 -0
  25. package/src/api-contract/model.js.map +1 -0
  26. package/src/api-contract/rollout.d.ts +32 -0
  27. package/src/api-contract/rollout.js +88 -0
  28. package/src/api-contract/rollout.js.map +1 -0
  29. package/src/authorization/compatibility.d.ts +62 -0
  30. package/src/authorization/compatibility.js +175 -0
  31. package/src/authorization/compatibility.js.map +1 -0
  32. package/src/authorization/index.d.ts +1 -0
  33. package/src/authorization/index.js +5 -0
  34. package/src/authorization/index.js.map +1 -0
  35. package/src/blueprints/execution.d.ts +25 -1
  36. package/src/blueprints/execution.js +246 -83
  37. package/src/blueprints/execution.js.map +1 -1
  38. package/src/blueprints/external-sandbox.d.ts +53 -0
  39. package/src/blueprints/external-sandbox.js +1182 -0
  40. package/src/blueprints/external-sandbox.js.map +1 -0
  41. package/src/blueprints/manifest.d.ts +42 -2
  42. package/src/blueprints/manifest.js +82 -27
  43. package/src/blueprints/manifest.js.map +1 -1
  44. package/src/blueprints/resolver.d.ts +14 -5
  45. package/src/blueprints/resolver.js +228 -68
  46. package/src/blueprints/resolver.js.map +1 -1
  47. package/src/cli/agent-command.d.ts +30 -0
  48. package/src/cli/agent-command.js +204 -0
  49. package/src/cli/agent-command.js.map +1 -0
  50. package/src/cli/agent-runtime.d.ts +25 -0
  51. package/src/cli/agent-runtime.js +488 -0
  52. package/src/cli/agent-runtime.js.map +1 -0
  53. package/src/cli/blueprint-authority.d.ts +9 -0
  54. package/src/cli/blueprint-authority.js +43 -0
  55. package/src/cli/blueprint-authority.js.map +1 -0
  56. package/src/cli/blueprint-command.d.ts +24 -0
  57. package/src/cli/blueprint-command.js +63 -0
  58. package/src/cli/blueprint-command.js.map +1 -0
  59. package/src/cli/bootstrap.d.ts +31 -0
  60. package/src/cli/bootstrap.js +165 -0
  61. package/src/cli/bootstrap.js.map +1 -0
  62. package/src/cli/dev-command.d.ts +92 -0
  63. package/src/cli/dev-command.js +561 -0
  64. package/src/cli/dev-command.js.map +1 -0
  65. package/src/cli/main.d.ts +131 -0
  66. package/src/cli/main.js +1199 -0
  67. package/src/cli/main.js.map +1 -0
  68. package/src/cli/output.d.ts +19 -0
  69. package/src/cli/output.js +51 -0
  70. package/src/cli/output.js.map +1 -0
  71. package/src/cli/personal-secret-runtime.d.ts +81 -0
  72. package/src/cli/personal-secret-runtime.js +567 -0
  73. package/src/cli/personal-secret-runtime.js.map +1 -0
  74. package/src/cli/secret-terminal.d.ts +12 -0
  75. package/src/cli/secret-terminal.js +128 -0
  76. package/src/cli/secret-terminal.js.map +1 -0
  77. package/src/container-images.d.ts +1 -0
  78. package/src/container-images.js +5 -0
  79. package/src/container-images.js.map +1 -0
  80. package/src/data-lifecycle/index.d.ts +3 -0
  81. package/src/data-lifecycle/index.js +7 -0
  82. package/src/data-lifecycle/index.js.map +1 -0
  83. package/src/data-lifecycle/model.d.ts +172 -0
  84. package/src/data-lifecycle/model.fixtures.d.ts +2 -0
  85. package/src/data-lifecycle/model.fixtures.js +244 -0
  86. package/src/data-lifecycle/model.fixtures.js.map +1 -0
  87. package/src/data-lifecycle/model.js +95 -0
  88. package/src/data-lifecycle/model.js.map +1 -0
  89. package/src/data-lifecycle/sensitive-artifacts.d.ts +28 -0
  90. package/src/data-lifecycle/sensitive-artifacts.js +146 -0
  91. package/src/data-lifecycle/sensitive-artifacts.js.map +1 -0
  92. package/src/data-lifecycle/validation.d.ts +32 -0
  93. package/src/data-lifecycle/validation.js +837 -0
  94. package/src/data-lifecycle/validation.js.map +1 -0
  95. package/src/database-retirement/contract.d.ts +68 -0
  96. package/src/database-retirement/contract.js +166 -0
  97. package/src/database-retirement/contract.js.map +1 -0
  98. package/src/database-retirement/index.d.ts +1 -0
  99. package/src/database-retirement/index.js +5 -0
  100. package/src/database-retirement/index.js.map +1 -0
  101. package/src/deterministic-order.d.ts +2 -0
  102. package/src/deterministic-order.js +7 -0
  103. package/src/deterministic-order.js.map +1 -0
  104. package/src/developer-agent/context.d.ts +27 -0
  105. package/src/developer-agent/context.js +497 -0
  106. package/src/developer-agent/context.js.map +1 -0
  107. package/src/developer-agent/generator-planning.d.ts +34 -0
  108. package/src/developer-agent/generator-planning.js +645 -0
  109. package/src/developer-agent/generator-planning.js.map +1 -0
  110. package/src/developer-agent/generator-preview.d.ts +8 -0
  111. package/src/developer-agent/generator-preview.js +650 -0
  112. package/src/developer-agent/generator-preview.js.map +1 -0
  113. package/src/developer-agent/git-inspection.d.ts +108 -0
  114. package/src/developer-agent/git-inspection.js +815 -0
  115. package/src/developer-agent/git-inspection.js.map +1 -0
  116. package/src/developer-agent/handoff.d.ts +43 -0
  117. package/src/developer-agent/handoff.js +698 -0
  118. package/src/developer-agent/handoff.js.map +1 -0
  119. package/src/developer-agent/index.d.ts +10 -0
  120. package/src/developer-agent/index.js +14 -0
  121. package/src/developer-agent/index.js.map +1 -0
  122. package/src/developer-agent/model.d.ts +481 -0
  123. package/src/developer-agent/model.js +143 -0
  124. package/src/developer-agent/model.js.map +1 -0
  125. package/src/developer-agent/operation-registry.d.ts +45 -0
  126. package/src/developer-agent/operation-registry.js +1255 -0
  127. package/src/developer-agent/operation-registry.js.map +1 -0
  128. package/src/developer-agent/ordering.d.ts +9 -0
  129. package/src/developer-agent/ordering.js +15 -0
  130. package/src/developer-agent/ordering.js.map +1 -0
  131. package/src/developer-agent/planning.d.ts +18 -0
  132. package/src/developer-agent/planning.js +447 -0
  133. package/src/developer-agent/planning.js.map +1 -0
  134. package/src/developer-agent/preview-changes.d.ts +26 -0
  135. package/src/developer-agent/preview-changes.js +203 -0
  136. package/src/developer-agent/preview-changes.js.map +1 -0
  137. package/src/developer-agent/preview-source.d.ts +2 -0
  138. package/src/developer-agent/preview-source.js +16 -0
  139. package/src/developer-agent/preview-source.js.map +1 -0
  140. package/src/developer-agent/validation.d.ts +18 -0
  141. package/src/developer-agent/validation.js +2617 -0
  142. package/src/developer-agent/validation.js.map +1 -0
  143. package/src/developer-agent/workspace-inspection.d.ts +20 -0
  144. package/src/developer-agent/workspace-inspection.js +1134 -0
  145. package/src/developer-agent/workspace-inspection.js.map +1 -0
  146. package/src/developer-agent/workspace-path.d.ts +6 -0
  147. package/src/developer-agent/workspace-path.js +22 -0
  148. package/src/developer-agent/workspace-path.js.map +1 -0
  149. package/src/executors/blueprint-trust/blueprint-trust.d.ts +29 -0
  150. package/src/executors/blueprint-trust/blueprint-trust.js +115 -0
  151. package/src/executors/blueprint-trust/blueprint-trust.js.map +1 -0
  152. package/src/executors/blueprint-trust/schema.json +27 -0
  153. package/src/executors/blueprint-verification/blueprint-verification.d.ts +13 -0
  154. package/src/executors/blueprint-verification/blueprint-verification.js +110 -0
  155. package/src/executors/blueprint-verification/blueprint-verification.js.map +1 -0
  156. package/src/executors/blueprint-verification/schema.json +44 -0
  157. package/src/executors/deployment-plan/deployment-plan.js +1 -0
  158. package/src/executors/deployment-plan/deployment-plan.js.map +1 -1
  159. package/src/executors/dev-doctor/dev-doctor.d.ts +19 -5
  160. package/src/executors/dev-doctor/dev-doctor.js +186 -32
  161. package/src/executors/dev-doctor/dev-doctor.js.map +1 -1
  162. package/src/executors/dev-doctor/schema.json +1 -6
  163. package/src/executors/dev-setup/dev-setup.d.ts +7 -1
  164. package/src/executors/dev-setup/dev-setup.js +14 -3
  165. package/src/executors/dev-setup/dev-setup.js.map +1 -1
  166. package/src/executors/developer-context/developer-context.d.ts +38 -0
  167. package/src/executors/developer-context/developer-context.js +78 -0
  168. package/src/executors/developer-context/developer-context.js.map +1 -0
  169. package/src/executors/developer-context/schema.json +87 -0
  170. package/src/executors/fleet/fleet.d.ts +12 -43
  171. package/src/executors/fleet/fleet.js +120 -500
  172. package/src/executors/fleet/fleet.js.map +1 -1
  173. package/src/executors/fleet/schema.json +64 -14
  174. package/src/executors/github-bootstrap/github-bootstrap.d.ts +1 -0
  175. package/src/executors/github-bootstrap/github-bootstrap.js +1 -0
  176. package/src/executors/github-bootstrap/github-bootstrap.js.map +1 -1
  177. package/src/executors/github-bootstrap/schema.json +5 -0
  178. package/src/executors/infrastructure-plan/infrastructure-plan.d.ts +144 -0
  179. package/src/executors/infrastructure-plan/infrastructure-plan.js +3320 -0
  180. package/src/executors/infrastructure-plan/infrastructure-plan.js.map +1 -0
  181. package/src/executors/infrastructure-plan/schema.json +78 -0
  182. package/src/executors/secret-guardrails/schema.json +6 -0
  183. package/src/executors/secret-guardrails/secret-guardrails.d.ts +3 -0
  184. package/src/executors/secret-guardrails/secret-guardrails.js +44 -0
  185. package/src/executors/secret-guardrails/secret-guardrails.js.map +1 -0
  186. package/src/executors/secret-metadata/schema.json +31 -0
  187. package/src/executors/secret-metadata/secret-metadata.d.ts +32 -0
  188. package/src/executors/secret-metadata/secret-metadata.js +131 -0
  189. package/src/executors/secret-metadata/secret-metadata.js.map +1 -0
  190. package/src/executors/sst-lifecycle/logging-preflight.d.ts +17 -0
  191. package/src/executors/sst-lifecycle/logging-preflight.js +196 -0
  192. package/src/executors/sst-lifecycle/logging-preflight.js.map +1 -0
  193. package/src/executors/sst-lifecycle/run-sst-command.d.ts +23 -3
  194. package/src/executors/sst-lifecycle/run-sst-command.js +113 -10
  195. package/src/executors/sst-lifecycle/run-sst-command.js.map +1 -1
  196. package/src/executors/sst-lifecycle/schema.json +9 -5
  197. package/src/executors/sst-lifecycle/secret-preflight.d.ts +25 -0
  198. package/src/executors/sst-lifecycle/secret-preflight.js +119 -0
  199. package/src/executors/sst-lifecycle/secret-preflight.js.map +1 -0
  200. package/src/foundation/discovery.d.ts +17 -1
  201. package/src/foundation/discovery.js +16 -1
  202. package/src/foundation/discovery.js.map +1 -1
  203. package/src/foundation/index.d.ts +3 -0
  204. package/src/foundation/index.js +3 -0
  205. package/src/foundation/index.js.map +1 -1
  206. package/src/foundation/local-database-contract.d.ts +1 -0
  207. package/src/foundation/local-database-contract.js +3 -0
  208. package/src/foundation/local-database-contract.js.map +1 -1
  209. package/src/foundation/logging-preflight.d.ts +30 -0
  210. package/src/foundation/logging-preflight.js +138 -0
  211. package/src/foundation/logging-preflight.js.map +1 -0
  212. package/src/foundation/logging.d.ts +70 -0
  213. package/src/foundation/logging.js +133 -0
  214. package/src/foundation/logging.js.map +1 -0
  215. package/src/foundation/preflight.d.ts +9 -0
  216. package/src/foundation/preflight.js +58 -2
  217. package/src/foundation/preflight.js.map +1 -1
  218. package/src/foundation/provision-database-bindings.d.ts +9 -1
  219. package/src/foundation/provision-database-bindings.js +25 -5
  220. package/src/foundation/provision-database-bindings.js.map +1 -1
  221. package/src/foundation/provision-logical-database.d.ts +10 -2
  222. package/src/foundation/provision-logical-database.js +68 -113
  223. package/src/foundation/provision-logical-database.js.map +1 -1
  224. package/src/foundation/router-origin-proof.d.ts +2 -0
  225. package/src/foundation/router-origin-proof.js +25 -0
  226. package/src/foundation/router-origin-proof.js.map +1 -0
  227. package/src/foundation/stages.d.ts +1 -0
  228. package/src/foundation/stages.js +9 -1
  229. package/src/foundation/stages.js.map +1 -1
  230. package/src/frontend-security/index.d.ts +1 -0
  231. package/src/frontend-security/index.js +5 -0
  232. package/src/frontend-security/index.js.map +1 -0
  233. package/src/frontend-security/security-headers.d.ts +50 -0
  234. package/src/frontend-security/security-headers.js +418 -0
  235. package/src/frontend-security/security-headers.js.map +1 -0
  236. package/src/generators/feature-registry.d.ts +13 -0
  237. package/src/generators/feature-registry.js +73 -0
  238. package/src/generators/feature-registry.js.map +1 -0
  239. package/src/generators/function/function.d.ts +1 -1
  240. package/src/generators/function/function.js +51 -6
  241. package/src/generators/function/function.js.map +1 -1
  242. package/src/generators/function/schema.d.ts +1 -0
  243. package/src/generators/function/schema.json +6 -1
  244. package/src/generators/logging-registry.d.ts +13 -0
  245. package/src/generators/logging-registry.js +62 -0
  246. package/src/generators/logging-registry.js.map +1 -0
  247. package/src/generators/post-generation-install.d.ts +67 -0
  248. package/src/generators/post-generation-install.js +3308 -0
  249. package/src/generators/post-generation-install.js.map +1 -0
  250. package/src/generators/preset/generator.js +3 -0
  251. package/src/generators/preset/generator.js.map +1 -1
  252. package/src/generators/preset/tool-versions.d.ts +18 -0
  253. package/src/generators/preset/tool-versions.js +22 -0
  254. package/src/generators/preset/tool-versions.js.map +1 -0
  255. package/src/generators/preset/workspace-files-developer-agent.d.ts +14 -0
  256. package/src/generators/preset/workspace-files-developer-agent.js +511 -0
  257. package/src/generators/preset/workspace-files-developer-agent.js.map +1 -0
  258. package/src/generators/preset/workspace-files-foundation-workload-roles.d.ts +6 -0
  259. package/src/generators/preset/workspace-files-foundation-workload-roles.js +406 -0
  260. package/src/generators/preset/workspace-files-foundation-workload-roles.js.map +1 -0
  261. package/src/generators/preset/workspace-files-performance-cost.d.ts +66 -0
  262. package/src/generators/preset/workspace-files-performance-cost.js +866 -0
  263. package/src/generators/preset/workspace-files-performance-cost.js.map +1 -0
  264. package/src/generators/preset/workspace-files-performance-load.d.ts +73 -0
  265. package/src/generators/preset/workspace-files-performance-load.js +801 -0
  266. package/src/generators/preset/workspace-files-performance-load.js.map +1 -0
  267. package/src/generators/preset/workspace-files-workload-role-baseline.d.ts +9 -0
  268. package/src/generators/preset/workspace-files-workload-role-baseline.js +1102 -0
  269. package/src/generators/preset/workspace-files-workload-role-baseline.js.map +1 -0
  270. package/src/generators/preset/workspace-files.d.ts +14 -1
  271. package/src/generators/preset/workspace-files.js +8189 -245
  272. package/src/generators/preset/workspace-files.js.map +1 -1
  273. package/src/generators/repository-policy/repository-policy.js +3 -47
  274. package/src/generators/repository-policy/repository-policy.js.map +1 -1
  275. package/src/generators/slice/built-in-plan-api-contract-files.d.ts +2 -0
  276. package/src/generators/slice/built-in-plan-api-contract-files.js +2656 -0
  277. package/src/generators/slice/built-in-plan-api-contract-files.js.map +1 -0
  278. package/src/generators/slice/built-in-plan-api-files.d.ts +2 -0
  279. package/src/generators/slice/built-in-plan-api-files.js +1186 -0
  280. package/src/generators/slice/built-in-plan-api-files.js.map +1 -0
  281. package/src/generators/slice/built-in-plan-async-work-files.d.ts +2 -0
  282. package/src/generators/slice/built-in-plan-async-work-files.js +7903 -0
  283. package/src/generators/slice/built-in-plan-async-work-files.js.map +1 -0
  284. package/src/generators/slice/built-in-plan-authorization-files.d.ts +2 -0
  285. package/src/generators/slice/built-in-plan-authorization-files.js +2314 -0
  286. package/src/generators/slice/built-in-plan-authorization-files.js.map +1 -0
  287. package/src/generators/slice/built-in-plan-authorization-infrastructure-files.d.ts +2 -0
  288. package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +559 -0
  289. package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js.map +1 -0
  290. package/src/generators/slice/built-in-plan-data-deletion-files.d.ts +2 -0
  291. package/src/generators/slice/built-in-plan-data-deletion-files.js +1101 -0
  292. package/src/generators/slice/built-in-plan-data-deletion-files.js.map +1 -0
  293. package/src/generators/slice/built-in-plan-data-export-infrastructure-files.d.ts +2 -0
  294. package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js +249 -0
  295. package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js.map +1 -0
  296. package/src/generators/slice/built-in-plan-data-files.d.ts +2 -0
  297. package/src/generators/slice/built-in-plan-data-files.js +1530 -0
  298. package/src/generators/slice/built-in-plan-data-files.js.map +1 -0
  299. package/src/generators/slice/built-in-plan-data-lifecycle-files.d.ts +2 -0
  300. package/src/generators/slice/built-in-plan-data-lifecycle-files.js +750 -0
  301. package/src/generators/slice/built-in-plan-data-lifecycle-files.js.map +1 -0
  302. package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.d.ts +2 -0
  303. package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js +828 -0
  304. package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js.map +1 -0
  305. package/src/generators/slice/built-in-plan-data-retention-job-files.d.ts +2 -0
  306. package/src/generators/slice/built-in-plan-data-retention-job-files.js +2604 -0
  307. package/src/generators/slice/built-in-plan-data-retention-job-files.js.map +1 -0
  308. package/src/generators/slice/built-in-plan-data-retention-launcher-files.d.ts +2 -0
  309. package/src/generators/slice/built-in-plan-data-retention-launcher-files.js +144 -0
  310. package/src/generators/slice/built-in-plan-data-retention-launcher-files.js.map +1 -0
  311. package/src/generators/slice/built-in-plan-data-rights-files.d.ts +2 -0
  312. package/src/generators/slice/built-in-plan-data-rights-files.js +4628 -0
  313. package/src/generators/slice/built-in-plan-data-rights-files.js.map +1 -0
  314. package/src/generators/slice/built-in-plan-database-lifecycle-files.d.ts +2 -0
  315. package/src/generators/slice/built-in-plan-database-lifecycle-files.js +1901 -0
  316. package/src/generators/slice/built-in-plan-database-lifecycle-files.js.map +1 -0
  317. package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.d.ts +2 -0
  318. package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js +485 -0
  319. package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js.map +1 -0
  320. package/src/generators/slice/built-in-plan-foundation-files.d.ts +2 -0
  321. package/src/generators/slice/built-in-plan-foundation-files.js +184 -0
  322. package/src/generators/slice/built-in-plan-foundation-files.js.map +1 -0
  323. package/src/generators/slice/built-in-plan-frontend-files.d.ts +2 -0
  324. package/src/generators/slice/built-in-plan-frontend-files.js +2233 -0
  325. package/src/generators/slice/built-in-plan-frontend-files.js.map +1 -0
  326. package/src/generators/slice/built-in-plan-infrastructure-files.d.ts +2 -0
  327. package/src/generators/slice/built-in-plan-infrastructure-files.js +3038 -0
  328. package/src/generators/slice/built-in-plan-infrastructure-files.js.map +1 -0
  329. package/src/generators/slice/built-in-plan-infrastructure-safety-files.d.ts +2 -0
  330. package/src/generators/slice/built-in-plan-infrastructure-safety-files.js +312 -0
  331. package/src/generators/slice/built-in-plan-infrastructure-safety-files.js.map +1 -0
  332. package/src/generators/slice/built-in-plan-metadata-files.d.ts +3 -0
  333. package/src/generators/slice/built-in-plan-metadata-files.js +219 -0
  334. package/src/generators/slice/built-in-plan-metadata-files.js.map +1 -0
  335. package/src/generators/slice/built-in-plan-operations-files.d.ts +2 -0
  336. package/src/generators/slice/built-in-plan-operations-files.js +630 -0
  337. package/src/generators/slice/built-in-plan-operations-files.js.map +1 -0
  338. package/src/generators/slice/built-in-plan-performance-files.d.ts +3 -0
  339. package/src/generators/slice/built-in-plan-performance-files.js +3293 -0
  340. package/src/generators/slice/built-in-plan-performance-files.js.map +1 -0
  341. package/src/generators/slice/built-in-plan-project-files.d.ts +3 -0
  342. package/src/generators/slice/built-in-plan-project-files.js +979 -0
  343. package/src/generators/slice/built-in-plan-project-files.js.map +1 -0
  344. package/src/generators/slice/built-in-plan-release-files.d.ts +2 -0
  345. package/src/generators/slice/built-in-plan-release-files.js +6387 -0
  346. package/src/generators/slice/built-in-plan-release-files.js.map +1 -0
  347. package/src/generators/slice/built-in-plan-reliability-files.d.ts +2 -0
  348. package/src/generators/slice/built-in-plan-reliability-files.js +4499 -0
  349. package/src/generators/slice/built-in-plan-reliability-files.js.map +1 -0
  350. package/src/generators/slice/built-in-plan-secret-runtime-files.d.ts +2 -0
  351. package/src/generators/slice/built-in-plan-secret-runtime-files.js +1004 -0
  352. package/src/generators/slice/built-in-plan-secret-runtime-files.js.map +1 -0
  353. package/src/generators/slice/built-in-plan-shared.d.ts +53 -0
  354. package/src/generators/slice/built-in-plan-shared.js +113 -0
  355. package/src/generators/slice/built-in-plan-shared.js.map +1 -0
  356. package/src/generators/slice/built-in-plan-testing-files.d.ts +2 -0
  357. package/src/generators/slice/built-in-plan-testing-files.js +2356 -0
  358. package/src/generators/slice/built-in-plan-testing-files.js.map +1 -0
  359. package/src/generators/slice/built-in-plan-verification-files.d.ts +2 -0
  360. package/src/generators/slice/built-in-plan-verification-files.js +358 -0
  361. package/src/generators/slice/built-in-plan-verification-files.js.map +1 -0
  362. package/src/generators/slice/built-in-plan-web-files.d.ts +2 -0
  363. package/src/generators/slice/built-in-plan-web-files.js +430 -0
  364. package/src/generators/slice/built-in-plan-web-files.js.map +1 -0
  365. package/src/generators/slice/built-in-plan-workload-role-files.d.ts +2 -0
  366. package/src/generators/slice/built-in-plan-workload-role-files.js +2356 -0
  367. package/src/generators/slice/built-in-plan-workload-role-files.js.map +1 -0
  368. package/src/generators/slice/built-in-plan.d.ts +8 -0
  369. package/src/generators/slice/built-in-plan.js +264 -0
  370. package/src/generators/slice/built-in-plan.js.map +1 -0
  371. package/src/generators/slice/schema.json +1 -1
  372. package/src/generators/slice/slice.d.ts +1 -22
  373. package/src/generators/slice/slice.js +185 -1510
  374. package/src/generators/slice/slice.js.map +1 -1
  375. package/src/generators/upgrade/schema.d.ts +2 -0
  376. package/src/generators/upgrade/schema.json +11 -1
  377. package/src/generators/upgrade/upgrade.d.ts +51 -1
  378. package/src/generators/upgrade/upgrade.js +820 -82
  379. package/src/generators/upgrade/upgrade.js.map +1 -1
  380. package/src/generators/workload/frozen-container.d.ts +8 -0
  381. package/src/generators/workload/frozen-container.js +36 -0
  382. package/src/generators/workload/frozen-container.js.map +1 -0
  383. package/src/generators/workload/performance-registration.d.ts +32 -0
  384. package/src/generators/workload/performance-registration.js +226 -0
  385. package/src/generators/workload/performance-registration.js.map +1 -0
  386. package/src/generators/workload/reliability-registration.d.ts +16 -0
  387. package/src/generators/workload/reliability-registration.js +150 -0
  388. package/src/generators/workload/reliability-registration.js.map +1 -0
  389. package/src/generators/workload/schema.d.ts +1 -0
  390. package/src/generators/workload/schema.json +6 -1
  391. package/src/generators/workload/service-performance-files.d.ts +4 -0
  392. package/src/generators/workload/service-performance-files.js +1846 -0
  393. package/src/generators/workload/service-performance-files.js.map +1 -0
  394. package/src/generators/workload/workload.d.ts +3 -2
  395. package/src/generators/workload/workload.js +1083 -18
  396. package/src/generators/workload/workload.js.map +1 -1
  397. package/src/git-policy/action-pins.d.ts +10 -0
  398. package/src/git-policy/action-pins.js +10 -0
  399. package/src/git-policy/action-pins.js.map +1 -1
  400. package/src/git-policy/github-bootstrap.d.ts +14 -1
  401. package/src/git-policy/github-bootstrap.js +274 -46
  402. package/src/git-policy/github-bootstrap.js.map +1 -1
  403. package/src/index.d.ts +2 -0
  404. package/src/index.js +2 -0
  405. package/src/index.js.map +1 -1
  406. package/src/infrastructure-change/convergence.d.ts +13 -0
  407. package/src/infrastructure-change/convergence.js +85 -0
  408. package/src/infrastructure-change/convergence.js.map +1 -0
  409. package/src/infrastructure-change/drift.d.ts +13 -0
  410. package/src/infrastructure-change/drift.js +112 -0
  411. package/src/infrastructure-change/drift.js.map +1 -0
  412. package/src/infrastructure-change/index.d.ts +7 -0
  413. package/src/infrastructure-change/index.js +11 -0
  414. package/src/infrastructure-change/index.js.map +1 -0
  415. package/src/infrastructure-change/model.d.ts +253 -0
  416. package/src/infrastructure-change/model.js +28 -0
  417. package/src/infrastructure-change/model.js.map +1 -0
  418. package/src/infrastructure-change/normalize.d.ts +12 -0
  419. package/src/infrastructure-change/normalize.js +245 -0
  420. package/src/infrastructure-change/normalize.js.map +1 -0
  421. package/src/infrastructure-change/plan.d.ts +40 -0
  422. package/src/infrastructure-change/plan.js +361 -0
  423. package/src/infrastructure-change/plan.js.map +1 -0
  424. package/src/infrastructure-change/risk.d.ts +7 -0
  425. package/src/infrastructure-change/risk.js +269 -0
  426. package/src/infrastructure-change/risk.js.map +1 -0
  427. package/src/infrastructure-change/summary.d.ts +20 -0
  428. package/src/infrastructure-change/summary.js +130 -0
  429. package/src/infrastructure-change/summary.js.map +1 -0
  430. package/src/local-dev/context-discovery.d.ts +2 -0
  431. package/src/local-dev/context-discovery.js +59 -0
  432. package/src/local-dev/context-discovery.js.map +1 -0
  433. package/src/local-dev/contract-validation.d.ts +15 -0
  434. package/src/local-dev/contract-validation.js +84 -0
  435. package/src/local-dev/contract-validation.js.map +1 -0
  436. package/src/local-dev/contracts.d.ts +10 -1
  437. package/src/local-dev/contracts.js +57 -5
  438. package/src/local-dev/contracts.js.map +1 -1
  439. package/src/local-dev/control-contract.d.ts +67 -0
  440. package/src/local-dev/control-contract.js +180 -0
  441. package/src/local-dev/control-contract.js.map +1 -0
  442. package/src/local-dev/dev-command-core.d.ts +60 -0
  443. package/src/local-dev/dev-command-core.js +89 -0
  444. package/src/local-dev/dev-command-core.js.map +1 -0
  445. package/src/local-dev/effects.d.ts +16 -0
  446. package/src/local-dev/effects.js +63 -0
  447. package/src/local-dev/effects.js.map +1 -0
  448. package/src/local-dev/environment-inspector.d.ts +125 -0
  449. package/src/local-dev/environment-inspector.js +687 -0
  450. package/src/local-dev/environment-inspector.js.map +1 -0
  451. package/src/local-dev/environment-state.d.ts +113 -0
  452. package/src/local-dev/environment-state.js +463 -0
  453. package/src/local-dev/environment-state.js.map +1 -0
  454. package/src/local-dev/errors.d.ts +6 -0
  455. package/src/local-dev/errors.js +41 -0
  456. package/src/local-dev/errors.js.map +1 -0
  457. package/src/local-dev/fleet-client.d.ts +33 -0
  458. package/src/local-dev/fleet-client.js +156 -0
  459. package/src/local-dev/fleet-client.js.map +1 -0
  460. package/src/local-dev/fleet-configuration.d.ts +13 -0
  461. package/src/local-dev/fleet-configuration.js +71 -0
  462. package/src/local-dev/fleet-configuration.js.map +1 -0
  463. package/src/local-dev/fleet-inventory.d.ts +56 -0
  464. package/src/local-dev/fleet-inventory.js +469 -0
  465. package/src/local-dev/fleet-inventory.js.map +1 -0
  466. package/src/local-dev/fleet-ipc.d.ts +28 -0
  467. package/src/local-dev/fleet-ipc.js +267 -0
  468. package/src/local-dev/fleet-ipc.js.map +1 -0
  469. package/src/local-dev/fleet-launcher.d.ts +53 -0
  470. package/src/local-dev/fleet-launcher.js +379 -0
  471. package/src/local-dev/fleet-launcher.js.map +1 -0
  472. package/src/local-dev/fleet-lock.d.ts +41 -0
  473. package/src/local-dev/fleet-lock.js +135 -0
  474. package/src/local-dev/fleet-lock.js.map +1 -0
  475. package/src/local-dev/fleet-logs.d.ts +66 -0
  476. package/src/local-dev/fleet-logs.js +542 -0
  477. package/src/local-dev/fleet-logs.js.map +1 -0
  478. package/src/local-dev/fleet-process.d.ts +50 -0
  479. package/src/local-dev/fleet-process.js +289 -0
  480. package/src/local-dev/fleet-process.js.map +1 -0
  481. package/src/local-dev/fleet-runtime.d.ts +22 -0
  482. package/src/local-dev/fleet-runtime.js +368 -0
  483. package/src/local-dev/fleet-runtime.js.map +1 -0
  484. package/src/local-dev/fleet-session.d.ts +70 -0
  485. package/src/local-dev/fleet-session.js +301 -0
  486. package/src/local-dev/fleet-session.js.map +1 -0
  487. package/src/local-dev/fleet-slice-runner-daemon.d.ts +1 -0
  488. package/src/local-dev/fleet-slice-runner-daemon.js +21 -0
  489. package/src/local-dev/fleet-slice-runner-daemon.js.map +1 -0
  490. package/src/local-dev/fleet-startup.d.ts +22 -0
  491. package/src/local-dev/fleet-startup.js +114 -0
  492. package/src/local-dev/fleet-startup.js.map +1 -0
  493. package/src/local-dev/fleet-state.d.ts +62 -0
  494. package/src/local-dev/fleet-state.js +297 -0
  495. package/src/local-dev/fleet-state.js.map +1 -0
  496. package/src/local-dev/fleet-supervisor-daemon.d.ts +1 -0
  497. package/src/local-dev/fleet-supervisor-daemon.js +41 -0
  498. package/src/local-dev/fleet-supervisor-daemon.js.map +1 -0
  499. package/src/local-dev/fleet-supervisor.d.ts +52 -0
  500. package/src/local-dev/fleet-supervisor.js +384 -0
  501. package/src/local-dev/fleet-supervisor.js.map +1 -0
  502. package/src/local-dev/gateway.js +1 -1
  503. package/src/local-dev/gateway.js.map +1 -1
  504. package/src/local-dev/identity.js +4 -6
  505. package/src/local-dev/identity.js.map +1 -1
  506. package/src/local-dev/index.d.ts +1 -0
  507. package/src/local-dev/index.js +1 -0
  508. package/src/local-dev/index.js.map +1 -1
  509. package/src/local-dev/local-context.d.ts +62 -0
  510. package/src/local-dev/local-context.js +299 -0
  511. package/src/local-dev/local-context.js.map +1 -0
  512. package/src/local-dev/nx-workspace.d.ts +45 -0
  513. package/src/local-dev/nx-workspace.js +228 -0
  514. package/src/local-dev/nx-workspace.js.map +1 -0
  515. package/src/local-dev/personal-secret-ledger.d.ts +75 -0
  516. package/src/local-dev/personal-secret-ledger.js +391 -0
  517. package/src/local-dev/personal-secret-ledger.js.map +1 -0
  518. package/src/local-dev/personal-stage.d.ts +18 -0
  519. package/src/local-dev/personal-stage.js +129 -0
  520. package/src/local-dev/personal-stage.js.map +1 -0
  521. package/src/local-dev/private-state.d.ts +17 -0
  522. package/src/local-dev/private-state.js +254 -0
  523. package/src/local-dev/private-state.js.map +1 -0
  524. package/src/local-dev/process-identity.d.ts +9 -0
  525. package/src/local-dev/process-identity.js +79 -0
  526. package/src/local-dev/process-identity.js.map +1 -0
  527. package/src/local-dev/runtime-paths.d.ts +17 -0
  528. package/src/local-dev/runtime-paths.js +33 -0
  529. package/src/local-dev/runtime-paths.js.map +1 -0
  530. package/src/local-dev/secret-slice-claim.d.ts +17 -0
  531. package/src/local-dev/secret-slice-claim.js +75 -0
  532. package/src/local-dev/secret-slice-claim.js.map +1 -0
  533. package/src/local-dev/slice-claim.d.ts +36 -0
  534. package/src/local-dev/slice-claim.js +199 -0
  535. package/src/local-dev/slice-claim.js.map +1 -0
  536. package/src/local-dev/slice-runner.d.ts +121 -0
  537. package/src/local-dev/slice-runner.js +715 -0
  538. package/src/local-dev/slice-runner.js.map +1 -0
  539. package/src/local-dev/tls.js +51 -17
  540. package/src/local-dev/tls.js.map +1 -1
  541. package/src/ownership/composition.d.ts +5 -2
  542. package/src/ownership/composition.js +26 -3
  543. package/src/ownership/composition.js.map +1 -1
  544. package/src/ownership/hash.d.ts +1 -1
  545. package/src/ownership/hash.js +3 -1
  546. package/src/ownership/hash.js.map +1 -1
  547. package/src/ownership/record.d.ts +32 -1
  548. package/src/ownership/record.js +139 -2
  549. package/src/ownership/record.js.map +1 -1
  550. package/src/performance/cost-collection.d.ts +225 -0
  551. package/src/performance/cost-collection.js +825 -0
  552. package/src/performance/cost-collection.js.map +1 -0
  553. package/src/performance/cost-controls.d.ts +131 -0
  554. package/src/performance/cost-controls.js +336 -0
  555. package/src/performance/cost-controls.js.map +1 -0
  556. package/src/performance/evidence.d.ts +140 -0
  557. package/src/performance/evidence.js +599 -0
  558. package/src/performance/evidence.js.map +1 -0
  559. package/src/performance/index.d.ts +10 -0
  560. package/src/performance/index.js +14 -0
  561. package/src/performance/index.js.map +1 -0
  562. package/src/performance/load-safety.d.ts +84 -0
  563. package/src/performance/load-safety.js +346 -0
  564. package/src/performance/load-safety.js.map +1 -0
  565. package/src/performance/model.d.ts +129 -0
  566. package/src/performance/model.js +452 -0
  567. package/src/performance/model.js.map +1 -0
  568. package/src/performance/pr-artifact-budget.d.ts +42 -0
  569. package/src/performance/pr-artifact-budget.js +151 -0
  570. package/src/performance/pr-artifact-budget.js.map +1 -0
  571. package/src/performance/runner.d.ts +75 -0
  572. package/src/performance/runner.js +227 -0
  573. package/src/performance/runner.js.map +1 -0
  574. package/src/performance/scenario-endpoint.d.ts +1 -0
  575. package/src/performance/scenario-endpoint.js +5 -0
  576. package/src/performance/scenario-endpoint.js.map +1 -0
  577. package/src/performance/scenario.d.ts +193 -0
  578. package/src/performance/scenario.js +736 -0
  579. package/src/performance/scenario.js.map +1 -0
  580. package/src/performance/test-fixtures.d.ts +7 -0
  581. package/src/performance/test-fixtures.js +169 -0
  582. package/src/performance/test-fixtures.js.map +1 -0
  583. package/src/performance/unit-cost.d.ts +105 -0
  584. package/src/performance/unit-cost.js +364 -0
  585. package/src/performance/unit-cost.js.map +1 -0
  586. package/src/release/index.d.ts +4 -0
  587. package/src/release/index.js +8 -0
  588. package/src/release/index.js.map +1 -0
  589. package/src/release/lifecycle.d.ts +132 -0
  590. package/src/release/lifecycle.js +411 -0
  591. package/src/release/lifecycle.js.map +1 -0
  592. package/src/release/manifest.d.ts +148 -0
  593. package/src/release/manifest.js +503 -0
  594. package/src/release/manifest.js.map +1 -0
  595. package/src/release/rollout.d.ts +170 -0
  596. package/src/release/rollout.js +578 -0
  597. package/src/release/rollout.js.map +1 -0
  598. package/src/release/source-authority.d.ts +19 -0
  599. package/src/release/source-authority.js +195 -0
  600. package/src/release/source-authority.js.map +1 -0
  601. package/src/repository-policy/deployment-plan.d.ts +2 -1
  602. package/src/repository-policy/deployment-plan.js +2 -0
  603. package/src/repository-policy/deployment-plan.js.map +1 -1
  604. package/src/repository-policy/policy.d.ts +1 -1
  605. package/src/repository-policy/policy.js +29 -25
  606. package/src/repository-policy/policy.js.map +1 -1
  607. package/src/schemas/aggregate-count-evidence-v1.json +135 -0
  608. package/src/schemas/api-contract-baseline-v1.json +674 -0
  609. package/src/schemas/api-contract-compatibility-report-v1.json +126 -0
  610. package/src/schemas/aws-billing-actual-evidence-v1.json +407 -0
  611. package/src/schemas/blueprint-v1.json +18 -1
  612. package/src/schemas/data-lifecycle-policy-v1.json +517 -0
  613. package/src/schemas/generated-ownership-v2.json +22 -0
  614. package/src/schemas/performance-policy-v1.json +335 -0
  615. package/src/schemas/repository-policy-v1.json +1 -0
  616. package/src/schemas/testing-evidence-quarantine-v1.json +168 -0
  617. package/src/schemas/testing-evidence-result-v1.json +319 -0
  618. package/src/secrets/adapters.d.ts +49 -0
  619. package/src/secrets/adapters.js +184 -0
  620. package/src/secrets/adapters.js.map +1 -0
  621. package/src/secrets/aws-control-plane.d.ts +20 -0
  622. package/src/secrets/aws-control-plane.js +255 -0
  623. package/src/secrets/aws-control-plane.js.map +1 -0
  624. package/src/secrets/declaration-verification.d.ts +11 -0
  625. package/src/secrets/declaration-verification.js +68 -0
  626. package/src/secrets/declaration-verification.js.map +1 -0
  627. package/src/secrets/guardrails.d.ts +26 -0
  628. package/src/secrets/guardrails.js +328 -0
  629. package/src/secrets/guardrails.js.map +1 -0
  630. package/src/secrets/index.d.ts +12 -0
  631. package/src/secrets/index.js +16 -0
  632. package/src/secrets/index.js.map +1 -0
  633. package/src/secrets/metadata.d.ts +48 -0
  634. package/src/secrets/metadata.js +171 -0
  635. package/src/secrets/metadata.js.map +1 -0
  636. package/src/secrets/model.d.ts +49 -0
  637. package/src/secrets/model.js +125 -0
  638. package/src/secrets/model.js.map +1 -0
  639. package/src/secrets/operator.d.ts +101 -0
  640. package/src/secrets/operator.js +229 -0
  641. package/src/secrets/operator.js.map +1 -0
  642. package/src/secrets/permissions.d.ts +34 -0
  643. package/src/secrets/permissions.js +86 -0
  644. package/src/secrets/permissions.js.map +1 -0
  645. package/src/secrets/personal-command.d.ts +83 -0
  646. package/src/secrets/personal-command.js +197 -0
  647. package/src/secrets/personal-command.js.map +1 -0
  648. package/src/secrets/personal-ledger.d.ts +21 -0
  649. package/src/secrets/personal-ledger.js +135 -0
  650. package/src/secrets/personal-ledger.js.map +1 -0
  651. package/src/secrets/registry.d.ts +9 -0
  652. package/src/secrets/registry.js +86 -0
  653. package/src/secrets/registry.js.map +1 -0
  654. package/src/secrets/verification.d.ts +18 -0
  655. package/src/secrets/verification.js +139 -0
  656. package/src/secrets/verification.js.map +1 -0
  657. package/src/secrets/workload-access.d.ts +46 -0
  658. package/src/secrets/workload-access.js +163 -0
  659. package/src/secrets/workload-access.js.map +1 -0
  660. package/src/supply-chain/action-pins.d.ts +26 -0
  661. package/src/supply-chain/action-pins.js +208 -0
  662. package/src/supply-chain/action-pins.js.map +1 -0
  663. package/src/supply-chain/blueprint-trust-git.d.ts +130 -0
  664. package/src/supply-chain/blueprint-trust-git.js +1581 -0
  665. package/src/supply-chain/blueprint-trust-git.js.map +1 -0
  666. package/src/supply-chain/blueprint-trust-process.d.ts +4 -0
  667. package/src/supply-chain/blueprint-trust-process.js +88 -0
  668. package/src/supply-chain/blueprint-trust-process.js.map +1 -0
  669. package/src/supply-chain/blueprint-trust.d.ts +354 -0
  670. package/src/supply-chain/blueprint-trust.js +1558 -0
  671. package/src/supply-chain/blueprint-trust.js.map +1 -0
  672. package/src/supply-chain/blueprint-verification-authority.d.ts +62 -0
  673. package/src/supply-chain/blueprint-verification-authority.js +588 -0
  674. package/src/supply-chain/blueprint-verification-authority.js.map +1 -0
  675. package/src/supply-chain/blueprint-verification-execution.d.ts +68 -0
  676. package/src/supply-chain/blueprint-verification-execution.js +624 -0
  677. package/src/supply-chain/blueprint-verification-execution.js.map +1 -0
  678. package/src/supply-chain/build-output.d.ts +35 -0
  679. package/src/supply-chain/build-output.js +398 -0
  680. package/src/supply-chain/build-output.js.map +1 -0
  681. package/src/supply-chain/common.d.ts +21 -0
  682. package/src/supply-chain/common.js +107 -0
  683. package/src/supply-chain/common.js.map +1 -0
  684. package/src/supply-chain/container-artifact-contract.d.ts +23 -0
  685. package/src/supply-chain/container-artifact-contract.js +208 -0
  686. package/src/supply-chain/container-artifact-contract.js.map +1 -0
  687. package/src/supply-chain/container-release.d.ts +119 -0
  688. package/src/supply-chain/container-release.js +496 -0
  689. package/src/supply-chain/container-release.js.map +1 -0
  690. package/src/supply-chain/ecr-applicability.d.ts +19 -0
  691. package/src/supply-chain/ecr-applicability.js +103 -0
  692. package/src/supply-chain/ecr-applicability.js.map +1 -0
  693. package/src/supply-chain/ecr-scanning.d.ts +83 -0
  694. package/src/supply-chain/ecr-scanning.js +321 -0
  695. package/src/supply-chain/ecr-scanning.js.map +1 -0
  696. package/src/supply-chain/ecs-deployed-image.d.ts +85 -0
  697. package/src/supply-chain/ecs-deployed-image.js +300 -0
  698. package/src/supply-chain/ecs-deployed-image.js.map +1 -0
  699. package/src/supply-chain/errors.d.ts +6 -0
  700. package/src/supply-chain/errors.js +15 -0
  701. package/src/supply-chain/errors.js.map +1 -0
  702. package/src/supply-chain/generated-blueprint-trust-command.d.ts +4 -0
  703. package/src/supply-chain/generated-blueprint-trust-command.js +1362 -0
  704. package/src/supply-chain/generated-blueprint-trust-command.js.map +1 -0
  705. package/src/supply-chain/generated-command.d.ts +1 -0
  706. package/src/supply-chain/generated-command.js +687 -0
  707. package/src/supply-chain/generated-command.js.map +1 -0
  708. package/src/supply-chain/generated-container-release-command.d.ts +16 -0
  709. package/src/supply-chain/generated-container-release-command.js +2087 -0
  710. package/src/supply-chain/generated-container-release-command.js.map +1 -0
  711. package/src/supply-chain/generated-ecr-collector-command.d.ts +21 -0
  712. package/src/supply-chain/generated-ecr-collector-command.js +1338 -0
  713. package/src/supply-chain/generated-ecr-collector-command.js.map +1 -0
  714. package/src/supply-chain/generated-files.d.ts +13 -0
  715. package/src/supply-chain/generated-files.js +401 -0
  716. package/src/supply-chain/generated-files.js.map +1 -0
  717. package/src/supply-chain/generated-scanner-command.d.ts +1 -0
  718. package/src/supply-chain/generated-scanner-command.js +718 -0
  719. package/src/supply-chain/generated-scanner-command.js.map +1 -0
  720. package/src/supply-chain/index.d.ts +28 -0
  721. package/src/supply-chain/index.js +35 -0
  722. package/src/supply-chain/index.js.map +1 -0
  723. package/src/supply-chain/inventory.d.ts +79 -0
  724. package/src/supply-chain/inventory.js +717 -0
  725. package/src/supply-chain/inventory.js.map +1 -0
  726. package/src/supply-chain/license-expression.d.ts +7 -0
  727. package/src/supply-chain/license-expression.js +128 -0
  728. package/src/supply-chain/license-expression.js.map +1 -0
  729. package/src/supply-chain/pnpm-toolchain-authority.d.ts +31 -0
  730. package/src/supply-chain/pnpm-toolchain-authority.js +316 -0
  731. package/src/supply-chain/pnpm-toolchain-authority.js.map +1 -0
  732. package/src/supply-chain/policy.d.ts +105 -0
  733. package/src/supply-chain/policy.js +301 -0
  734. package/src/supply-chain/policy.js.map +1 -0
  735. package/src/supply-chain/publication.d.ts +48 -0
  736. package/src/supply-chain/publication.js +85 -0
  737. package/src/supply-chain/publication.js.map +1 -0
  738. package/src/supply-chain/sbom.d.ts +228 -0
  739. package/src/supply-chain/sbom.js +826 -0
  740. package/src/supply-chain/sbom.js.map +1 -0
  741. package/src/supply-chain/scanner.d.ts +77 -0
  742. package/src/supply-chain/scanner.js +502 -0
  743. package/src/supply-chain/scanner.js.map +1 -0
  744. package/src/supply-chain/vendored-source.d.ts +95 -0
  745. package/src/supply-chain/vendored-source.js +315 -0
  746. package/src/supply-chain/vendored-source.js.map +1 -0
  747. package/src/testing-evidence/fixture-scope.d.ts +52 -0
  748. package/src/testing-evidence/fixture-scope.js +140 -0
  749. package/src/testing-evidence/fixture-scope.js.map +1 -0
  750. package/src/testing-evidence/index.d.ts +5 -0
  751. package/src/testing-evidence/index.js +9 -0
  752. package/src/testing-evidence/index.js.map +1 -0
  753. package/src/testing-evidence/quarantine.d.ts +48 -0
  754. package/src/testing-evidence/quarantine.js +253 -0
  755. package/src/testing-evidence/quarantine.js.map +1 -0
  756. package/src/testing-evidence/result.d.ts +108 -0
  757. package/src/testing-evidence/result.js +571 -0
  758. package/src/testing-evidence/result.js.map +1 -0
  759. package/src/testing-evidence/runner-adapter.d.ts +51 -0
  760. package/src/testing-evidence/runner-adapter.js +288 -0
  761. package/src/testing-evidence/runner-adapter.js.map +1 -0
  762. package/src/testing-evidence/sensitive-artifacts.d.ts +13 -0
  763. package/src/testing-evidence/sensitive-artifacts.js +93 -0
  764. package/src/testing-evidence/sensitive-artifacts.js.map +1 -0
  765. package/src/work-markers/work-markers.js +4 -3
  766. package/src/work-markers/work-markers.js.map +1 -1
  767. package/src/workload-roles/account-baseline.d.ts +132 -0
  768. package/src/workload-roles/account-baseline.js +743 -0
  769. package/src/workload-roles/account-baseline.js.map +1 -0
  770. package/src/workload-roles/authority.d.ts +38 -0
  771. package/src/workload-roles/authority.js +156 -0
  772. package/src/workload-roles/authority.js.map +1 -0
  773. package/src/workload-roles/aws-adapter.d.ts +99 -0
  774. package/src/workload-roles/aws-adapter.js +416 -0
  775. package/src/workload-roles/aws-adapter.js.map +1 -0
  776. package/src/workload-roles/aws-internal-handler.d.ts +27 -0
  777. package/src/workload-roles/aws-internal-handler.js +58 -0
  778. package/src/workload-roles/aws-internal-handler.js.map +1 -0
  779. package/src/workload-roles/aws-s3-state.d.ts +52 -0
  780. package/src/workload-roles/aws-s3-state.js +164 -0
  781. package/src/workload-roles/aws-s3-state.js.map +1 -0
  782. package/src/workload-roles/aws-sdk-control-plane.d.ts +12 -0
  783. package/src/workload-roles/aws-sdk-control-plane.js +291 -0
  784. package/src/workload-roles/aws-sdk-control-plane.js.map +1 -0
  785. package/src/workload-roles/boundary.d.ts +33 -0
  786. package/src/workload-roles/boundary.js +130 -0
  787. package/src/workload-roles/boundary.js.map +1 -0
  788. package/src/workload-roles/convergence.d.ts +66 -0
  789. package/src/workload-roles/convergence.js +186 -0
  790. package/src/workload-roles/convergence.js.map +1 -0
  791. package/src/workload-roles/effective-policy.d.ts +51 -0
  792. package/src/workload-roles/effective-policy.js +183 -0
  793. package/src/workload-roles/effective-policy.js.map +1 -0
  794. package/src/workload-roles/handler.d.ts +43 -0
  795. package/src/workload-roles/handler.js +130 -0
  796. package/src/workload-roles/handler.js.map +1 -0
  797. package/src/workload-roles/history.d.ts +47 -0
  798. package/src/workload-roles/history.js +324 -0
  799. package/src/workload-roles/history.js.map +1 -0
  800. package/src/workload-roles/index.d.ts +17 -0
  801. package/src/workload-roles/index.js +21 -0
  802. package/src/workload-roles/index.js.map +1 -0
  803. package/src/workload-roles/injection.d.ts +119 -0
  804. package/src/workload-roles/injection.js +495 -0
  805. package/src/workload-roles/injection.js.map +1 -0
  806. package/src/workload-roles/manifest.d.ts +54 -0
  807. package/src/workload-roles/manifest.js +343 -0
  808. package/src/workload-roles/manifest.js.map +1 -0
  809. package/src/workload-roles/provisioner.d.ts +70 -0
  810. package/src/workload-roles/provisioner.js +231 -0
  811. package/src/workload-roles/provisioner.js.map +1 -0
  812. package/src/workload-roles/registration.d.ts +101 -0
  813. package/src/workload-roles/registration.js +457 -0
  814. package/src/workload-roles/registration.js.map +1 -0
  815. package/src/workload-roles/stage-boundary.d.ts +31 -0
  816. package/src/workload-roles/stage-boundary.js +208 -0
  817. package/src/workload-roles/stage-boundary.js.map +1 -0
  818. package/src/workload-roles/standard-slice.d.ts +54 -0
  819. package/src/workload-roles/standard-slice.js +252 -0
  820. package/src/workload-roles/standard-slice.js.map +1 -0
  821. package/migrations/standard-pre-v1-to-v1.md +0 -11
  822. package/src/foundation/aurora-logical-database.d.ts +0 -76
  823. package/src/foundation/aurora-logical-database.js +0 -419
  824. package/src/foundation/aurora-logical-database.js.map +0 -1
@@ -0,0 +1,1846 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderServicePerformanceFiles = renderServicePerformanceFiles;
4
+ const model_js_1 = require("../../performance/model.js");
5
+ function pascal(value) {
6
+ return value
7
+ .split('-')
8
+ .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
9
+ .join('');
10
+ }
11
+ function renderServicePerformanceFiles(input) {
12
+ const sliceClass = pascal(input.slice);
13
+ const workloadClass = pascal(input.workload);
14
+ const secretName = `${sliceClass}PerformanceLoadHmacKeys`;
15
+ const reservationResourceName = `${sliceClass}${workloadClass}PerformanceReservations`;
16
+ const workloadIdentity = `${input.slice}.${input.workload}-service-performance-task`;
17
+ const executePath = `/${input.slice}/__ebk/performance/service`;
18
+ const cleanupPath = `${executePath}/cleanup`;
19
+ return {
20
+ [`services/${input.workload}/src/performance.ts`]: `import {
21
+ DynamoDBClient,
22
+ GetItemCommand,
23
+ PutItemCommand,
24
+ TransactWriteItemsCommand,
25
+ type GetItemCommandInput,
26
+ type GetItemCommandOutput,
27
+ type PutItemCommandInput,
28
+ type TransactWriteItemsCommandInput,
29
+ } from '@aws-sdk/client-dynamodb';
30
+ import {
31
+ handleProtectedLoadCleanupEndpoint,
32
+ handleProtectedLoadScenarioEndpoint,
33
+ type ProtectedLoadEndpointBindingV1,
34
+ type ProtectedLoadEndpointResponseV1,
35
+ type ProtectedLoadRequestAuthorizationV1,
36
+ } from '@empire-builder-kit/runtime/performance';
37
+ import {
38
+ bindServerSecretRuntime,
39
+ createAwsSecretsManagerSource,
40
+ createServerSecretResolver,
41
+ defineSecrets,
42
+ secret,
43
+ } from '@empire-builder-kit/runtime/secrets';
44
+ import { randomUUID, timingSafeEqual } from 'node:crypto';
45
+ import {
46
+ request as httpRequest,
47
+ type IncomingMessage,
48
+ type ServerResponse,
49
+ } from 'node:http';
50
+ import { Resource } from 'sst/resource';
51
+ import { DEFAULT_SERVICE_PORT } from './service-runtime.js';
52
+
53
+ const EXECUTE_PATH = '${executePath}';
54
+ const CLEANUP_PATH = '${cleanupPath}';
55
+ const MAXIMUM_BODY_BYTES = 32 * 1024;
56
+ export const SERVICE_PER_TASK_CONFIGURED_MAXIMUM = ${model_js_1.STANDARD_SERVICE_PER_TASK_CONCURRENCY};
57
+ export const SERVICE_PER_TASK_SATURATION_SIGNAL_REF =
58
+ 'runtime:service-${input.workload}-per-task-concurrency-utilization-percent';
59
+ const RESERVATION_RETENTION_SECONDS = 30 * 24 * 60 * 60;
60
+ const resources = Resource as unknown as Readonly<Record<string, unknown>>;
61
+
62
+ interface PerformanceHmacKey {
63
+ id: string;
64
+ secret: string;
65
+ }
66
+
67
+ interface PerformanceHmacKeys {
68
+ current: PerformanceHmacKey;
69
+ previous?: PerformanceHmacKey;
70
+ }
71
+
72
+ const performanceHmacKeys = secret.json<PerformanceHmacKeys>({
73
+ validate(value): value is PerformanceHmacKeys {
74
+ const validKey = (candidate: unknown): candidate is PerformanceHmacKey => {
75
+ if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
76
+ return false;
77
+ }
78
+ const record = candidate as Record<string, unknown>;
79
+ const material = typeof record.secret === 'string' ? record.secret : '';
80
+ const decoded = /^[A-Za-z0-9_-]{43}$/.test(material)
81
+ ? Buffer.from(material, 'base64url')
82
+ : Buffer.alloc(0);
83
+ return Object.keys(record).length === 2 &&
84
+ typeof record.id === 'string' &&
85
+ /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(record.id) &&
86
+ decoded.length === 32 && decoded.toString('base64url') === material;
87
+ };
88
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
89
+ const keys = value as Record<string, unknown>;
90
+ if (Object.keys(keys).some((key) => key !== 'current' && key !== 'previous')) {
91
+ return false;
92
+ }
93
+ if (!validKey(keys.current) || (keys.previous !== undefined && !validKey(keys.previous))) {
94
+ return false;
95
+ }
96
+ return keys.previous === undefined ||
97
+ (keys.previous.id !== keys.current.id && keys.previous.secret !== keys.current.secret);
98
+ },
99
+ });
100
+
101
+ const PerformanceSecrets = defineSecrets({
102
+ ${secretName}: {
103
+ cache: { freshTtlMs: 1_000, staleTtlMs: 0 },
104
+ owner: '${input.slice}',
105
+ requiredStages: ['staging', 'production'],
106
+ retention: { mode: 'retain' },
107
+ rotation: {
108
+ mode: 'manual',
109
+ runbook: 'docs/runbooks/performance-capacity-cost.md',
110
+ },
111
+ source: 'operator',
112
+ value: performanceHmacKeys,
113
+ },
114
+ });
115
+
116
+ function required(name: string): string {
117
+ const value = process.env[name]?.trim();
118
+ if (!value) throw new Error('protected-performance-endpoint-disabled');
119
+ return value;
120
+ }
121
+
122
+ export function linkedResource(
123
+ name: string,
124
+ properties: readonly string[],
125
+ ): Record<string, unknown> {
126
+ const value = resources[name];
127
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
128
+ throw new Error('protected-performance-endpoint-disabled');
129
+ }
130
+ const record = value as Record<string, unknown>;
131
+ if (
132
+ record.type !== 'sst.sst.Linkable' ||
133
+ Object.keys(record).some(
134
+ (key) => key !== 'type' && !properties.includes(key),
135
+ )
136
+ ) {
137
+ throw new Error('protected-performance-endpoint-disabled');
138
+ }
139
+ return record;
140
+ }
141
+
142
+ function secretReference() {
143
+ const resource = linkedResource('${secretName}', [
144
+ 'logicalName',
145
+ 'provider',
146
+ 'secretArn',
147
+ ]);
148
+ if (
149
+ resource.logicalName !== '${secretName}' ||
150
+ resource.provider !== 'aws-secrets-manager' ||
151
+ typeof resource.secretArn !== 'string'
152
+ ) {
153
+ throw new Error('protected-performance-endpoint-disabled');
154
+ }
155
+ return {
156
+ logicalName: '${secretName}',
157
+ provider: 'aws-secrets-manager' as const,
158
+ secretArn: resource.secretArn,
159
+ };
160
+ }
161
+
162
+ function reservationTableName(): string {
163
+ const resource = linkedResource('${reservationResourceName}', ['tableName']);
164
+ if (typeof resource.tableName !== 'string' || resource.tableName.length === 0) {
165
+ throw new Error('protected-performance-endpoint-disabled');
166
+ }
167
+ return resource.tableName;
168
+ }
169
+
170
+ type BindingOperation<Result> = (
171
+ binding: ProtectedLoadEndpointBindingV1,
172
+ ) => Promise<Result>;
173
+
174
+ export interface ProtectedServicePerformanceDependencies {
175
+ cleanup(authorization: ProtectedLoadRequestAuthorizationV1): Promise<{
176
+ remainingEffectCount: number;
177
+ removedEffectCount: number;
178
+ }>;
179
+ execute(input: {
180
+ authorization: ProtectedLoadRequestAuthorizationV1;
181
+ requestOrdinal: number;
182
+ }): Promise<{ saturationPercent: number }>;
183
+ now?: () => Date;
184
+ reserve(
185
+ authorization: ProtectedLoadRequestAuthorizationV1,
186
+ ): Promise<'claimed'>;
187
+ withBinding<Result>(
188
+ requestOrigin: string,
189
+ operation: BindingOperation<Result>,
190
+ ): Promise<Result>;
191
+ }
192
+
193
+ const dynamo = new DynamoDBClient({ maxAttempts: 2 });
194
+
195
+ function assertProtectedServiceAuthorization(
196
+ authorization: ProtectedLoadRequestAuthorizationV1,
197
+ ): URL {
198
+ let endpoint: URL;
199
+ try {
200
+ endpoint = new URL(authorization.target.endpoint);
201
+ } catch {
202
+ throw new Error('protected-performance-service-authorization-mismatch');
203
+ }
204
+ const expectedPath =
205
+ authorization.operation === 'cleanup' ? CLEANUP_PATH : EXECUTE_PATH;
206
+ if (
207
+ authorization.adapterId !== 'ebk-service-v1' ||
208
+ authorization.configuredMaximum !== SERVICE_PER_TASK_CONFIGURED_MAXIMUM ||
209
+ authorization.effectId !== null ||
210
+ authorization.saturationSignalRef !==
211
+ SERVICE_PER_TASK_SATURATION_SIGNAL_REF ||
212
+ authorization.scenarioId !== 'service-extension' ||
213
+ authorization.target.slice !== '${input.slice}' ||
214
+ authorization.workload !== 'service' ||
215
+ endpoint.protocol !== 'https:' ||
216
+ endpoint.username ||
217
+ endpoint.password ||
218
+ endpoint.pathname !== expectedPath ||
219
+ endpoint.search ||
220
+ endpoint.hash ||
221
+ endpoint.href !== authorization.target.endpoint ||
222
+ !Number.isFinite(Date.parse(authorization.createdAt)) ||
223
+ !Number.isFinite(Date.parse(authorization.expiresAt))
224
+ ) {
225
+ throw new Error('protected-performance-service-authorization-mismatch');
226
+ }
227
+ return endpoint;
228
+ }
229
+
230
+ function runIdentityMaterial(
231
+ authorization: ProtectedLoadRequestAuthorizationV1,
232
+ ): string {
233
+ const endpoint = assertProtectedServiceAuthorization(authorization);
234
+ return JSON.stringify({
235
+ adapterId: authorization.adapterId,
236
+ configuredMaximum: authorization.configuredMaximum,
237
+ createdAt: authorization.createdAt,
238
+ durationSeconds: authorization.durationSeconds,
239
+ expiresAt: authorization.expiresAt,
240
+ maximumRequests: authorization.maximumRequests,
241
+ planMaterialDigest: authorization.planMaterialDigest,
242
+ release: authorization.release,
243
+ runId: authorization.runId,
244
+ saturationSignalRef: authorization.saturationSignalRef,
245
+ scenarioId: authorization.scenarioId,
246
+ schemaVersion: 1,
247
+ stage: authorization.stage,
248
+ target: {
249
+ accountFingerprint: authorization.target.accountFingerprint,
250
+ origin: endpoint.origin,
251
+ region: authorization.target.region,
252
+ slice: authorization.target.slice,
253
+ },
254
+ workload: authorization.workload,
255
+ });
256
+ }
257
+
258
+ function runItem(input: {
259
+ authorization: ProtectedLoadRequestAuthorizationV1;
260
+ identityMaterial: string;
261
+ sortKey: 'cleanup' | 'run';
262
+ }) {
263
+ const expiresAt =
264
+ Math.ceil(Date.parse(input.authorization.expiresAt) / 1_000) +
265
+ RESERVATION_RETENTION_SECONDS;
266
+ return {
267
+ expires_at_epoch_seconds: { N: String(expiresAt) },
268
+ identity_material: { S: input.identityMaterial },
269
+ pk: { S: 'plan#' + input.authorization.planMaterialDigest },
270
+ sk: { S: input.sortKey },
271
+ };
272
+ }
273
+
274
+ function exactRunPut(input: {
275
+ authorization: ProtectedLoadRequestAuthorizationV1;
276
+ identityMaterial: string;
277
+ sortKey: 'cleanup' | 'run';
278
+ tableName: string;
279
+ }) {
280
+ return {
281
+ ConditionExpression:
282
+ 'attribute_not_exists(pk) OR #identity = :identity',
283
+ ExpressionAttributeNames: { '#identity': 'identity_material' },
284
+ ExpressionAttributeValues: {
285
+ ':identity': { S: input.identityMaterial },
286
+ },
287
+ Item: runItem(input),
288
+ TableName: input.tableName,
289
+ };
290
+ }
291
+
292
+ export interface ServicePerformanceReservationTransport {
293
+ get(input: GetItemCommandInput): Promise<Pick<GetItemCommandOutput, 'Item'>>;
294
+ put(input: PutItemCommandInput): Promise<void>;
295
+ transact(input: TransactWriteItemsCommandInput): Promise<void>;
296
+ }
297
+
298
+ function conditionalCheckFailed(error: unknown): boolean {
299
+ return Boolean(
300
+ error &&
301
+ typeof error === 'object' &&
302
+ !Array.isArray(error) &&
303
+ (error as { name?: string }).name === 'ConditionalCheckFailedException',
304
+ );
305
+ }
306
+
307
+ function retryableTransactionConflict(error: unknown): boolean {
308
+ if (!error || typeof error !== 'object' || Array.isArray(error)) return false;
309
+ const candidate = error as {
310
+ CancellationReasons?: Array<{ Code?: string }>;
311
+ name?: string;
312
+ };
313
+ return candidate.name === 'TransactionConflictException' ||
314
+ (candidate.name === 'TransactionCanceledException' &&
315
+ Array.isArray(candidate.CancellationReasons) &&
316
+ candidate.CancellationReasons.some(
317
+ (reason) => reason.Code === 'TransactionConflict',
318
+ ) &&
319
+ candidate.CancellationReasons.every(
320
+ (reason) =>
321
+ reason.Code === 'None' || reason.Code === 'TransactionConflict',
322
+ ));
323
+ }
324
+
325
+ function conditionalTransactionFailed(error: unknown): boolean {
326
+ if (!error || typeof error !== 'object' || Array.isArray(error)) return false;
327
+ const candidate = error as {
328
+ CancellationReasons?: Array<{ Code?: string }>;
329
+ name?: string;
330
+ };
331
+ return candidate.name === 'TransactionCanceledException' &&
332
+ Array.isArray(candidate.CancellationReasons) &&
333
+ candidate.CancellationReasons.some(
334
+ (reason) => reason.Code === 'ConditionalCheckFailed',
335
+ ) &&
336
+ candidate.CancellationReasons.every(
337
+ (reason) =>
338
+ reason.Code === 'None' || reason.Code === 'ConditionalCheckFailed',
339
+ );
340
+ }
341
+
342
+ async function transactWithBoundedConflictRetry(
343
+ transport: ServicePerformanceReservationTransport,
344
+ transaction: TransactWriteItemsCommandInput,
345
+ ): Promise<void> {
346
+ for (let attempt = 0; attempt < 3; attempt += 1) {
347
+ try {
348
+ await transport.transact(transaction);
349
+ return;
350
+ } catch (error) {
351
+ if (!retryableTransactionConflict(error) || attempt === 2) throw error;
352
+ await new Promise((resolve) => setTimeout(resolve, 10 * (attempt + 1)));
353
+ }
354
+ }
355
+ }
356
+
357
+ async function assertStoredRunIdentity(input: {
358
+ authorization: ProtectedLoadRequestAuthorizationV1;
359
+ identityMaterial: string;
360
+ tableName: string;
361
+ transport: ServicePerformanceReservationTransport;
362
+ }): Promise<boolean> {
363
+ const result = await input.transport.get({
364
+ ConsistentRead: true,
365
+ ExpressionAttributeNames: { '#identity': 'identity_material' },
366
+ Key: {
367
+ pk: { S: 'plan#' + input.authorization.planMaterialDigest },
368
+ sk: { S: 'run' },
369
+ },
370
+ ProjectionExpression: '#identity',
371
+ TableName: input.tableName,
372
+ });
373
+ if (!result.Item) return false;
374
+ if (
375
+ Object.keys(result.Item).length !== 1 ||
376
+ result.Item.identity_material?.S !== input.identityMaterial
377
+ ) {
378
+ throw new Error('protected-performance-service-run-collision');
379
+ }
380
+ return true;
381
+ }
382
+
383
+ async function ensureRunIdentity(input: {
384
+ authorization: ProtectedLoadRequestAuthorizationV1;
385
+ identityMaterial: string;
386
+ tableName: string;
387
+ transport: ServicePerformanceReservationTransport;
388
+ }): Promise<void> {
389
+ if (await assertStoredRunIdentity(input)) return;
390
+ try {
391
+ await input.transport.put({
392
+ ConditionExpression: 'attribute_not_exists(pk)',
393
+ Item: runItem({
394
+ authorization: input.authorization,
395
+ identityMaterial: input.identityMaterial,
396
+ sortKey: 'run',
397
+ }),
398
+ TableName: input.tableName,
399
+ });
400
+ } catch (error) {
401
+ if (!conditionalCheckFailed(error)) throw error;
402
+ if (!(await assertStoredRunIdentity(input))) {
403
+ throw new Error('protected-performance-service-run-initialization-lost');
404
+ }
405
+ }
406
+ }
407
+
408
+ export function createServicePerformanceReservationStore(input: {
409
+ tableName: string;
410
+ transport: ServicePerformanceReservationTransport;
411
+ }) {
412
+ if (!input.tableName.trim()) {
413
+ throw new Error('protected-performance-endpoint-disabled');
414
+ }
415
+ return {
416
+ async cleanup(authorization: ProtectedLoadRequestAuthorizationV1) {
417
+ if (authorization.operation !== 'cleanup') {
418
+ throw new Error('protected-performance-service-authorization-mismatch');
419
+ }
420
+ const identityMaterial = runIdentityMaterial(authorization);
421
+ try {
422
+ await transactWithBoundedConflictRetry(input.transport, {
423
+ ClientRequestToken: randomUUID(),
424
+ TransactItems: [
425
+ {
426
+ Put: exactRunPut({
427
+ authorization,
428
+ identityMaterial,
429
+ sortKey: 'run',
430
+ tableName: input.tableName,
431
+ }),
432
+ },
433
+ {
434
+ Put: exactRunPut({
435
+ authorization,
436
+ identityMaterial,
437
+ sortKey: 'cleanup',
438
+ tableName: input.tableName,
439
+ }),
440
+ },
441
+ ],
442
+ });
443
+ } catch (error) {
444
+ if (!conditionalTransactionFailed(error)) throw error;
445
+ await assertStoredRunIdentity({
446
+ authorization,
447
+ identityMaterial,
448
+ tableName: input.tableName,
449
+ transport: input.transport,
450
+ });
451
+ throw new Error('protected-performance-service-cleanup-collision');
452
+ }
453
+ return { remainingEffectCount: 0, removedEffectCount: 0 };
454
+ },
455
+ async reserve(
456
+ authorization: ProtectedLoadRequestAuthorizationV1,
457
+ ): Promise<'claimed'> {
458
+ if (authorization.operation !== 'execute') {
459
+ throw new Error('protected-performance-service-authorization-mismatch');
460
+ }
461
+ const identityMaterial = runIdentityMaterial(authorization);
462
+ await ensureRunIdentity({
463
+ authorization,
464
+ identityMaterial,
465
+ tableName: input.tableName,
466
+ transport: input.transport,
467
+ });
468
+ const partition = {
469
+ S: 'plan#' + authorization.planMaterialDigest,
470
+ };
471
+ const expiresAt =
472
+ Math.ceil(Date.parse(authorization.expiresAt) / 1_000) +
473
+ RESERVATION_RETENTION_SECONDS;
474
+ await transactWithBoundedConflictRetry(input.transport, {
475
+ ClientRequestToken: randomUUID(),
476
+ TransactItems: [
477
+ {
478
+ ConditionCheck: {
479
+ ConditionExpression: 'attribute_not_exists(pk)',
480
+ Key: { pk: partition, sk: { S: 'cleanup' } },
481
+ TableName: input.tableName,
482
+ },
483
+ },
484
+ {
485
+ Put: {
486
+ ConditionExpression: 'attribute_not_exists(pk)',
487
+ Item: {
488
+ expires_at_epoch_seconds: { N: String(expiresAt) },
489
+ identity_material: { S: identityMaterial },
490
+ pk: partition,
491
+ request_ordinal: {
492
+ N: String(authorization.requestOrdinal),
493
+ },
494
+ sk: { S: 'request#' + authorization.requestOrdinal },
495
+ },
496
+ TableName: input.tableName,
497
+ },
498
+ },
499
+ ],
500
+ });
501
+ return 'claimed';
502
+ },
503
+ };
504
+ }
505
+
506
+ function reservationStore() {
507
+ return createServicePerformanceReservationStore({
508
+ tableName: reservationTableName(),
509
+ transport: {
510
+ async get(input) {
511
+ return dynamo.send(new GetItemCommand(input));
512
+ },
513
+ async put(input) {
514
+ await dynamo.send(new PutItemCommand(input));
515
+ },
516
+ async transact(input) {
517
+ await dynamo.send(new TransactWriteItemsCommand(input));
518
+ },
519
+ },
520
+ });
521
+ }
522
+
523
+ async function reserveRequest(
524
+ authorization: ProtectedLoadRequestAuthorizationV1,
525
+ ): Promise<'claimed'> {
526
+ return reservationStore().reserve(authorization);
527
+ }
528
+
529
+ async function cleanupRun(
530
+ authorization: ProtectedLoadRequestAuthorizationV1,
531
+ ) {
532
+ return reservationStore().cleanup(authorization);
533
+ }
534
+
535
+ export interface LocalServicePerformanceHealthObservation {
536
+ body: unknown;
537
+ statusCode: number | undefined;
538
+ }
539
+
540
+ export type LocalServicePerformanceHealthProbe = (
541
+ port: number,
542
+ ) => Promise<LocalServicePerformanceHealthObservation>;
543
+
544
+ const requestLocalServiceHealth: LocalServicePerformanceHealthProbe =
545
+ (port) => new Promise((resolve, reject) => {
546
+ const request = httpRequest(
547
+ {
548
+ headers: { accept: 'application/json' },
549
+ host: '127.0.0.1',
550
+ method: 'GET',
551
+ path: '/health',
552
+ port,
553
+ },
554
+ (response) => {
555
+ const chunks: Uint8Array[] = [];
556
+ let size = 0;
557
+ response.on('data', (chunk: Uint8Array) => {
558
+ size += chunk.byteLength;
559
+ if (size > 1_024) {
560
+ request.destroy(
561
+ new Error('protected-performance-service-probe-invalid'),
562
+ );
563
+ return;
564
+ }
565
+ chunks.push(chunk);
566
+ });
567
+ response.once('error', reject);
568
+ response.once('end', () => {
569
+ try {
570
+ const body = JSON.parse(
571
+ Buffer.concat(chunks, size).toString('utf8'),
572
+ ) as unknown;
573
+ resolve({ body, statusCode: response.statusCode });
574
+ } catch (error) {
575
+ reject(error);
576
+ }
577
+ });
578
+ },
579
+ );
580
+ request.setTimeout(2_000, () =>
581
+ request.destroy(
582
+ new Error('protected-performance-service-probe-timeout'),
583
+ ),
584
+ );
585
+ request.once('error', reject);
586
+ request.end();
587
+ });
588
+
589
+ export async function performLocalServicePerformanceProbe(
590
+ authorization: ProtectedLoadRequestAuthorizationV1,
591
+ healthProbe: LocalServicePerformanceHealthProbe = requestLocalServiceHealth,
592
+ ): Promise<void> {
593
+ assertProtectedServiceAuthorization(authorization);
594
+ const port = Number(process.env.PORT ?? DEFAULT_SERVICE_PORT);
595
+ if (!Number.isSafeInteger(port) || port <= 0 || port > 65_535) {
596
+ throw new Error('protected-performance-service-port-invalid');
597
+ }
598
+ const observation = await healthProbe(port);
599
+ const body = observation.body;
600
+ if (
601
+ observation.statusCode !== 200 ||
602
+ !body ||
603
+ typeof body !== 'object' ||
604
+ Array.isArray(body) ||
605
+ Object.keys(body).sort().join() !== 'service,status' ||
606
+ (body as Record<string, unknown>).service !== '${input.workload}' ||
607
+ (body as Record<string, unknown>).status !== 'ok'
608
+ ) {
609
+ throw new Error('protected-performance-service-probe-invalid');
610
+ }
611
+ }
612
+
613
+ interface ServicePerformanceExecutionInput {
614
+ authorization: ProtectedLoadRequestAuthorizationV1;
615
+ requestOrdinal: number;
616
+ }
617
+
618
+ export function createProtectedServicePerformanceExecutor(input: {
619
+ perform?: (
620
+ request: ServicePerformanceExecutionInput,
621
+ ) => Promise<void>;
622
+ } = {}) {
623
+ const perform = input.perform ?? ((request) =>
624
+ performLocalServicePerformanceProbe(request.authorization));
625
+ let activeProtectedRequests = 0;
626
+ return async (request: ServicePerformanceExecutionInput) => {
627
+ assertProtectedServiceAuthorization(request.authorization);
628
+ if (
629
+ !Number.isSafeInteger(request.requestOrdinal) ||
630
+ request.requestOrdinal !== request.authorization.requestOrdinal ||
631
+ activeProtectedRequests >= SERVICE_PER_TASK_CONFIGURED_MAXIMUM
632
+ ) {
633
+ throw new Error('protected-performance-service-capacity-refused');
634
+ }
635
+ activeProtectedRequests += 1;
636
+ const observedActiveRequests = activeProtectedRequests;
637
+ try {
638
+ await perform(request);
639
+ return {
640
+ saturationPercent:
641
+ (observedActiveRequests /
642
+ SERVICE_PER_TASK_CONFIGURED_MAXIMUM) *
643
+ 100,
644
+ };
645
+ } finally {
646
+ activeProtectedRequests -= 1;
647
+ }
648
+ };
649
+ }
650
+
651
+ const executeRequest = createProtectedServicePerformanceExecutor();
652
+
653
+ let resolverStage: 'production' | 'staging' | undefined;
654
+ let resolver: ReturnType<typeof createServerSecretResolver> | undefined;
655
+
656
+ async function withEndpointBinding<Result>(
657
+ requestOrigin: string,
658
+ operation: BindingOperation<Result>,
659
+ ): Promise<Result> {
660
+ const stage = process.env.EBK_STAGE;
661
+ if (
662
+ process.env.EBK_PERFORMANCE_LOAD_ENABLED !== 'true' ||
663
+ (stage !== 'staging' && stage !== 'production')
664
+ ) {
665
+ throw new Error('protected-performance-endpoint-disabled');
666
+ }
667
+ if (resolverStage !== undefined && resolverStage !== stage) {
668
+ throw new Error('protected-performance-endpoint-disabled');
669
+ }
670
+ resolverStage = stage;
671
+ resolver ??= createServerSecretResolver({
672
+ binding: bindServerSecretRuntime({
673
+ stage,
674
+ workload: '${workloadIdentity}',
675
+ }),
676
+ source: createAwsSecretsManagerSource(),
677
+ });
678
+ return resolver.runWithSecret({
679
+ declaration: PerformanceSecrets.${secretName},
680
+ isAuthenticationFailure: () => false,
681
+ operation: (hmacKeys) => operation({
682
+ adapterId: 'ebk-service-v1',
683
+ deployedCandidateDigest: required('EBK_PERFORMANCE_CANDIDATE_DIGEST'),
684
+ deployedReleaseId: required('EBK_PERFORMANCE_RELEASE_ID'),
685
+ deployedReleaseMaterialDigest: required(
686
+ 'EBK_PERFORMANCE_RELEASE_MATERIAL_DIGEST',
687
+ ),
688
+ deployedSourceCommit: required('EBK_SOURCE_COMMIT'),
689
+ hmacKeys,
690
+ stage,
691
+ target: {
692
+ accountFingerprint: required('EBK_PERFORMANCE_ACCOUNT_FINGERPRINT'),
693
+ origin: requestOrigin,
694
+ region: required('EBK_PERFORMANCE_REGION'),
695
+ slice: required('EBK_PERFORMANCE_SLICE'),
696
+ },
697
+ }),
698
+ reference: secretReference(),
699
+ });
700
+ }
701
+
702
+ export function createProtectedServicePerformanceHandler(
703
+ dependencies: ProtectedServicePerformanceDependencies,
704
+ ) {
705
+ return async (request: Request): Promise<Response> => {
706
+ try {
707
+ const pathname = new URL(request.url).pathname;
708
+ const requestOrigin = new URL(request.url).origin;
709
+ let result: ProtectedLoadEndpointResponseV1;
710
+ if (pathname === EXECUTE_PATH && request.method === 'GET') {
711
+ result = await dependencies.withBinding(requestOrigin, (binding) =>
712
+ handleProtectedLoadScenarioEndpoint({
713
+ binding,
714
+ execute: dependencies.execute,
715
+ now: dependencies.now,
716
+ request: {
717
+ headers: Object.fromEntries(request.headers.entries()),
718
+ method: 'GET',
719
+ url: request.url,
720
+ },
721
+ reserve: dependencies.reserve,
722
+ }),
723
+ );
724
+ } else if (pathname === CLEANUP_PATH && request.method === 'POST') {
725
+ const bytes = new Uint8Array(await request.arrayBuffer());
726
+ if (bytes.byteLength === 0 || bytes.byteLength > MAXIMUM_BODY_BYTES) {
727
+ throw new Error('protected-performance-request-body-invalid');
728
+ }
729
+ const body = JSON.parse(
730
+ new TextDecoder('utf-8', { fatal: true }).decode(bytes),
731
+ ) as unknown;
732
+ result = await dependencies.withBinding(requestOrigin, (binding) =>
733
+ handleProtectedLoadCleanupEndpoint({
734
+ binding,
735
+ cleanup: dependencies.cleanup,
736
+ now: dependencies.now,
737
+ request: {
738
+ body,
739
+ headers: Object.fromEntries(request.headers.entries()),
740
+ method: 'POST',
741
+ url: request.url,
742
+ },
743
+ }),
744
+ );
745
+ } else {
746
+ throw new Error('protected-performance-endpoint-disabled');
747
+ }
748
+ return Response.json(result.body, {
749
+ headers: { 'cache-control': 'no-store' },
750
+ status: result.status,
751
+ });
752
+ } catch {
753
+ return Response.json(
754
+ { kind: 'ebk-protected-load-endpoint-refusal', status: 'not-found' },
755
+ {
756
+ headers: { 'cache-control': 'no-store' },
757
+ status: 404,
758
+ },
759
+ );
760
+ }
761
+ };
762
+ }
763
+
764
+ export const runProtectedServicePerformanceEndpoint =
765
+ createProtectedServicePerformanceHandler({
766
+ cleanup: cleanupRun,
767
+ execute: executeRequest,
768
+ reserve: reserveRequest,
769
+ withBinding: withEndpointBinding,
770
+ });
771
+
772
+ async function incomingBody(request: IncomingMessage): Promise<ArrayBuffer | undefined> {
773
+ if (request.method !== 'POST') return undefined;
774
+ const chunks: Uint8Array[] = [];
775
+ let size = 0;
776
+ for await (const chunk of request) {
777
+ const bytes = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
778
+ size += bytes.byteLength;
779
+ if (size > MAXIMUM_BODY_BYTES) {
780
+ throw new Error('protected-performance-request-body-invalid');
781
+ }
782
+ chunks.push(bytes);
783
+ }
784
+ if (size === 0) throw new Error('protected-performance-request-body-invalid');
785
+ const concatenated = Buffer.concat(chunks, size);
786
+ const body = new ArrayBuffer(concatenated.byteLength);
787
+ new Uint8Array(body).set(concatenated);
788
+ return body;
789
+ }
790
+
791
+ export async function serveProtectedServicePerformanceRequest(
792
+ request: IncomingMessage,
793
+ response: ServerResponse,
794
+ handler = runProtectedServicePerformanceEndpoint,
795
+ ): Promise<void> {
796
+ const configuredOrigin = required('EBK_PERFORMANCE_ORIGIN');
797
+ let origin: URL;
798
+ try {
799
+ origin = new URL(configuredOrigin);
800
+ } catch {
801
+ throw new Error('protected-performance-endpoint-disabled');
802
+ }
803
+ const requestTarget = request.url;
804
+ if (
805
+ origin.protocol !== 'https:' ||
806
+ origin.username ||
807
+ origin.password ||
808
+ origin.pathname !== '/' ||
809
+ origin.search ||
810
+ origin.hash ||
811
+ origin.origin !== configuredOrigin ||
812
+ !requestTarget ||
813
+ !requestTarget.startsWith('/') ||
814
+ requestTarget.startsWith('//') ||
815
+ requestTarget.includes('\\\\')
816
+ ) {
817
+ throw new Error('protected-performance-endpoint-disabled');
818
+ }
819
+ let target: URL;
820
+ try {
821
+ target = new URL(requestTarget, origin);
822
+ } catch {
823
+ throw new Error('protected-performance-endpoint-disabled');
824
+ }
825
+ if (target.origin !== origin.origin) {
826
+ throw new Error('protected-performance-endpoint-disabled');
827
+ }
828
+ const expectedIngressProof = required('EBK_PERFORMANCE_INGRESS_PROOF');
829
+ const suppliedIngressProof = request.headers['x-ebk-router-origin-proof'];
830
+ if (
831
+ !/^[A-Za-z0-9]{43}$/.test(expectedIngressProof) ||
832
+ typeof suppliedIngressProof !== 'string' ||
833
+ suppliedIngressProof.length !== expectedIngressProof.length ||
834
+ !timingSafeEqual(
835
+ Buffer.from(suppliedIngressProof, 'utf8'),
836
+ Buffer.from(expectedIngressProof, 'utf8'),
837
+ )
838
+ ) {
839
+ throw new Error('protected-performance-endpoint-disabled');
840
+ }
841
+ const headers = new Headers();
842
+ for (const [name, value] of Object.entries(request.headers)) {
843
+ if (name.toLowerCase() === 'x-ebk-router-origin-proof') continue;
844
+ if (Array.isArray(value)) value.forEach((entry) => headers.append(name, entry));
845
+ else if (value !== undefined) headers.set(name, value);
846
+ }
847
+ const body = await incomingBody(request);
848
+ const result = await handler(
849
+ new Request(target.href, {
850
+ ...(body ? { body } : {}),
851
+ headers,
852
+ method: request.method,
853
+ }),
854
+ );
855
+ response.writeHead(result.status, {
856
+ 'cache-control': result.headers.get('cache-control') ?? 'no-store',
857
+ 'content-type': result.headers.get('content-type') ?? 'application/json',
858
+ });
859
+ response.end(await result.text());
860
+ }
861
+ `,
862
+ [`services/${input.workload}/src/performance.spec.ts`]: `import type {
863
+ GetItemCommandInput,
864
+ GetItemCommandOutput,
865
+ PutItemCommandInput,
866
+ TransactWriteItemsCommandInput,
867
+ } from '@aws-sdk/client-dynamodb';
868
+ import {
869
+ createProtectedLoadRequestSignature,
870
+ type ProtectedLoadEndpointBindingV1,
871
+ type ProtectedLoadRequestAuthorizationV1,
872
+ } from '@empire-builder-kit/runtime/performance';
873
+ import { createLogger } from '@empire-builder-kit/runtime/logging';
874
+ import { once } from 'node:events';
875
+ import { request as httpRequest } from 'node:http';
876
+ import { describe, expect, it, vi } from 'vitest';
877
+
878
+ vi.mock('sst/resource', () => ({
879
+ Resource: {
880
+ ${reservationResourceName}: {
881
+ tableName: 'performance-reservations',
882
+ type: 'sst.sst.Linkable',
883
+ },
884
+ ${secretName}: {
885
+ logicalName: '${secretName}',
886
+ provider: 'aws-secrets-manager',
887
+ secretArn: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:performance',
888
+ type: 'sst.sst.Linkable',
889
+ },
890
+ MissingType: { tableName: 'performance-reservations' },
891
+ SubstitutedType: {
892
+ tableName: 'performance-reservations',
893
+ type: 'sst.sst.Secret',
894
+ },
895
+ UnexpectedProperty: {
896
+ tableName: 'performance-reservations',
897
+ type: 'sst.sst.Linkable',
898
+ value: 'forbidden',
899
+ },
900
+ },
901
+ }));
902
+
903
+ import { start } from './main.js';
904
+ import {
905
+ createProtectedServicePerformanceExecutor,
906
+ createProtectedServicePerformanceHandler,
907
+ createServicePerformanceReservationStore,
908
+ linkedResource,
909
+ performLocalServicePerformanceProbe,
910
+ SERVICE_PER_TASK_CONFIGURED_MAXIMUM,
911
+ SERVICE_PER_TASK_SATURATION_SIGNAL_REF,
912
+ type ServicePerformanceReservationTransport,
913
+ serveProtectedServicePerformanceRequest,
914
+ } from './performance.js';
915
+ import { DEFAULT_SERVICE_PORT } from './service-runtime.js';
916
+
917
+ const hmacKey = {
918
+ id: 'service-current-v1',
919
+ secret: Buffer.alloc(32, 0x73).toString('base64url'),
920
+ };
921
+ const ingressProof = 'R'.repeat(43);
922
+ const binding: ProtectedLoadEndpointBindingV1 = {
923
+ adapterId: 'ebk-service-v1',
924
+ deployedCandidateDigest: 'b'.repeat(64),
925
+ deployedReleaseId: 'service-release',
926
+ deployedReleaseMaterialDigest: 'c'.repeat(64),
927
+ deployedSourceCommit: 'd'.repeat(40),
928
+ hmacKeys: { current: hmacKey },
929
+ stage: 'staging',
930
+ target: {
931
+ accountFingerprint: 'sha256:' + 'a'.repeat(64),
932
+ origin: 'https://service.example.test',
933
+ region: 'us-east-1',
934
+ slice: '${input.slice}',
935
+ },
936
+ };
937
+
938
+ function authorization(operation: 'cleanup' | 'execute'):
939
+ ProtectedLoadRequestAuthorizationV1 {
940
+ return {
941
+ adapterId: 'ebk-service-v1',
942
+ configuredMaximum: SERVICE_PER_TASK_CONFIGURED_MAXIMUM,
943
+ createdAt: '2026-08-01T12:00:00.000Z',
944
+ durationSeconds: 60,
945
+ effectId: null,
946
+ expiresAt: '2026-08-01T13:00:00.000Z',
947
+ hmacKeyId: hmacKey.id,
948
+ maximumRequests: 10,
949
+ operation,
950
+ planMaterialDigest: 'e'.repeat(64),
951
+ release: {
952
+ candidateDigest: binding.deployedCandidateDigest,
953
+ releaseId: binding.deployedReleaseId,
954
+ releaseMaterialDigest: binding.deployedReleaseMaterialDigest,
955
+ sourceCommit: binding.deployedSourceCommit,
956
+ },
957
+ requestOrdinal: 1,
958
+ runId: 'service-run',
959
+ saturationSignalRef: SERVICE_PER_TASK_SATURATION_SIGNAL_REF,
960
+ scenarioId: 'service-extension',
961
+ stage: 'staging',
962
+ target: {
963
+ ...binding.target,
964
+ endpoint: 'https://service.example.test' +
965
+ (operation === 'cleanup' ? '${cleanupPath}' : '${executePath}'),
966
+ },
967
+ workload: 'service',
968
+ };
969
+ }
970
+
971
+ function signedRequest(operation: 'cleanup' | 'execute') {
972
+ const material = authorization(operation);
973
+ const headers = {
974
+ 'x-ebk-performance-account-fingerprint': material.target.accountFingerprint,
975
+ 'x-ebk-performance-candidate': material.release.candidateDigest,
976
+ 'x-ebk-performance-configured-maximum': String(material.configuredMaximum),
977
+ 'x-ebk-performance-created-at': material.createdAt,
978
+ 'x-ebk-performance-duration-seconds': String(material.durationSeconds),
979
+ 'x-ebk-performance-expires-at': material.expiresAt,
980
+ 'x-ebk-performance-hmac-key-id': material.hmacKeyId,
981
+ 'x-ebk-performance-maximum-requests': String(material.maximumRequests),
982
+ 'x-ebk-performance-plan': material.planMaterialDigest,
983
+ 'x-ebk-performance-release-id': material.release.releaseId,
984
+ 'x-ebk-performance-release-material': material.release.releaseMaterialDigest,
985
+ 'x-ebk-performance-request': String(material.requestOrdinal),
986
+ 'x-ebk-performance-region': material.target.region,
987
+ 'x-ebk-performance-run': material.runId,
988
+ 'x-ebk-performance-saturation-signal': material.saturationSignalRef,
989
+ 'x-ebk-performance-scenario': material.scenarioId,
990
+ 'x-ebk-performance-signature': createProtectedLoadRequestSignature({
991
+ authorization: material,
992
+ hmacKey,
993
+ }),
994
+ 'x-ebk-performance-slice': material.target.slice,
995
+ 'x-ebk-performance-source': material.release.sourceCommit,
996
+ 'x-ebk-performance-stage': material.stage,
997
+ };
998
+ const body = {
999
+ planMaterialDigest: material.planMaterialDigest,
1000
+ release: material.release,
1001
+ requestOrdinal: material.requestOrdinal,
1002
+ runId: material.runId,
1003
+ scenarioId: material.scenarioId,
1004
+ workload: material.workload,
1005
+ };
1006
+ return new Request(material.target.endpoint, {
1007
+ ...(operation === 'cleanup'
1008
+ ? { body: JSON.stringify(body), headers: { ...headers, 'content-type': 'application/json' } }
1009
+ : { headers }),
1010
+ method: operation === 'cleanup' ? 'POST' : 'GET',
1011
+ });
1012
+ }
1013
+
1014
+ type DynamoItem = Record<string, { N?: string; S?: string }>;
1015
+
1016
+ class FakeDynamoTransactions implements ServicePerformanceReservationTransport {
1017
+ private rows = new Map<string, DynamoItem>();
1018
+ readonly getCalls: GetItemCommandInput[] = [];
1019
+ readonly putCalls: PutItemCommandInput[] = [];
1020
+ readonly transactionCalls: TransactWriteItemsCommandInput[] = [];
1021
+ successfulInitializations = 0;
1022
+
1023
+ async get(
1024
+ input: GetItemCommandInput,
1025
+ ): Promise<Pick<GetItemCommandOutput, 'Item'>> {
1026
+ this.getCalls.push(input);
1027
+ if (
1028
+ input.ConsistentRead !== true ||
1029
+ input.ProjectionExpression !== '#identity' ||
1030
+ input.ExpressionAttributeNames?.['#identity'] !== 'identity_material'
1031
+ ) {
1032
+ throw new Error('fake-dynamo-read-invalid');
1033
+ }
1034
+ const existing = this.rows.get(
1035
+ this.key(input.Key as unknown as DynamoItem),
1036
+ );
1037
+ const identity = existing?.identity_material?.S;
1038
+ return identity ? { Item: { identity_material: { S: identity } } } : {};
1039
+ }
1040
+
1041
+ async put(input: PutItemCommandInput): Promise<void> {
1042
+ this.putCalls.push(input);
1043
+ if (
1044
+ input.ConditionExpression !== 'attribute_not_exists(pk)' ||
1045
+ !input.Item
1046
+ ) {
1047
+ throw new Error('fake-dynamo-initialization-invalid');
1048
+ }
1049
+ const item = input.Item as unknown as DynamoItem;
1050
+ const key = this.key(item);
1051
+ if (this.rows.has(key)) {
1052
+ throw Object.assign(new Error('fake-dynamo-run-already-exists'), {
1053
+ name: 'ConditionalCheckFailedException',
1054
+ });
1055
+ }
1056
+ this.rows.set(key, item);
1057
+ this.successfulInitializations += 1;
1058
+ }
1059
+
1060
+ async transact(input: TransactWriteItemsCommandInput): Promise<void> {
1061
+ this.transactionCalls.push(input);
1062
+ const next = new Map(this.rows);
1063
+ for (const operation of input.TransactItems ?? []) {
1064
+ if (operation.ConditionCheck) {
1065
+ const key = this.key(
1066
+ operation.ConditionCheck.Key as unknown as DynamoItem,
1067
+ );
1068
+ if (
1069
+ operation.ConditionCheck.ConditionExpression !==
1070
+ 'attribute_not_exists(pk)' ||
1071
+ next.has(key)
1072
+ ) {
1073
+ throw new Error('fake-dynamo-conditional-check-failed');
1074
+ }
1075
+ continue;
1076
+ }
1077
+ const put = operation.Put;
1078
+ if (!put?.Item) throw new Error('fake-dynamo-operation-invalid');
1079
+ const item = put.Item as unknown as DynamoItem;
1080
+ const key = this.key(item);
1081
+ const existing = next.get(key);
1082
+ if (put.ConditionExpression === 'attribute_not_exists(pk)') {
1083
+ if (existing) throw new Error('fake-dynamo-request-replayed');
1084
+ } else if (
1085
+ put.ConditionExpression ===
1086
+ 'attribute_not_exists(pk) OR #identity = :identity'
1087
+ ) {
1088
+ const expected = (
1089
+ put.ExpressionAttributeValues?.[':identity'] as
1090
+ | { S?: string }
1091
+ | undefined
1092
+ )?.S;
1093
+ if (!expected || (existing && existing.identity_material?.S !== expected)) {
1094
+ const operationIndex = (input.TransactItems ?? []).indexOf(operation);
1095
+ throw Object.assign(new Error('fake-dynamo-run-collision'), {
1096
+ CancellationReasons: (input.TransactItems ?? []).map((_, index) => ({
1097
+ Code:
1098
+ index === operationIndex ? 'ConditionalCheckFailed' : 'None',
1099
+ })),
1100
+ name: 'TransactionCanceledException',
1101
+ });
1102
+ }
1103
+ } else {
1104
+ throw new Error('fake-dynamo-condition-invalid');
1105
+ }
1106
+ next.set(key, item);
1107
+ }
1108
+ this.rows = next;
1109
+ }
1110
+
1111
+ snapshot() {
1112
+ return [...this.rows.entries()]
1113
+ .map(([key, item]) => ({
1114
+ identity: item.identity_material?.S,
1115
+ key,
1116
+ ordinal: item.request_ordinal?.N,
1117
+ }))
1118
+ .sort((left, right) =>
1119
+ left.key < right.key ? -1 : left.key > right.key ? 1 : 0,
1120
+ );
1121
+ }
1122
+
1123
+ private key(item: DynamoItem): string {
1124
+ const pk = item.pk?.S;
1125
+ const sk = item.sk?.S;
1126
+ if (!pk || !sk) throw new Error('fake-dynamo-key-invalid');
1127
+ return pk + '|' + sk;
1128
+ }
1129
+ }
1130
+
1131
+ class GatedConflictTransactions
1132
+ implements ServicePerformanceReservationTransport {
1133
+ private readonly backing = new FakeDynamoTransactions();
1134
+ private released = false;
1135
+ private readonly waiting: Array<{
1136
+ input: TransactWriteItemsCommandInput;
1137
+ reject(error: unknown): void;
1138
+ resolve(value: void | PromiseLike<void>): void;
1139
+ }> = [];
1140
+ readonly tokens: Array<{
1141
+ operation: 'cleanup' | 'reserve';
1142
+ token: string;
1143
+ }> = [];
1144
+
1145
+ constructor(private readonly first: 'cleanup' | 'reserve') {}
1146
+
1147
+ async get(
1148
+ input: GetItemCommandInput,
1149
+ ): Promise<Pick<GetItemCommandOutput, 'Item'>> {
1150
+ return this.backing.get(input);
1151
+ }
1152
+
1153
+ async put(input: PutItemCommandInput): Promise<void> {
1154
+ return this.backing.put(input);
1155
+ }
1156
+
1157
+ async transact(input: TransactWriteItemsCommandInput): Promise<void> {
1158
+ this.tokens.push({
1159
+ operation: input.TransactItems?.some((item) => item.ConditionCheck)
1160
+ ? 'reserve'
1161
+ : 'cleanup',
1162
+ token: String(input.ClientRequestToken),
1163
+ });
1164
+ if (this.released) return this.backing.transact(input);
1165
+ return new Promise<void>((resolve, reject) => {
1166
+ this.waiting.push({ input, reject, resolve });
1167
+ if (this.waiting.length === 2) void this.releaseConflict();
1168
+ });
1169
+ }
1170
+
1171
+ snapshot() {
1172
+ return this.backing.snapshot();
1173
+ }
1174
+
1175
+ private async releaseConflict(): Promise<void> {
1176
+ const reserve = this.waiting.find(({ input }) =>
1177
+ input.TransactItems?.some((item) => item.ConditionCheck),
1178
+ );
1179
+ const cleanup = this.waiting.find(({ input }) =>
1180
+ input.TransactItems?.every((item) => !item.ConditionCheck),
1181
+ );
1182
+ if (!reserve || !cleanup) throw new Error('fake-dynamo-race-invalid');
1183
+ const winner = this.first === 'reserve' ? reserve : cleanup;
1184
+ const loser = this.first === 'reserve' ? cleanup : reserve;
1185
+ await this.backing.transact(winner.input);
1186
+ this.released = true;
1187
+ winner.resolve(undefined);
1188
+ const conflict = Object.assign(
1189
+ new Error('fake-dynamo-transaction-conflict'),
1190
+ {
1191
+ CancellationReasons: loser.input.TransactItems?.map((_, index) => ({
1192
+ Code: index === 1 ? 'TransactionConflict' : 'None',
1193
+ })),
1194
+ name: 'TransactionCanceledException',
1195
+ },
1196
+ );
1197
+ loser.reject(conflict);
1198
+ }
1199
+ }
1200
+
1201
+ class OneShotCancellationTransactions
1202
+ implements ServicePerformanceReservationTransport {
1203
+ private readonly backing = new FakeDynamoTransactions();
1204
+ private failed = false;
1205
+ readonly tokens: string[] = [];
1206
+
1207
+ constructor(private readonly reasonCodes: readonly string[]) {}
1208
+
1209
+ async get(
1210
+ input: GetItemCommandInput,
1211
+ ): Promise<Pick<GetItemCommandOutput, 'Item'>> {
1212
+ return this.backing.get(input);
1213
+ }
1214
+
1215
+ async put(input: PutItemCommandInput): Promise<void> {
1216
+ return this.backing.put(input);
1217
+ }
1218
+
1219
+ async transact(input: TransactWriteItemsCommandInput): Promise<void> {
1220
+ this.tokens.push(String(input.ClientRequestToken));
1221
+ if (!this.failed) {
1222
+ this.failed = true;
1223
+ throw Object.assign(new Error('fake-dynamo-transaction-cancelled'), {
1224
+ CancellationReasons: this.reasonCodes.map((Code) => ({ Code })),
1225
+ name: 'TransactionCanceledException',
1226
+ });
1227
+ }
1228
+ return this.backing.transact(input);
1229
+ }
1230
+ }
1231
+
1232
+ describe('${input.workload} protected Service performance runtime', () => {
1233
+ it('accepts only exact SST 4.17.1 Linkable resource payloads', () => {
1234
+ expect(
1235
+ linkedResource('${reservationResourceName}', ['tableName']),
1236
+ ).toEqual({
1237
+ tableName: 'performance-reservations',
1238
+ type: 'sst.sst.Linkable',
1239
+ });
1240
+ for (const name of [
1241
+ 'MissingType',
1242
+ 'SubstitutedType',
1243
+ 'UnexpectedProperty',
1244
+ ]) {
1245
+ expect(() => linkedResource(name, ['tableName'])).toThrow(
1246
+ 'protected-performance-endpoint-disabled',
1247
+ );
1248
+ }
1249
+ });
1250
+
1251
+ it('initializes one immutable run before 32 independent reservations', async () => {
1252
+ const transport = new FakeDynamoTransactions();
1253
+ const store = createServicePerformanceReservationStore({
1254
+ tableName: 'performance-reservations',
1255
+ transport,
1256
+ });
1257
+ const execute = {
1258
+ ...authorization('execute'),
1259
+ maximumRequests: SERVICE_PER_TASK_CONFIGURED_MAXIMUM,
1260
+ };
1261
+ await expect(
1262
+ Promise.all(
1263
+ Array.from(
1264
+ { length: SERVICE_PER_TASK_CONFIGURED_MAXIMUM },
1265
+ (_, index) =>
1266
+ store.reserve({ ...execute, requestOrdinal: index + 1 }),
1267
+ ),
1268
+ ),
1269
+ ).resolves.toEqual(
1270
+ Array.from(
1271
+ { length: SERVICE_PER_TASK_CONFIGURED_MAXIMUM },
1272
+ () => 'claimed',
1273
+ ),
1274
+ );
1275
+ expect(transport.successfulInitializations).toBe(1);
1276
+ expect(transport.putCalls).toHaveLength(
1277
+ SERVICE_PER_TASK_CONFIGURED_MAXIMUM,
1278
+ );
1279
+ expect(
1280
+ transport.getCalls.every(({ ConsistentRead }) => ConsistentRead === true),
1281
+ ).toBe(true);
1282
+ expect(transport.transactionCalls).toHaveLength(
1283
+ SERVICE_PER_TASK_CONFIGURED_MAXIMUM,
1284
+ );
1285
+ expect(
1286
+ transport.transactionCalls.every(
1287
+ ({ TransactItems }) =>
1288
+ TransactItems?.length === 2 &&
1289
+ (TransactItems[0]?.ConditionCheck?.Key?.sk as
1290
+ | { S?: string }
1291
+ | undefined)?.S === 'cleanup' &&
1292
+ (TransactItems[1]?.Put?.Item?.sk as
1293
+ | { S?: string }
1294
+ | undefined)?.S?.startsWith('request#') === true &&
1295
+ TransactItems.every(
1296
+ (item) =>
1297
+ (item.Put?.Item?.sk as { S?: string } | undefined)?.S !== 'run',
1298
+ ),
1299
+ ),
1300
+ ).toBe(true);
1301
+ expect(
1302
+ new Set(
1303
+ transport.transactionCalls.map(
1304
+ ({ TransactItems }) =>
1305
+ (TransactItems?.[1]?.Put?.Item?.sk as
1306
+ | { S?: string }
1307
+ | undefined)?.S,
1308
+ ),
1309
+ ).size,
1310
+ ).toBe(SERVICE_PER_TASK_CONFIGURED_MAXIMUM);
1311
+ expect(transport.snapshot().map(({ key }) => key)).toEqual([
1312
+ ...Array.from(
1313
+ { length: SERVICE_PER_TASK_CONFIGURED_MAXIMUM },
1314
+ (_, index) =>
1315
+ 'plan#' + 'e'.repeat(64) + '|request#' + (index + 1),
1316
+ ).sort(),
1317
+ 'plan#' + 'e'.repeat(64) + '|run',
1318
+ ].sort());
1319
+ });
1320
+
1321
+ it('atomically binds one immutable run and rejects replay or cross-pair substitution', async () => {
1322
+ const transport = new FakeDynamoTransactions();
1323
+ const store = createServicePerformanceReservationStore({
1324
+ tableName: 'performance-reservations',
1325
+ transport,
1326
+ });
1327
+ const execute = authorization('execute');
1328
+ await expect(
1329
+ store.reserve({
1330
+ ...execute,
1331
+ configuredMaximum: SERVICE_PER_TASK_CONFIGURED_MAXIMUM + 1,
1332
+ }),
1333
+ ).rejects.toThrow('protected-performance-service-authorization-mismatch');
1334
+ await expect(
1335
+ store.reserve({
1336
+ ...execute,
1337
+ saturationSignalRef: 'runtime:substituted-signal',
1338
+ }),
1339
+ ).rejects.toThrow('protected-performance-service-authorization-mismatch');
1340
+ expect(transport.snapshot()).toEqual([]);
1341
+ await expect(store.reserve(execute)).resolves.toBe('claimed');
1342
+ const afterClaim = transport.snapshot();
1343
+ await expect(store.reserve(execute)).rejects.toThrow(
1344
+ 'fake-dynamo-request-replayed',
1345
+ );
1346
+ expect(transport.snapshot()).toEqual(afterClaim);
1347
+
1348
+ const substitutedCleanup = {
1349
+ ...authorization('cleanup'),
1350
+ release: {
1351
+ ...authorization('cleanup').release,
1352
+ releaseMaterialDigest: 'f'.repeat(64),
1353
+ },
1354
+ runId: 'other-service-run',
1355
+ };
1356
+ await expect(store.cleanup(substitutedCleanup)).rejects.toThrow(
1357
+ 'protected-performance-service-run-collision',
1358
+ );
1359
+ expect(transport.snapshot()).toEqual(afterClaim);
1360
+
1361
+ const cleanup = authorization('cleanup');
1362
+ await expect(store.cleanup(cleanup)).resolves.toEqual({
1363
+ remainingEffectCount: 0,
1364
+ removedEffectCount: 0,
1365
+ });
1366
+ const afterCleanup = transport.snapshot();
1367
+ await expect(store.cleanup(cleanup)).resolves.toEqual({
1368
+ remainingEffectCount: 0,
1369
+ removedEffectCount: 0,
1370
+ });
1371
+ expect(transport.snapshot()).toEqual(afterCleanup);
1372
+ await expect(
1373
+ store.reserve({ ...execute, requestOrdinal: 2 }),
1374
+ ).rejects.toThrow('fake-dynamo-conditional-check-failed');
1375
+ });
1376
+
1377
+ it('tombstones cleanup before the first request and recovers after a process crash', async () => {
1378
+ const beforeFirstTransport = new FakeDynamoTransactions();
1379
+ const beforeFirst = createServicePerformanceReservationStore({
1380
+ tableName: 'performance-reservations',
1381
+ transport: beforeFirstTransport,
1382
+ });
1383
+ await expect(beforeFirst.cleanup(authorization('cleanup'))).resolves.toEqual({
1384
+ remainingEffectCount: 0,
1385
+ removedEffectCount: 0,
1386
+ });
1387
+ await expect(beforeFirst.reserve(authorization('execute'))).rejects.toThrow(
1388
+ 'fake-dynamo-conditional-check-failed',
1389
+ );
1390
+
1391
+ const crashTransport = new FakeDynamoTransactions();
1392
+ const beforeCrash = createServicePerformanceReservationStore({
1393
+ tableName: 'performance-reservations',
1394
+ transport: crashTransport,
1395
+ });
1396
+ await beforeCrash.reserve(authorization('execute'));
1397
+ const afterRestart = createServicePerformanceReservationStore({
1398
+ tableName: 'performance-reservations',
1399
+ transport: crashTransport,
1400
+ });
1401
+ await expect(afterRestart.cleanup(authorization('cleanup'))).resolves.toEqual({
1402
+ remainingEffectCount: 0,
1403
+ removedEffectCount: 0,
1404
+ });
1405
+ expect(crashTransport.snapshot().map(({ key }) => key)).toEqual([
1406
+ 'plan#' + 'e'.repeat(64) + '|cleanup',
1407
+ 'plan#' + 'e'.repeat(64) + '|request#1',
1408
+ 'plan#' + 'e'.repeat(64) + '|run',
1409
+ ]);
1410
+ });
1411
+
1412
+ it('linearizes concurrent reserve and cleanup transactions in either order', async () => {
1413
+ const reserveFirstTransport = new GatedConflictTransactions('reserve');
1414
+ const reserveFirst = createServicePerformanceReservationStore({
1415
+ tableName: 'performance-reservations',
1416
+ transport: reserveFirstTransport,
1417
+ });
1418
+ await expect(
1419
+ Promise.all([
1420
+ reserveFirst.reserve(authorization('execute')),
1421
+ reserveFirst.cleanup(authorization('cleanup')),
1422
+ ]),
1423
+ ).resolves.toEqual([
1424
+ 'claimed',
1425
+ { remainingEffectCount: 0, removedEffectCount: 0 },
1426
+ ]);
1427
+ expect(reserveFirstTransport.tokens).toHaveLength(3);
1428
+ const cleanupTokens = reserveFirstTransport.tokens.filter(
1429
+ ({ operation }) => operation === 'cleanup',
1430
+ );
1431
+ expect(cleanupTokens).toHaveLength(2);
1432
+ expect(cleanupTokens[0]?.token).toBe(cleanupTokens[1]?.token);
1433
+ await expect(
1434
+ reserveFirst.reserve({ ...authorization('execute'), requestOrdinal: 2 }),
1435
+ ).rejects.toThrow('fake-dynamo-conditional-check-failed');
1436
+
1437
+ const cleanupFirstTransport = new GatedConflictTransactions('cleanup');
1438
+ const cleanupFirst = createServicePerformanceReservationStore({
1439
+ tableName: 'performance-reservations',
1440
+ transport: cleanupFirstTransport,
1441
+ });
1442
+ const results = await Promise.allSettled([
1443
+ cleanupFirst.cleanup(authorization('cleanup')),
1444
+ cleanupFirst.reserve(authorization('execute')),
1445
+ ]);
1446
+ expect(results.map(({ status }) => status)).toEqual([
1447
+ 'fulfilled',
1448
+ 'rejected',
1449
+ ]);
1450
+ expect(cleanupFirstTransport.tokens).toHaveLength(3);
1451
+ const reserveTokens = cleanupFirstTransport.tokens.filter(
1452
+ ({ operation }) => operation === 'reserve',
1453
+ );
1454
+ expect(reserveTokens).toHaveLength(2);
1455
+ expect(reserveTokens[0]?.token).toBe(reserveTokens[1]?.token);
1456
+ });
1457
+
1458
+ it('retries only AWS transaction conflicts with one stable idempotency token', async () => {
1459
+ const conflict = new OneShotCancellationTransactions([
1460
+ 'None',
1461
+ 'TransactionConflict',
1462
+ 'None',
1463
+ ]);
1464
+ const conflictStore = createServicePerformanceReservationStore({
1465
+ tableName: 'performance-reservations',
1466
+ transport: conflict,
1467
+ });
1468
+ await expect(
1469
+ conflictStore.reserve(authorization('execute')),
1470
+ ).resolves.toBe('claimed');
1471
+ expect(conflict.tokens).toHaveLength(2);
1472
+ expect(conflict.tokens[0]).toBe(conflict.tokens[1]);
1473
+
1474
+ for (const reasonCodes of [
1475
+ ['None', 'ConditionalCheckFailed', 'None'],
1476
+ ['TransactionConflict', 'ProvisionedThroughputExceeded', 'None'],
1477
+ ]) {
1478
+ const rejected = new OneShotCancellationTransactions(reasonCodes);
1479
+ const rejectedStore = createServicePerformanceReservationStore({
1480
+ tableName: 'performance-reservations',
1481
+ transport: rejected,
1482
+ });
1483
+ await expect(
1484
+ rejectedStore.reserve(authorization('execute')),
1485
+ ).rejects.toMatchObject({ name: 'TransactionCanceledException' });
1486
+ expect(rejected.tokens).toHaveLength(1);
1487
+ }
1488
+ });
1489
+
1490
+ it('enforces the exact per-task admission maximum and signal', async () => {
1491
+ const releases: Array<() => void> = [];
1492
+ const perform = vi.fn(
1493
+ () => new Promise<void>((resolve) => releases.push(resolve)),
1494
+ );
1495
+ const execute = createProtectedServicePerformanceExecutor({ perform });
1496
+ const base = {
1497
+ ...authorization('execute'),
1498
+ maximumRequests: SERVICE_PER_TASK_CONFIGURED_MAXIMUM + 1,
1499
+ };
1500
+ const active = Array.from(
1501
+ { length: SERVICE_PER_TASK_CONFIGURED_MAXIMUM },
1502
+ (_, index) =>
1503
+ execute({
1504
+ authorization: { ...base, requestOrdinal: index + 1 },
1505
+ requestOrdinal: index + 1,
1506
+ }),
1507
+ );
1508
+ expect(releases).toHaveLength(SERVICE_PER_TASK_CONFIGURED_MAXIMUM);
1509
+ await expect(
1510
+ execute({
1511
+ authorization: {
1512
+ ...base,
1513
+ requestOrdinal: SERVICE_PER_TASK_CONFIGURED_MAXIMUM + 1,
1514
+ },
1515
+ requestOrdinal: SERVICE_PER_TASK_CONFIGURED_MAXIMUM + 1,
1516
+ }),
1517
+ ).rejects.toThrow('protected-performance-service-capacity-refused');
1518
+ releases.forEach((release) => release());
1519
+ const telemetry = await Promise.all(active);
1520
+ expect(Math.max(...telemetry.map(({ saturationPercent }) =>
1521
+ saturationPercent))).toBe(100);
1522
+
1523
+ const rejectedPerform = vi.fn(async () => undefined);
1524
+ const exactExecutor = createProtectedServicePerformanceExecutor({
1525
+ perform: rejectedPerform,
1526
+ });
1527
+ await expect(
1528
+ exactExecutor({
1529
+ authorization: {
1530
+ ...authorization('execute'),
1531
+ configuredMaximum: SERVICE_PER_TASK_CONFIGURED_MAXIMUM + 1,
1532
+ },
1533
+ requestOrdinal: 1,
1534
+ }),
1535
+ ).rejects.toThrow('protected-performance-service-authorization-mismatch');
1536
+ await expect(
1537
+ exactExecutor({
1538
+ authorization: {
1539
+ ...authorization('execute'),
1540
+ saturationSignalRef: 'runtime:substituted-signal',
1541
+ },
1542
+ requestOrdinal: 1,
1543
+ }),
1544
+ ).rejects.toThrow('protected-performance-service-authorization-mismatch');
1545
+ expect(rejectedPerform).not.toHaveBeenCalled();
1546
+ });
1547
+
1548
+ it('reports independent per-task utilization across two Service processes', async () => {
1549
+ let releaseFirst: () => void = () => undefined;
1550
+ let releaseSecond: () => void = () => undefined;
1551
+ const first = createProtectedServicePerformanceExecutor({
1552
+ perform: () => new Promise<void>((resolve) => {
1553
+ releaseFirst = () => resolve();
1554
+ }),
1555
+ });
1556
+ const second = createProtectedServicePerformanceExecutor({
1557
+ perform: () => new Promise<void>((resolve) => {
1558
+ releaseSecond = () => resolve();
1559
+ }),
1560
+ });
1561
+ const request = {
1562
+ authorization: authorization('execute'),
1563
+ requestOrdinal: 1,
1564
+ };
1565
+ const firstResult = first(request);
1566
+ const secondResult = second(request);
1567
+ releaseFirst();
1568
+ releaseSecond();
1569
+ await expect(Promise.all([firstResult, secondResult])).resolves.toEqual([
1570
+ { saturationPercent: 100 / SERVICE_PER_TASK_CONFIGURED_MAXIMUM },
1571
+ { saturationPercent: 100 / SERVICE_PER_TASK_CONFIGURED_MAXIMUM },
1572
+ ]);
1573
+ expect(SERVICE_PER_TASK_SATURATION_SIGNAL_REF).toContain('per-task');
1574
+ });
1575
+
1576
+ it('probes the deployed Service default when PORT is absent', async () => {
1577
+ const previousPort = process.env.PORT;
1578
+ delete process.env.PORT;
1579
+ const healthProbe = vi.fn(async () => ({
1580
+ body: { service: '${input.workload}', status: 'ok' },
1581
+ statusCode: 200,
1582
+ }));
1583
+ try {
1584
+ await expect(
1585
+ performLocalServicePerformanceProbe(
1586
+ authorization('execute'),
1587
+ healthProbe,
1588
+ ),
1589
+ ).resolves.toBeUndefined();
1590
+ expect(healthProbe).toHaveBeenCalledTimes(1);
1591
+ expect(healthProbe).toHaveBeenCalledWith(DEFAULT_SERVICE_PORT);
1592
+ } finally {
1593
+ if (previousPort === undefined) delete process.env.PORT;
1594
+ else process.env.PORT = previousPort;
1595
+ }
1596
+ });
1597
+
1598
+ it('serves a signed request through the generated Node Service route', async () => {
1599
+ const handler = createProtectedServicePerformanceHandler({
1600
+ cleanup: async () => ({
1601
+ remainingEffectCount: 0,
1602
+ removedEffectCount: 0,
1603
+ }),
1604
+ execute: async () => ({ saturationPercent: 25 }),
1605
+ now: () => new Date('2026-08-01T12:30:00.000Z'),
1606
+ reserve: async () => 'claimed',
1607
+ withBinding: (requestOrigin, operation) => {
1608
+ expect(requestOrigin).toBe(binding.target.origin);
1609
+ return operation(binding);
1610
+ },
1611
+ });
1612
+ const previousPort = process.env.PORT;
1613
+ const previousIngressProof = process.env.EBK_PERFORMANCE_INGRESS_PROOF;
1614
+ const previousOrigin = process.env.EBK_PERFORMANCE_ORIGIN;
1615
+ process.env.PORT = '0';
1616
+ process.env.EBK_PERFORMANCE_INGRESS_PROOF = ingressProof;
1617
+ process.env.EBK_PERFORMANCE_ORIGIN = binding.target.origin;
1618
+ const server = await start(
1619
+ createLogger({
1620
+ component: 'service-${input.workload}',
1621
+ feature: 'performance',
1622
+ operation: 'serve',
1623
+ sink: () => undefined,
1624
+ slice: '${input.slice}',
1625
+ stage: 'test',
1626
+ workspace: 'generated-service-test',
1627
+ }),
1628
+ (request, response) =>
1629
+ serveProtectedServicePerformanceRequest(
1630
+ request,
1631
+ response,
1632
+ handler,
1633
+ ),
1634
+ );
1635
+ try {
1636
+ if (!server.listening) await once(server, 'listening');
1637
+ const address = server.address();
1638
+ if (!address || typeof address === 'string') {
1639
+ throw new Error('Generated Service did not bind a TCP port.');
1640
+ }
1641
+ process.env.PORT = String(address.port);
1642
+ await expect(
1643
+ performLocalServicePerformanceProbe(authorization('execute')),
1644
+ ).resolves.toBeUndefined();
1645
+ const signed = signedRequest('execute');
1646
+ const response = await new Promise<{
1647
+ body: unknown;
1648
+ cacheControl: string | undefined;
1649
+ status: number | undefined;
1650
+ }>((resolve, reject) => {
1651
+ const request = httpRequest({
1652
+ headers: {
1653
+ ...Object.fromEntries(signed.headers.entries()),
1654
+ host: 'untrusted-proxy.invalid',
1655
+ 'x-ebk-router-origin-proof': ingressProof,
1656
+ 'x-forwarded-proto': 'http',
1657
+ },
1658
+ hostname: '127.0.0.1',
1659
+ method: 'GET',
1660
+ path: '${executePath}',
1661
+ port: address.port,
1662
+ }, (incoming) => {
1663
+ const chunks: Uint8Array[] = [];
1664
+ incoming.on('data', (chunk: Uint8Array) => chunks.push(chunk));
1665
+ incoming.once('error', reject);
1666
+ incoming.once('end', () => resolve({
1667
+ body: JSON.parse(Buffer.concat(chunks).toString('utf8')),
1668
+ cacheControl: incoming.headers['cache-control'],
1669
+ status: incoming.statusCode,
1670
+ }));
1671
+ });
1672
+ request.once('error', reject);
1673
+ request.end();
1674
+ });
1675
+ expect(response.status).toBe(200);
1676
+ expect(response.cacheControl).toBe('no-store');
1677
+ expect(response.body).toMatchObject({
1678
+ kind: 'ebk-protected-load-telemetry',
1679
+ saturation: { percent: 25 },
1680
+ });
1681
+ } finally {
1682
+ await new Promise<void>((resolve, reject) =>
1683
+ server.close((error) => (error ? reject(error) : resolve())),
1684
+ );
1685
+ if (previousPort === undefined) delete process.env.PORT;
1686
+ else process.env.PORT = previousPort;
1687
+ if (previousIngressProof === undefined) {
1688
+ delete process.env.EBK_PERFORMANCE_INGRESS_PROOF;
1689
+ } else {
1690
+ process.env.EBK_PERFORMANCE_INGRESS_PROOF = previousIngressProof;
1691
+ }
1692
+ if (previousOrigin === undefined) delete process.env.EBK_PERFORMANCE_ORIGIN;
1693
+ else process.env.EBK_PERFORMANCE_ORIGIN = previousOrigin;
1694
+ }
1695
+ });
1696
+
1697
+ it('executes the signed Service request and exact run cleanup endpoints', async () => {
1698
+ const reserve = vi.fn(async () => 'claimed' as const);
1699
+ const cleanup = vi.fn(async () => ({
1700
+ remainingEffectCount: 0,
1701
+ removedEffectCount: 0,
1702
+ }));
1703
+ const handler = createProtectedServicePerformanceHandler({
1704
+ cleanup,
1705
+ execute: async ({ authorization: requestAuthorization }) => ({
1706
+ saturationPercent: 100 / requestAuthorization.configuredMaximum,
1707
+ }),
1708
+ now: () => new Date('2026-08-01T12:30:00.000Z'),
1709
+ reserve,
1710
+ withBinding: (_requestOrigin, operation) => operation(binding),
1711
+ });
1712
+
1713
+ const execution = await handler(signedRequest('execute'));
1714
+ expect(execution.status).toBe(200);
1715
+ await expect(execution.json()).resolves.toMatchObject({
1716
+ kind: 'ebk-protected-load-telemetry',
1717
+ saturation: {
1718
+ percent: 100 / SERVICE_PER_TASK_CONFIGURED_MAXIMUM,
1719
+ signalRef: SERVICE_PER_TASK_SATURATION_SIGNAL_REF,
1720
+ },
1721
+ workload: 'service',
1722
+ });
1723
+ expect(reserve).toHaveBeenCalledOnce();
1724
+
1725
+ const cleaned = await handler(signedRequest('cleanup'));
1726
+ expect(cleaned.status).toBe(200);
1727
+ await expect(cleaned.json()).resolves.toMatchObject({
1728
+ kind: 'ebk-protected-load-cleanup-result',
1729
+ remainingEffectCount: 0,
1730
+ removedEffectCount: 0,
1731
+ status: 'run-absent',
1732
+ });
1733
+ expect(cleanup).toHaveBeenCalledOnce();
1734
+ });
1735
+
1736
+ it.each([
1737
+ 'https://substituted.example.test${executePath}',
1738
+ '//substituted.example.test${executePath}',
1739
+ '/${input.slice}\\\\__ebk/performance/service',
1740
+ ])('rejects a non-origin-form Node request target %s', async (url) => {
1741
+ const handler = vi.fn();
1742
+ const request = {
1743
+ headers: { 'x-ebk-router-origin-proof': ingressProof },
1744
+ method: 'GET',
1745
+ url,
1746
+ async *[Symbol.asyncIterator]() {},
1747
+ } as unknown as import('node:http').IncomingMessage;
1748
+ const response = {} as import('node:http').ServerResponse;
1749
+ const previousIngressProof = process.env.EBK_PERFORMANCE_INGRESS_PROOF;
1750
+ const previousOrigin = process.env.EBK_PERFORMANCE_ORIGIN;
1751
+ process.env.EBK_PERFORMANCE_INGRESS_PROOF = ingressProof;
1752
+ process.env.EBK_PERFORMANCE_ORIGIN = binding.target.origin;
1753
+ try {
1754
+ await expect(
1755
+ serveProtectedServicePerformanceRequest(request, response, handler),
1756
+ ).rejects.toThrow('protected-performance-endpoint-disabled');
1757
+ expect(handler).not.toHaveBeenCalled();
1758
+ } finally {
1759
+ if (previousIngressProof === undefined) {
1760
+ delete process.env.EBK_PERFORMANCE_INGRESS_PROOF;
1761
+ } else {
1762
+ process.env.EBK_PERFORMANCE_INGRESS_PROOF = previousIngressProof;
1763
+ }
1764
+ if (previousOrigin === undefined) delete process.env.EBK_PERFORMANCE_ORIGIN;
1765
+ else process.env.EBK_PERFORMANCE_ORIGIN = previousOrigin;
1766
+ }
1767
+ });
1768
+
1769
+ it('rejects a direct origin request without the Router-injected proof', async () => {
1770
+ const handler = vi.fn();
1771
+ const request = {
1772
+ headers: {},
1773
+ method: 'GET',
1774
+ url: '${executePath}',
1775
+ async *[Symbol.asyncIterator]() {},
1776
+ } as unknown as import('node:http').IncomingMessage;
1777
+ const response = {} as import('node:http').ServerResponse;
1778
+ const previousIngressProof = process.env.EBK_PERFORMANCE_INGRESS_PROOF;
1779
+ const previousOrigin = process.env.EBK_PERFORMANCE_ORIGIN;
1780
+ process.env.EBK_PERFORMANCE_INGRESS_PROOF = ingressProof;
1781
+ process.env.EBK_PERFORMANCE_ORIGIN = binding.target.origin;
1782
+ try {
1783
+ await expect(
1784
+ serveProtectedServicePerformanceRequest(request, response, handler),
1785
+ ).rejects.toThrow('protected-performance-endpoint-disabled');
1786
+ expect(handler).not.toHaveBeenCalled();
1787
+ } finally {
1788
+ if (previousIngressProof === undefined) {
1789
+ delete process.env.EBK_PERFORMANCE_INGRESS_PROOF;
1790
+ } else {
1791
+ process.env.EBK_PERFORMANCE_INGRESS_PROOF = previousIngressProof;
1792
+ }
1793
+ if (previousOrigin === undefined) delete process.env.EBK_PERFORMANCE_ORIGIN;
1794
+ else process.env.EBK_PERFORMANCE_ORIGIN = previousOrigin;
1795
+ }
1796
+ });
1797
+
1798
+ it('fails closed before callbacks for a substituted release or effect body', async () => {
1799
+ const reserve = vi.fn(async () => 'claimed' as const);
1800
+ const cleanup = vi.fn(async () => ({
1801
+ remainingEffectCount: 0,
1802
+ removedEffectCount: 0,
1803
+ }));
1804
+ const handler = createProtectedServicePerformanceHandler({
1805
+ cleanup,
1806
+ execute: async () => ({ saturationPercent: 1 }),
1807
+ now: () => new Date('2026-08-01T12:30:00.000Z'),
1808
+ reserve,
1809
+ withBinding: (_requestOrigin, operation) => operation(binding),
1810
+ });
1811
+ const substituted = signedRequest('execute');
1812
+ substituted.headers.set('x-ebk-performance-release-id', 'other-release');
1813
+ expect((await handler(substituted)).status).toBe(404);
1814
+
1815
+ const cleanupMaterial = authorization('cleanup');
1816
+ const cleanupRequest = signedRequest('cleanup');
1817
+ const body = JSON.parse(await cleanupRequest.text()) as Record<string, unknown>;
1818
+ const effectRequest = new Request(cleanupMaterial.target.endpoint, {
1819
+ body: JSON.stringify({ ...body, effectId: 'f'.repeat(64) }),
1820
+ headers: cleanupRequest.headers,
1821
+ method: 'POST',
1822
+ });
1823
+ expect((await handler(effectRequest)).status).toBe(404);
1824
+ expect(reserve).not.toHaveBeenCalled();
1825
+ expect(cleanup).not.toHaveBeenCalled();
1826
+ });
1827
+ });
1828
+ `,
1829
+ [`services/${input.workload}/PERFORMANCE.md`]: `# Protected Service performance
1830
+
1831
+ The managed \`${input.workload}\` endpoint admits at most 32 concurrent protected
1832
+ performance requests in each generated Service process. The
1833
+ \`runtime:service-${input.workload}-per-task-concurrency-utilization-percent\`
1834
+ signal reports that per-task admission utilization only. It is not whole-fleet
1835
+ or application saturation evidence. The adopted performance policy must keep
1836
+ \`configuredMaximum\` at 32 while independently supplying and reviewing the
1837
+ downstream and quota ceilings before protected load can run.
1838
+
1839
+ Each admitted request executes the Service's real local \`GET /health\` codepath.
1840
+ The DynamoDB reservation transaction binds one immutable run identity, rejects
1841
+ replayed ordinals, and creates an idempotent cleanup tombstone that blocks every
1842
+ late request for that exact plan digest.
1843
+ `,
1844
+ };
1845
+ }
1846
+ //# sourceMappingURL=service-performance-files.js.map