@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,2656 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderProductApiContractFiles = renderProductApiContractFiles;
4
+ const api_contract_1 = require("@empire-builder-kit/runtime/api-contract");
5
+ const index_js_1 = require("../../api-contract/index.js");
6
+ const built_in_plan_shared_js_1 = require("./built-in-plan-shared.js");
7
+ function createStandardApiContract(name, pascalName) {
8
+ const authenticationProblems = [
9
+ {
10
+ code: 'auth_invalid_token',
11
+ message: 'The access token is invalid or expired.',
12
+ retryable: false,
13
+ status: 401,
14
+ type: 'https://empirebuilderkit.dev/problems/auth/invalid-token',
15
+ },
16
+ {
17
+ code: 'auth_unauthenticated',
18
+ message: 'Authentication is required.',
19
+ retryable: false,
20
+ status: 401,
21
+ type: 'https://empirebuilderkit.dev/problems/auth/unauthenticated',
22
+ },
23
+ ];
24
+ const authorizationProblems = [
25
+ ...authenticationProblems,
26
+ {
27
+ code: 'authorization_admission_required',
28
+ message: 'Required operation admission is missing.',
29
+ retryable: false,
30
+ status: 403,
31
+ type: 'https://empirebuilderkit.dev/problems/authorization/admission-required',
32
+ },
33
+ {
34
+ code: 'authorization_approval_required',
35
+ message: 'Approval is required.',
36
+ retryable: false,
37
+ status: 409,
38
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-required',
39
+ },
40
+ {
41
+ code: 'authorization_denied',
42
+ message: 'Authorization denied.',
43
+ retryable: false,
44
+ status: 403,
45
+ type: 'https://empirebuilderkit.dev/problems/authorization/denied',
46
+ },
47
+ {
48
+ code: 'authorization_input_invalid',
49
+ message: 'Authorization input is invalid.',
50
+ retryable: false,
51
+ status: 403,
52
+ type: 'https://empirebuilderkit.dev/problems/authorization/input-invalid',
53
+ },
54
+ {
55
+ code: 'authorization_policy_stale',
56
+ message: 'Authorization policy is not current.',
57
+ retryable: true,
58
+ status: 503,
59
+ type: 'https://empirebuilderkit.dev/problems/authorization/policy-stale',
60
+ },
61
+ {
62
+ code: 'authorization_unavailable',
63
+ message: 'Authorization is temporarily unavailable.',
64
+ retryable: true,
65
+ status: 503,
66
+ type: 'https://empirebuilderkit.dev/problems/authorization/unavailable',
67
+ },
68
+ ];
69
+ const recordConflictProblems = [
70
+ ...authorizationProblems,
71
+ {
72
+ code: 'record_conflict',
73
+ message: 'The record identifier is owned by another principal.',
74
+ retryable: false,
75
+ status: 409,
76
+ type: 'https://empirebuilderkit.dev/problems/records/conflict',
77
+ },
78
+ {
79
+ code: 'record_correction_retry_required',
80
+ message: 'Record correction propagation requires retry.',
81
+ retryable: true,
82
+ status: 503,
83
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/correction-retry-required',
84
+ },
85
+ {
86
+ code: 'test_data_expiry_invalid',
87
+ message: 'Test data expiry must be a canonical future timestamp within 48 hours.',
88
+ retryable: false,
89
+ status: 400,
90
+ type: 'https://empirebuilderkit.dev/problems/testing/expiry-invalid',
91
+ },
92
+ ];
93
+ const recordNotFoundProblems = [
94
+ ...authorizationProblems,
95
+ {
96
+ code: 'record_not_found',
97
+ message: 'The record was not found.',
98
+ retryable: false,
99
+ status: 404,
100
+ type: 'https://empirebuilderkit.dev/problems/records/not-found',
101
+ },
102
+ ];
103
+ const delegationProblems = [
104
+ ...authorizationProblems,
105
+ {
106
+ code: 'authorization_delegation_expired',
107
+ message: 'Delegated authority has expired.',
108
+ retryable: false,
109
+ status: 403,
110
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-expired',
111
+ },
112
+ {
113
+ code: 'authorization_delegation_out_of_bounds',
114
+ message: 'Delegated authority does not cover this request.',
115
+ retryable: false,
116
+ status: 403,
117
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-out-of-bounds',
118
+ },
119
+ {
120
+ code: 'authorization_delegation_rate_limited',
121
+ message: 'Delegated authority use limit has been reached.',
122
+ retryable: false,
123
+ status: 429,
124
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-rate-limited',
125
+ },
126
+ {
127
+ code: 'authorization_delegation_revoked',
128
+ message: 'Delegated authority has been revoked.',
129
+ retryable: false,
130
+ status: 403,
131
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-revoked',
132
+ },
133
+ ];
134
+ const delegatedRecordProblems = [
135
+ ...delegationProblems,
136
+ {
137
+ code: 'record_not_found',
138
+ message: 'The record was not found.',
139
+ retryable: false,
140
+ status: 404,
141
+ type: 'https://empirebuilderkit.dev/problems/records/not-found',
142
+ },
143
+ ];
144
+ const deletionProblems = [
145
+ ...recordNotFoundProblems,
146
+ {
147
+ code: 'authorization_approval_expired',
148
+ message: 'Approval has expired.',
149
+ retryable: false,
150
+ status: 409,
151
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-expired',
152
+ },
153
+ {
154
+ code: 'authorization_approval_invalid',
155
+ message: 'Approval is not valid for this request.',
156
+ retryable: false,
157
+ status: 409,
158
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-invalid',
159
+ },
160
+ {
161
+ code: 'authorization_approval_pending',
162
+ message: 'Approval is pending.',
163
+ retryable: false,
164
+ status: 409,
165
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-pending',
166
+ },
167
+ {
168
+ code: 'data_deletion_held',
169
+ message: 'Deletion is blocked by an active hold.',
170
+ retryable: false,
171
+ status: 409,
172
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/deletion-held',
173
+ },
174
+ {
175
+ code: 'data_deletion_retry_required',
176
+ message: 'Deletion propagation requires retry.',
177
+ retryable: true,
178
+ status: 503,
179
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/deletion-retry-required',
180
+ },
181
+ ];
182
+ const dataRightsProblems = [
183
+ ...recordNotFoundProblems,
184
+ {
185
+ code: 'data_export_expired',
186
+ message: 'The confidential export has expired.',
187
+ retryable: false,
188
+ status: 410,
189
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-expired',
190
+ },
191
+ {
192
+ code: 'data_export_held',
193
+ message: 'An active hold blocks the confidential export.',
194
+ retryable: false,
195
+ status: 409,
196
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-held',
197
+ },
198
+ {
199
+ code: 'data_export_not_ready',
200
+ message: 'The confidential export is not ready.',
201
+ retryable: false,
202
+ status: 409,
203
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-not-ready',
204
+ },
205
+ {
206
+ code: 'data_export_rate_limited',
207
+ message: 'The bounded confidential export rate was exceeded.',
208
+ retryable: false,
209
+ status: 429,
210
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-rate-limited',
211
+ },
212
+ {
213
+ code: 'data_export_retry_required',
214
+ message: 'Confidential export processing requires retry.',
215
+ retryable: true,
216
+ status: 503,
217
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-retry-required',
218
+ },
219
+ {
220
+ code: 'data_rights_input_invalid',
221
+ message: 'The data-rights request is invalid.',
222
+ retryable: false,
223
+ status: 400,
224
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/input-invalid',
225
+ },
226
+ {
227
+ code: 'record_hold_invalid',
228
+ message: 'The record hold cannot make the requested transition.',
229
+ retryable: false,
230
+ status: 409,
231
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/hold-invalid',
232
+ },
233
+ ];
234
+ const retentionProblems = [
235
+ {
236
+ code: 'data_retention_approval_invalid',
237
+ message: 'The retention approval is invalid for this report.',
238
+ retryable: false,
239
+ status: 409,
240
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-approval-invalid',
241
+ },
242
+ {
243
+ code: 'data_retention_input_invalid',
244
+ message: 'The retention review request is invalid.',
245
+ retryable: false,
246
+ status: 400,
247
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-input-invalid',
248
+ },
249
+ {
250
+ code: 'data_retention_not_reviewable',
251
+ message: 'The retention report is no longer reviewable.',
252
+ retryable: false,
253
+ status: 409,
254
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-not-reviewable',
255
+ },
256
+ {
257
+ code: 'data_retention_report_not_found',
258
+ message: 'The retention report was not found.',
259
+ retryable: false,
260
+ status: 404,
261
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-report-not-found',
262
+ },
263
+ {
264
+ code: 'data_retention_retry_required',
265
+ message: 'Retention review persistence requires retry.',
266
+ retryable: true,
267
+ status: 503,
268
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-retry-required',
269
+ },
270
+ ];
271
+ const recordPath = () => (0, api_contract_1.apiObject)({
272
+ recordId: (0, api_contract_1.apiString)({ format: 'uuid' }),
273
+ });
274
+ const deletionRequestPath = () => (0, api_contract_1.apiObject)({
275
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
276
+ recordId: (0, api_contract_1.apiString)({ format: 'uuid' }),
277
+ });
278
+ const delegationPath = () => (0, api_contract_1.apiObject)({
279
+ delegationId: (0, api_contract_1.apiString)({ format: 'uuid' }),
280
+ recordId: (0, api_contract_1.apiString)({ format: 'uuid' }),
281
+ });
282
+ const exportPath = () => (0, api_contract_1.apiObject)({
283
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
284
+ recordId: (0, api_contract_1.apiString)({ format: 'uuid' }),
285
+ });
286
+ const holdPath = () => (0, api_contract_1.apiObject)({
287
+ holdId: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 1 }),
288
+ recordId: (0, api_contract_1.apiString)({ format: 'uuid' }),
289
+ });
290
+ const retentionApprovalPath = () => (0, api_contract_1.apiObject)({
291
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
292
+ runId: (0, api_contract_1.apiString)({ format: 'uuid' }),
293
+ });
294
+ const retentionRunPath = () => (0, api_contract_1.apiObject)({
295
+ runId: (0, api_contract_1.apiString)({ format: 'uuid' }),
296
+ });
297
+ const recordResponse = () => (0, api_contract_1.apiObject)({
298
+ id: (0, api_contract_1.apiString)({ format: 'uuid' }),
299
+ name: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
300
+ runScope: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
301
+ });
302
+ const holdResponse = () => (0, api_contract_1.apiObject)({
303
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
304
+ holdId: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 1 }),
305
+ reviewAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
306
+ status: (0, api_contract_1.apiString)({ enum: ['active', 'released'] }),
307
+ });
308
+ const health = (0, api_contract_1.defineApiOperation)({
309
+ authentication: 'anonymous',
310
+ authorizationActions: [],
311
+ contractVersion: '1.0.0',
312
+ feature: 'operations',
313
+ lifecycle: { status: 'active' },
314
+ method: 'GET',
315
+ operationId: `${name}.health`,
316
+ path: '/health',
317
+ problems: [],
318
+ response: {
319
+ body: (0, api_contract_1.apiObject)({
320
+ service: (0, api_contract_1.apiString)({ enum: [name] }),
321
+ sourceCommit: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 1 }),
322
+ stage: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 1 }),
323
+ status: (0, api_contract_1.apiString)({ enum: ['ok'] }),
324
+ }),
325
+ status: 200,
326
+ },
327
+ responseProfile: 'ebk-app-v1',
328
+ slice: name,
329
+ summary: `Read ${pascalName} API health`,
330
+ });
331
+ const machineAuthorizationProof = (0, api_contract_1.defineApiOperation)({
332
+ authentication: 'customer',
333
+ authorizationActions: [`${name}:machine-proof-read`],
334
+ contractVersion: '1.0.0',
335
+ feature: 'authorization',
336
+ lifecycle: { status: 'active' },
337
+ method: 'GET',
338
+ operationId: `${name}.machine-authorization-proof`,
339
+ path: '/authorization/machine-proof',
340
+ problems: authorizationProblems,
341
+ response: {
342
+ body: (0, api_contract_1.apiObject)({
343
+ message: (0, api_contract_1.apiString)({
344
+ enum: ['Machine authorization accepted.'],
345
+ }),
346
+ }),
347
+ status: 200,
348
+ },
349
+ responseProfile: 'ebk-app-v1',
350
+ slice: name,
351
+ summary: `Prove narrow ${pascalName} machine authorization`,
352
+ });
353
+ const issueRecordDelegation = (0, api_contract_1.defineApiOperation)({
354
+ authentication: 'customer',
355
+ authorizationActions: [`${name}:record-delegation-issue`],
356
+ contractVersion: '1.0.0',
357
+ feature: 'authorization',
358
+ lifecycle: { status: 'active' },
359
+ method: 'POST',
360
+ operationId: `${name}.issue-record-delegation`,
361
+ path: '/records/{recordId}/delegations',
362
+ problems: authorizationProblems,
363
+ request: {
364
+ body: (0, api_contract_1.apiObject)({
365
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
366
+ purposeReference: (0, api_contract_1.apiString)({ maxLength: 256, minLength: 1 }),
367
+ }),
368
+ maxBodyBytes: 512,
369
+ path: recordPath(),
370
+ },
371
+ response: {
372
+ body: (0, api_contract_1.apiObject)({
373
+ capability: (0, api_contract_1.apiString)({ maxLength: 43, minLength: 43 }),
374
+ delegationId: (0, api_contract_1.apiString)({ format: 'uuid' }),
375
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
376
+ status: (0, api_contract_1.apiString)({ enum: ['active'] }),
377
+ }),
378
+ status: 201,
379
+ },
380
+ responseProfile: 'ebk-app-v1',
381
+ slice: name,
382
+ summary: `Issue one attended ${pascalName} record delegation`,
383
+ });
384
+ const revokeRecordDelegation = (0, api_contract_1.defineApiOperation)({
385
+ authentication: 'customer',
386
+ authorizationActions: [`${name}:record-delegation-revoke`],
387
+ contractVersion: '1.0.0',
388
+ feature: 'authorization',
389
+ lifecycle: { status: 'active' },
390
+ method: 'DELETE',
391
+ operationId: `${name}.revoke-record-delegation`,
392
+ path: '/records/{recordId}/delegations/{delegationId}',
393
+ problems: authorizationProblems,
394
+ request: { path: delegationPath() },
395
+ response: {
396
+ body: (0, api_contract_1.apiObject)({
397
+ delegationId: (0, api_contract_1.apiString)({ format: 'uuid' }),
398
+ status: (0, api_contract_1.apiString)({ enum: ['revoked'] }),
399
+ }),
400
+ status: 200,
401
+ },
402
+ responseProfile: 'ebk-app-v1',
403
+ slice: name,
404
+ summary: `Revoke one attended ${pascalName} record delegation`,
405
+ });
406
+ const useRecordDelegation = (0, api_contract_1.defineApiOperation)({
407
+ authentication: 'customer',
408
+ authorizationActions: [`${name}:record-delegation-use`],
409
+ contractVersion: '1.0.0',
410
+ feature: 'authorization',
411
+ lifecycle: { status: 'active' },
412
+ method: 'POST',
413
+ operationId: `${name}.use-record-delegation`,
414
+ path: '/records/{recordId}/delegations/{delegationId}/use',
415
+ problems: delegatedRecordProblems,
416
+ request: {
417
+ body: (0, api_contract_1.apiObject)({
418
+ capability: (0, api_contract_1.apiString)({ maxLength: 43, minLength: 43 }),
419
+ }),
420
+ maxBodyBytes: 256,
421
+ path: delegationPath(),
422
+ },
423
+ response: { body: recordResponse(), status: 200 },
424
+ responseProfile: 'ebk-app-v1',
425
+ slice: name,
426
+ summary: `Use one attended ${pascalName} record delegation`,
427
+ });
428
+ const requestRecordExport = (0, api_contract_1.defineApiOperation)({
429
+ authentication: 'customer',
430
+ authorizationActions: [`${name}:record-export`],
431
+ contractVersion: '1.0.0',
432
+ feature: 'data-lifecycle',
433
+ lifecycle: { status: 'active' },
434
+ method: 'POST',
435
+ operationId: `${name}.request-record-export`,
436
+ path: '/records/{recordId}/exports',
437
+ problems: dataRightsProblems,
438
+ request: { path: recordPath() },
439
+ response: {
440
+ body: (0, api_contract_1.apiObject)({
441
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
442
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
443
+ requestDigest: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 64 }),
444
+ status: (0, api_contract_1.apiString)({ enum: ['pending'] }),
445
+ }),
446
+ status: 202,
447
+ },
448
+ responseProfile: 'ebk-app-v1',
449
+ slice: name,
450
+ summary: `Request one subject-bound ${pascalName} record export`,
451
+ });
452
+ const decideRecordExport = (0, api_contract_1.defineApiOperation)({
453
+ authentication: 'customer',
454
+ authorizationActions: [`${name}:approval-review`],
455
+ contractVersion: '1.0.0',
456
+ feature: 'data-lifecycle',
457
+ lifecycle: { status: 'active' },
458
+ method: 'POST',
459
+ operationId: `${name}.decide-record-export`,
460
+ path: '/records/{recordId}/exports/{approvalRequestId}/decision',
461
+ problems: dataRightsProblems,
462
+ request: {
463
+ body: (0, api_contract_1.apiObject)({
464
+ expectedRequestDigest: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 64 }),
465
+ outcome: (0, api_contract_1.apiString)({ enum: ['approved', 'rejected'] }),
466
+ reasonReference: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
467
+ }),
468
+ maxBodyBytes: 512,
469
+ path: exportPath(),
470
+ },
471
+ response: {
472
+ body: (0, api_contract_1.apiObject)({
473
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
474
+ status: (0, api_contract_1.apiString)({ enum: ['approved', 'rejected'] }),
475
+ }),
476
+ status: 200,
477
+ },
478
+ responseProfile: 'ebk-app-v1',
479
+ slice: name,
480
+ summary: `Decide one ${pascalName} record export`,
481
+ });
482
+ const executeRecordExport = (0, api_contract_1.defineApiOperation)({
483
+ authentication: 'customer',
484
+ authorizationActions: [`${name}:record-export`],
485
+ contractVersion: '1.0.0',
486
+ feature: 'data-lifecycle',
487
+ lifecycle: { status: 'active' },
488
+ method: 'POST',
489
+ operationId: `${name}.execute-record-export`,
490
+ path: '/records/{recordId}/exports/{approvalRequestId}/execute',
491
+ problems: dataRightsProblems,
492
+ request: { path: exportPath() },
493
+ response: {
494
+ body: (0, api_contract_1.apiObject)({
495
+ artifactRef: (0, api_contract_1.apiOptional)((0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 })),
496
+ expiresAt: (0, api_contract_1.apiOptional)((0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 })),
497
+ status: (0, api_contract_1.apiString)({ enum: ['held', 'ready'] }),
498
+ }),
499
+ status: 200,
500
+ },
501
+ responseProfile: 'ebk-app-v1',
502
+ slice: name,
503
+ summary: `Execute one approved ${pascalName} record export`,
504
+ });
505
+ const deliverRecordExport = (0, api_contract_1.defineApiOperation)({
506
+ authentication: 'customer',
507
+ authorizationActions: [`${name}:record-export`],
508
+ contractVersion: '1.0.0',
509
+ feature: 'data-lifecycle',
510
+ lifecycle: { status: 'active' },
511
+ method: 'GET',
512
+ operationId: `${name}.deliver-record-export`,
513
+ path: '/records/{recordId}/exports/{approvalRequestId}/delivery',
514
+ problems: dataRightsProblems,
515
+ request: { path: exportPath() },
516
+ response: {
517
+ body: (0, api_contract_1.apiObject)({
518
+ artifactRef: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
519
+ deliveredAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
520
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
521
+ record: recordResponse(),
522
+ }),
523
+ status: 200,
524
+ },
525
+ responseProfile: 'ebk-app-v1',
526
+ slice: name,
527
+ summary: `Deliver one unexpired ${pascalName} record export`,
528
+ });
529
+ const cleanupRecordExport = (0, api_contract_1.defineApiOperation)({
530
+ authentication: 'customer',
531
+ authorizationActions: [`${name}:record-export-cleanup`],
532
+ contractVersion: '1.0.0',
533
+ feature: 'data-lifecycle',
534
+ lifecycle: { status: 'active' },
535
+ method: 'DELETE',
536
+ operationId: `${name}.cleanup-record-export`,
537
+ path: '/records/{recordId}/exports/{approvalRequestId}',
538
+ problems: dataRightsProblems,
539
+ request: { path: exportPath() },
540
+ response: {
541
+ body: (0, api_contract_1.apiObject)({
542
+ deletedVersions: (0, api_contract_1.apiNumber)({ integer: true, minimum: 0 }),
543
+ status: (0, api_contract_1.apiString)({
544
+ enum: ['completed', 'retry-required'],
545
+ }),
546
+ }),
547
+ status: 200,
548
+ },
549
+ responseProfile: 'ebk-app-v1',
550
+ slice: name,
551
+ summary: `Clean up one expired ${pascalName} record export`,
552
+ });
553
+ const requestRetentionApproval = (0, api_contract_1.defineApiOperation)({
554
+ authentication: 'customer',
555
+ authorizationActions: [`${name}:retention-review`],
556
+ contractVersion: '1.0.0',
557
+ feature: 'data-lifecycle',
558
+ lifecycle: { status: 'active' },
559
+ method: 'POST',
560
+ operationId: `${name}.request-retention-approval`,
561
+ path: '/data-retention/runs/{runId}/approval-requests',
562
+ problems: retentionProblems,
563
+ request: { path: retentionRunPath() },
564
+ response: {
565
+ body: (0, api_contract_1.apiObject)({
566
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
567
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
568
+ requestDigest: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 64 }),
569
+ status: (0, api_contract_1.apiString)({ enum: ['pending'] }),
570
+ }),
571
+ status: 202,
572
+ },
573
+ responseProfile: 'ebk-app-v1',
574
+ slice: name,
575
+ summary: `Request direct-admin review of one ${pascalName} retention report`,
576
+ });
577
+ const decideRetentionApproval = (0, api_contract_1.defineApiOperation)({
578
+ authentication: 'customer',
579
+ authorizationActions: [`${name}:retention-review`],
580
+ contractVersion: '1.0.0',
581
+ feature: 'data-lifecycle',
582
+ lifecycle: { status: 'active' },
583
+ method: 'POST',
584
+ operationId: `${name}.decide-retention-approval`,
585
+ path: '/data-retention/runs/{runId}/approval-requests/{approvalRequestId}/decision',
586
+ problems: retentionProblems,
587
+ request: {
588
+ body: (0, api_contract_1.apiObject)({
589
+ expectedRequestDigest: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 64 }),
590
+ outcome: (0, api_contract_1.apiString)({ enum: ['approved', 'rejected'] }),
591
+ reasonReference: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
592
+ }),
593
+ maxBodyBytes: 512,
594
+ path: retentionApprovalPath(),
595
+ },
596
+ response: {
597
+ body: (0, api_contract_1.apiObject)({
598
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
599
+ status: (0, api_contract_1.apiString)({ enum: ['approved', 'rejected'] }),
600
+ }),
601
+ status: 200,
602
+ },
603
+ responseProfile: 'ebk-app-v1',
604
+ slice: name,
605
+ summary: `Decide one ${pascalName} retention approval as a non-author admin`,
606
+ });
607
+ const issueRecordHold = (0, api_contract_1.defineApiOperation)({
608
+ authentication: 'customer',
609
+ authorizationActions: [`${name}:record-hold-manage`],
610
+ contractVersion: '1.0.0',
611
+ feature: 'data-lifecycle',
612
+ lifecycle: { status: 'active' },
613
+ method: 'POST',
614
+ operationId: `${name}.issue-record-hold`,
615
+ path: '/records/{recordId}/holds',
616
+ problems: dataRightsProblems,
617
+ request: {
618
+ body: (0, api_contract_1.apiObject)({
619
+ effects: (0, api_contract_1.apiArray)((0, api_contract_1.apiString)({
620
+ enum: ['block-deletion', 'block-export'],
621
+ }), { maxItems: 2, minItems: 1 }),
622
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
623
+ purpose: (0, api_contract_1.apiString)({
624
+ enum: ['fraud', 'incident', 'legal', 'security', 'support'],
625
+ }),
626
+ reviewAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
627
+ }),
628
+ maxBodyBytes: 512,
629
+ path: recordPath(),
630
+ },
631
+ response: { body: holdResponse(), status: 201 },
632
+ responseProfile: 'ebk-app-v1',
633
+ slice: name,
634
+ summary: `Issue one bounded ${pascalName} record hold`,
635
+ });
636
+ const reviewRecordHold = (0, api_contract_1.defineApiOperation)({
637
+ authentication: 'customer',
638
+ authorizationActions: [`${name}:record-hold-manage`],
639
+ contractVersion: '1.0.0',
640
+ feature: 'data-lifecycle',
641
+ lifecycle: { status: 'active' },
642
+ method: 'POST',
643
+ operationId: `${name}.review-record-hold`,
644
+ path: '/records/{recordId}/holds/{holdId}/review',
645
+ problems: dataRightsProblems,
646
+ request: {
647
+ body: (0, api_contract_1.apiObject)({
648
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
649
+ reviewAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
650
+ }),
651
+ maxBodyBytes: 256,
652
+ path: holdPath(),
653
+ },
654
+ response: { body: holdResponse(), status: 200 },
655
+ responseProfile: 'ebk-app-v1',
656
+ slice: name,
657
+ summary: `Review one bounded ${pascalName} record hold`,
658
+ });
659
+ const releaseRecordHold = (0, api_contract_1.defineApiOperation)({
660
+ authentication: 'customer',
661
+ authorizationActions: [`${name}:record-hold-manage`],
662
+ contractVersion: '1.0.0',
663
+ feature: 'data-lifecycle',
664
+ lifecycle: { status: 'active' },
665
+ method: 'DELETE',
666
+ operationId: `${name}.release-record-hold`,
667
+ path: '/records/{recordId}/holds/{holdId}',
668
+ problems: dataRightsProblems,
669
+ request: { path: holdPath() },
670
+ response: { body: holdResponse(), status: 200 },
671
+ responseProfile: 'ebk-app-v1',
672
+ slice: name,
673
+ summary: `Release one bounded ${pascalName} record hold`,
674
+ });
675
+ const expireRecordHold = (0, api_contract_1.defineApiOperation)({
676
+ authentication: 'customer',
677
+ authorizationActions: [`${name}:record-hold-manage`],
678
+ contractVersion: '1.0.0',
679
+ feature: 'data-lifecycle',
680
+ lifecycle: { status: 'active' },
681
+ method: 'POST',
682
+ operationId: `${name}.expire-record-hold`,
683
+ path: '/records/{recordId}/holds/{holdId}/expire',
684
+ problems: dataRightsProblems,
685
+ request: { path: holdPath() },
686
+ response: { body: holdResponse(), status: 200 },
687
+ responseProfile: 'ebk-app-v1',
688
+ slice: name,
689
+ summary: `Expire one due ${pascalName} record hold`,
690
+ });
691
+ const protectedExample = (0, api_contract_1.defineApiOperation)({
692
+ authentication: 'customer',
693
+ authorizationActions: [`${name}:protected-read`],
694
+ contractVersion: '1.0.0',
695
+ feature: 'authorization',
696
+ lifecycle: { status: 'active' },
697
+ method: 'GET',
698
+ operationId: `${name}.protected-example`,
699
+ path: '/protected',
700
+ problems: authorizationProblems,
701
+ response: {
702
+ body: (0, api_contract_1.apiObject)({
703
+ message: (0, api_contract_1.apiString)({
704
+ enum: ['Authenticated request accepted.'],
705
+ }),
706
+ }),
707
+ status: 200,
708
+ },
709
+ responseProfile: 'ebk-app-v1',
710
+ slice: name,
711
+ summary: `Read the authenticated ${pascalName} example`,
712
+ });
713
+ const databaseHealth = (0, api_contract_1.defineApiOperation)({
714
+ authentication: 'customer',
715
+ authorizationActions: [`${name}:database-read`],
716
+ contractVersion: '1.0.0',
717
+ feature: 'database',
718
+ lifecycle: { status: 'active' },
719
+ method: 'GET',
720
+ operationId: `${name}.database-health`,
721
+ path: '/database-health',
722
+ problems: authorizationProblems,
723
+ response: {
724
+ body: (0, api_contract_1.apiObject)({
725
+ service: (0, api_contract_1.apiString)({ enum: [name] }),
726
+ status: (0, api_contract_1.apiString)({ enum: ['ok'] }),
727
+ }),
728
+ status: 200,
729
+ },
730
+ responseProfile: 'ebk-app-v1',
731
+ slice: name,
732
+ summary: `Read ${pascalName} database health`,
733
+ });
734
+ const decideRecordDeletion = (0, api_contract_1.defineApiOperation)({
735
+ authentication: 'customer',
736
+ authorizationActions: [`${name}:approval-review`],
737
+ contractVersion: '1.0.0',
738
+ feature: 'data-lifecycle',
739
+ lifecycle: { status: 'active' },
740
+ method: 'POST',
741
+ operationId: `${name}.decide-record-deletion`,
742
+ path: '/records/{recordId}/deletion-requests/{approvalRequestId}/decision',
743
+ problems: deletionProblems,
744
+ request: {
745
+ body: (0, api_contract_1.apiObject)({
746
+ expectedRequestDigest: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 64 }),
747
+ outcome: (0, api_contract_1.apiString)({ enum: ['approved', 'rejected'] }),
748
+ reasonReference: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
749
+ }),
750
+ maxBodyBytes: 512,
751
+ path: deletionRequestPath(),
752
+ },
753
+ response: {
754
+ body: (0, api_contract_1.apiObject)({
755
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
756
+ status: (0, api_contract_1.apiString)({ enum: ['approved', 'rejected'] }),
757
+ }),
758
+ status: 200,
759
+ },
760
+ responseProfile: 'ebk-app-v1',
761
+ slice: name,
762
+ summary: `Decide one pending ${pascalName} record deletion`,
763
+ });
764
+ const deleteSyntheticRecord = (0, api_contract_1.defineApiOperation)({
765
+ authentication: 'customer',
766
+ authorizationActions: [`${name}:record-delete`],
767
+ contractVersion: '1.0.0',
768
+ feature: 'database',
769
+ lifecycle: { status: 'active' },
770
+ method: 'DELETE',
771
+ operationId: `${name}.delete-record`,
772
+ path: '/records/{recordId}',
773
+ problems: deletionProblems,
774
+ request: {
775
+ path: recordPath(),
776
+ query: (0, api_contract_1.apiObject)({
777
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
778
+ reasonCode: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 1 }),
779
+ }),
780
+ },
781
+ response: {
782
+ body: (0, api_contract_1.apiObject)({
783
+ deleted: (0, api_contract_1.apiBoolean)(),
784
+ id: (0, api_contract_1.apiString)({ format: 'uuid' }),
785
+ }),
786
+ status: 200,
787
+ },
788
+ responseProfile: 'ebk-app-v1',
789
+ slice: name,
790
+ summary: `Delete one owned ${pascalName} record`,
791
+ });
792
+ const getSyntheticRecord = (0, api_contract_1.defineApiOperation)({
793
+ authentication: 'customer',
794
+ authorizationActions: [`${name}:record-read`],
795
+ contractVersion: '1.0.0',
796
+ feature: 'database',
797
+ lifecycle: { status: 'active' },
798
+ method: 'GET',
799
+ operationId: `${name}.get-record`,
800
+ path: '/records/{recordId}',
801
+ problems: recordNotFoundProblems,
802
+ request: { path: recordPath() },
803
+ response: { body: recordResponse(), status: 200 },
804
+ responseProfile: 'ebk-app-v1',
805
+ slice: name,
806
+ summary: `Read one owned ${pascalName} record`,
807
+ });
808
+ const publishCreated = (0, api_contract_1.defineApiOperation)({
809
+ authentication: 'customer',
810
+ authorizationActions: [`${name}:event-publish`],
811
+ contractVersion: '1.0.0',
812
+ feature: 'events',
813
+ lifecycle: { status: 'active' },
814
+ method: 'POST',
815
+ operationId: `${name}.publish-created`,
816
+ path: '/events/example',
817
+ problems: authorizationProblems,
818
+ response: {
819
+ body: (0, api_contract_1.apiObject)({
820
+ eventId: (0, api_contract_1.apiString)({ format: 'uuid' }),
821
+ }),
822
+ status: 200,
823
+ },
824
+ responseProfile: 'ebk-app-v1',
825
+ slice: name,
826
+ summary: `Publish a ${pascalName} example event`,
827
+ });
828
+ const putSyntheticRecord = (0, api_contract_1.defineApiOperation)({
829
+ authentication: 'customer',
830
+ authorizationActions: [`${name}:record-write`],
831
+ contractVersion: '1.0.0',
832
+ feature: 'database',
833
+ lifecycle: { status: 'active' },
834
+ method: 'PUT',
835
+ operationId: `${name}.put-record`,
836
+ path: '/records/{recordId}',
837
+ problems: recordConflictProblems,
838
+ request: {
839
+ body: (0, api_contract_1.apiObject)({
840
+ name: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
841
+ runScope: (0, api_contract_1.apiString)({ maxLength: 128, minLength: 1 }),
842
+ testExpiresAt: (0, api_contract_1.apiOptional)((0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 })),
843
+ }),
844
+ maxBodyBytes: 512,
845
+ path: recordPath(),
846
+ },
847
+ response: { body: recordResponse(), status: 200 },
848
+ responseProfile: 'ebk-app-v1',
849
+ slice: name,
850
+ summary: `Create or replace one owned ${pascalName} record`,
851
+ });
852
+ const requestRecordDeletion = (0, api_contract_1.defineApiOperation)({
853
+ authentication: 'customer',
854
+ authorizationActions: [`${name}:record-delete`],
855
+ contractVersion: '1.0.0',
856
+ feature: 'data-lifecycle',
857
+ lifecycle: { status: 'active' },
858
+ method: 'POST',
859
+ operationId: `${name}.request-record-deletion`,
860
+ path: '/records/{recordId}/deletion-requests',
861
+ problems: recordNotFoundProblems,
862
+ request: {
863
+ body: (0, api_contract_1.apiObject)({
864
+ reasonCode: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 1 }),
865
+ }),
866
+ maxBodyBytes: 256,
867
+ path: recordPath(),
868
+ },
869
+ response: {
870
+ body: (0, api_contract_1.apiObject)({
871
+ approvalRequestId: (0, api_contract_1.apiString)({ format: 'uuid' }),
872
+ expiresAt: (0, api_contract_1.apiString)({ maxLength: 40, minLength: 20 }),
873
+ requestDigest: (0, api_contract_1.apiString)({ maxLength: 64, minLength: 64 }),
874
+ status: (0, api_contract_1.apiString)({ enum: ['pending'] }),
875
+ }),
876
+ status: 202,
877
+ },
878
+ responseProfile: 'ebk-app-v1',
879
+ slice: name,
880
+ summary: `Request approval for one ${pascalName} record deletion`,
881
+ });
882
+ return (0, api_contract_1.defineApiContract)({
883
+ operations: [
884
+ cleanupRecordExport,
885
+ databaseHealth,
886
+ decideRecordExport,
887
+ decideRecordDeletion,
888
+ decideRetentionApproval,
889
+ deliverRecordExport,
890
+ deleteSyntheticRecord,
891
+ executeRecordExport,
892
+ expireRecordHold,
893
+ getSyntheticRecord,
894
+ health,
895
+ issueRecordDelegation,
896
+ issueRecordHold,
897
+ machineAuthorizationProof,
898
+ protectedExample,
899
+ publishCreated,
900
+ putSyntheticRecord,
901
+ requestRecordDeletion,
902
+ requestRecordExport,
903
+ requestRetentionApproval,
904
+ releaseRecordHold,
905
+ reviewRecordHold,
906
+ revokeRecordDelegation,
907
+ useRecordDelegation,
908
+ ],
909
+ slice: name,
910
+ title: `${pascalName} API`,
911
+ version: '1.0.0',
912
+ });
913
+ }
914
+ /** @internal */
915
+ function renderProductApiContractFiles(name, pascalName) {
916
+ const contract = createStandardApiContract(name, pascalName);
917
+ const artifacts = (0, api_contract_1.createApiContractArtifacts)(contract);
918
+ const baseline = (0, index_js_1.canonicalApiContractBaselineJson)((0, index_js_1.createApiContractBaseline)(artifacts.normalized));
919
+ const identifierPrefix = (0, built_in_plan_shared_js_1.lowerCamelIdentifier)(pascalName);
920
+ const contractIdentifier = `${identifierPrefix}ApiContract`;
921
+ return {
922
+ 'api/contracts/protected.ts': `import {
923
+ apiArray,
924
+ apiBoolean,
925
+ apiNumber,
926
+ apiObject,
927
+ apiOptional,
928
+ apiString,
929
+ defineApiContract,
930
+ defineApiOperation,
931
+ } from '@empire-builder-kit/runtime/api-contract';
932
+
933
+ const authenticationProblems = [
934
+ {
935
+ code: 'auth_invalid_token',
936
+ message: 'The access token is invalid or expired.',
937
+ retryable: false,
938
+ status: 401,
939
+ type: 'https://empirebuilderkit.dev/problems/auth/invalid-token',
940
+ },
941
+ {
942
+ code: 'auth_unauthenticated',
943
+ message: 'Authentication is required.',
944
+ retryable: false,
945
+ status: 401,
946
+ type: 'https://empirebuilderkit.dev/problems/auth/unauthenticated',
947
+ },
948
+ ] as const;
949
+
950
+ const authorizationProblems = [
951
+ ...authenticationProblems,
952
+ {
953
+ code: 'authorization_admission_required',
954
+ message: 'Required operation admission is missing.',
955
+ retryable: false,
956
+ status: 403,
957
+ type: 'https://empirebuilderkit.dev/problems/authorization/admission-required',
958
+ },
959
+ {
960
+ code: 'authorization_approval_required',
961
+ message: 'Approval is required.',
962
+ retryable: false,
963
+ status: 409,
964
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-required',
965
+ },
966
+ {
967
+ code: 'authorization_denied',
968
+ message: 'Authorization denied.',
969
+ retryable: false,
970
+ status: 403,
971
+ type: 'https://empirebuilderkit.dev/problems/authorization/denied',
972
+ },
973
+ {
974
+ code: 'authorization_input_invalid',
975
+ message: 'Authorization input is invalid.',
976
+ retryable: false,
977
+ status: 403,
978
+ type: 'https://empirebuilderkit.dev/problems/authorization/input-invalid',
979
+ },
980
+ {
981
+ code: 'authorization_policy_stale',
982
+ message: 'Authorization policy is not current.',
983
+ retryable: true,
984
+ status: 503,
985
+ type: 'https://empirebuilderkit.dev/problems/authorization/policy-stale',
986
+ },
987
+ {
988
+ code: 'authorization_unavailable',
989
+ message: 'Authorization is temporarily unavailable.',
990
+ retryable: true,
991
+ status: 503,
992
+ type: 'https://empirebuilderkit.dev/problems/authorization/unavailable',
993
+ },
994
+ ] as const;
995
+
996
+ const recordConflictProblems = [
997
+ ...authorizationProblems,
998
+ {
999
+ code: 'record_conflict',
1000
+ message: 'The record identifier is owned by another principal.',
1001
+ retryable: false,
1002
+ status: 409,
1003
+ type: 'https://empirebuilderkit.dev/problems/records/conflict',
1004
+ },
1005
+ {
1006
+ code: 'record_correction_retry_required',
1007
+ message: 'Record correction propagation requires retry.',
1008
+ retryable: true,
1009
+ status: 503,
1010
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/correction-retry-required',
1011
+ },
1012
+ {
1013
+ code: 'test_data_expiry_invalid',
1014
+ message:
1015
+ 'Test data expiry must be a canonical future timestamp within 48 hours.',
1016
+ retryable: false,
1017
+ status: 400,
1018
+ type: 'https://empirebuilderkit.dev/problems/testing/expiry-invalid',
1019
+ },
1020
+ ] as const;
1021
+
1022
+ const recordNotFoundProblems = [
1023
+ ...authorizationProblems,
1024
+ {
1025
+ code: 'record_not_found',
1026
+ message: 'The record was not found.',
1027
+ retryable: false,
1028
+ status: 404,
1029
+ type: 'https://empirebuilderkit.dev/problems/records/not-found',
1030
+ },
1031
+ ] as const;
1032
+
1033
+ const delegationProblems = [
1034
+ ...authorizationProblems,
1035
+ {
1036
+ code: 'authorization_delegation_expired',
1037
+ message: 'Delegated authority has expired.',
1038
+ retryable: false,
1039
+ status: 403,
1040
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-expired',
1041
+ },
1042
+ {
1043
+ code: 'authorization_delegation_out_of_bounds',
1044
+ message: 'Delegated authority does not cover this request.',
1045
+ retryable: false,
1046
+ status: 403,
1047
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-out-of-bounds',
1048
+ },
1049
+ {
1050
+ code: 'authorization_delegation_rate_limited',
1051
+ message: 'Delegated authority use limit has been reached.',
1052
+ retryable: false,
1053
+ status: 429,
1054
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-rate-limited',
1055
+ },
1056
+ {
1057
+ code: 'authorization_delegation_revoked',
1058
+ message: 'Delegated authority has been revoked.',
1059
+ retryable: false,
1060
+ status: 403,
1061
+ type: 'https://empirebuilderkit.dev/problems/authorization/delegation-revoked',
1062
+ },
1063
+ ] as const;
1064
+
1065
+ const delegatedRecordProblems = [
1066
+ ...delegationProblems,
1067
+ {
1068
+ code: 'record_not_found',
1069
+ message: 'The record was not found.',
1070
+ retryable: false,
1071
+ status: 404,
1072
+ type: 'https://empirebuilderkit.dev/problems/records/not-found',
1073
+ },
1074
+ ] as const;
1075
+
1076
+ const deletionProblems = [
1077
+ ...recordNotFoundProblems,
1078
+ {
1079
+ code: 'authorization_approval_expired',
1080
+ message: 'Approval has expired.',
1081
+ retryable: false,
1082
+ status: 409,
1083
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-expired',
1084
+ },
1085
+ {
1086
+ code: 'authorization_approval_invalid',
1087
+ message: 'Approval is not valid for this request.',
1088
+ retryable: false,
1089
+ status: 409,
1090
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-invalid',
1091
+ },
1092
+ {
1093
+ code: 'authorization_approval_pending',
1094
+ message: 'Approval is pending.',
1095
+ retryable: false,
1096
+ status: 409,
1097
+ type: 'https://empirebuilderkit.dev/problems/authorization/approval-pending',
1098
+ },
1099
+ {
1100
+ code: 'data_deletion_held',
1101
+ message: 'Deletion is blocked by an active hold.',
1102
+ retryable: false,
1103
+ status: 409,
1104
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/deletion-held',
1105
+ },
1106
+ {
1107
+ code: 'data_deletion_retry_required',
1108
+ message: 'Deletion propagation requires retry.',
1109
+ retryable: true,
1110
+ status: 503,
1111
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/deletion-retry-required',
1112
+ },
1113
+ ] as const;
1114
+
1115
+ const dataRightsProblems = [
1116
+ ...recordNotFoundProblems,
1117
+ {
1118
+ code: 'data_export_expired',
1119
+ message: 'The confidential export has expired.',
1120
+ retryable: false,
1121
+ status: 410,
1122
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-expired',
1123
+ },
1124
+ {
1125
+ code: 'data_export_held',
1126
+ message: 'An active hold blocks the confidential export.',
1127
+ retryable: false,
1128
+ status: 409,
1129
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-held',
1130
+ },
1131
+ {
1132
+ code: 'data_export_not_ready',
1133
+ message: 'The confidential export is not ready.',
1134
+ retryable: false,
1135
+ status: 409,
1136
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-not-ready',
1137
+ },
1138
+ {
1139
+ code: 'data_export_rate_limited',
1140
+ message: 'The bounded confidential export rate was exceeded.',
1141
+ retryable: false,
1142
+ status: 429,
1143
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-rate-limited',
1144
+ },
1145
+ {
1146
+ code: 'data_export_retry_required',
1147
+ message: 'Confidential export processing requires retry.',
1148
+ retryable: true,
1149
+ status: 503,
1150
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/export-retry-required',
1151
+ },
1152
+ {
1153
+ code: 'data_rights_input_invalid',
1154
+ message: 'The data-rights request is invalid.',
1155
+ retryable: false,
1156
+ status: 400,
1157
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/input-invalid',
1158
+ },
1159
+ {
1160
+ code: 'record_hold_invalid',
1161
+ message: 'The record hold cannot make the requested transition.',
1162
+ retryable: false,
1163
+ status: 409,
1164
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/hold-invalid',
1165
+ },
1166
+ ] as const;
1167
+
1168
+ const retentionProblems = [
1169
+ {
1170
+ code: 'data_retention_approval_invalid',
1171
+ message: 'The retention approval is invalid for this report.',
1172
+ retryable: false,
1173
+ status: 409,
1174
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-approval-invalid',
1175
+ },
1176
+ {
1177
+ code: 'data_retention_input_invalid',
1178
+ message: 'The retention review request is invalid.',
1179
+ retryable: false,
1180
+ status: 400,
1181
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-input-invalid',
1182
+ },
1183
+ {
1184
+ code: 'data_retention_not_reviewable',
1185
+ message: 'The retention report is no longer reviewable.',
1186
+ retryable: false,
1187
+ status: 409,
1188
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-not-reviewable',
1189
+ },
1190
+ {
1191
+ code: 'data_retention_report_not_found',
1192
+ message: 'The retention report was not found.',
1193
+ retryable: false,
1194
+ status: 404,
1195
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-report-not-found',
1196
+ },
1197
+ {
1198
+ code: 'data_retention_retry_required',
1199
+ message: 'Retention review persistence requires retry.',
1200
+ retryable: true,
1201
+ status: 503,
1202
+ type: 'https://empirebuilderkit.dev/problems/data-lifecycle/retention-retry-required',
1203
+ },
1204
+ ] as const;
1205
+
1206
+ const recordPath = () =>
1207
+ apiObject({
1208
+ recordId: apiString({ format: 'uuid' }),
1209
+ });
1210
+
1211
+ const deletionRequestPath = () =>
1212
+ apiObject({
1213
+ approvalRequestId: apiString({ format: 'uuid' }),
1214
+ recordId: apiString({ format: 'uuid' }),
1215
+ });
1216
+
1217
+ const delegationPath = () =>
1218
+ apiObject({
1219
+ delegationId: apiString({ format: 'uuid' }),
1220
+ recordId: apiString({ format: 'uuid' }),
1221
+ });
1222
+
1223
+ const exportPath = () =>
1224
+ apiObject({
1225
+ approvalRequestId: apiString({ format: 'uuid' }),
1226
+ recordId: apiString({ format: 'uuid' }),
1227
+ });
1228
+
1229
+ const holdPath = () =>
1230
+ apiObject({
1231
+ holdId: apiString({ maxLength: 64, minLength: 1 }),
1232
+ recordId: apiString({ format: 'uuid' }),
1233
+ });
1234
+
1235
+ const retentionApprovalPath = () =>
1236
+ apiObject({
1237
+ approvalRequestId: apiString({ format: 'uuid' }),
1238
+ runId: apiString({ format: 'uuid' }),
1239
+ });
1240
+
1241
+ const retentionRunPath = () =>
1242
+ apiObject({
1243
+ runId: apiString({ format: 'uuid' }),
1244
+ });
1245
+
1246
+ const recordResponse = () =>
1247
+ apiObject({
1248
+ id: apiString({ format: 'uuid' }),
1249
+ name: apiString({ maxLength: 128, minLength: 1 }),
1250
+ runScope: apiString({ maxLength: 128, minLength: 1 }),
1251
+ });
1252
+
1253
+ const holdResponse = () =>
1254
+ apiObject({
1255
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1256
+ holdId: apiString({ maxLength: 64, minLength: 1 }),
1257
+ reviewAt: apiString({ maxLength: 40, minLength: 20 }),
1258
+ status: apiString({ enum: ['active', 'released'] as const }),
1259
+ });
1260
+
1261
+ export const ${identifierPrefix}Health = defineApiOperation({
1262
+ authentication: 'anonymous',
1263
+ authorizationActions: [],
1264
+ contractVersion: '1.0.0',
1265
+ feature: 'operations',
1266
+ lifecycle: { status: 'active' },
1267
+ method: 'GET',
1268
+ operationId: '${name}.health',
1269
+ path: '/health',
1270
+ problems: [],
1271
+ response: {
1272
+ body: apiObject({
1273
+ service: apiString({ enum: ['${name}'] as const }),
1274
+ sourceCommit: apiString({ maxLength: 64, minLength: 1 }),
1275
+ stage: apiString({ maxLength: 64, minLength: 1 }),
1276
+ status: apiString({ enum: ['ok'] as const }),
1277
+ }),
1278
+ status: 200,
1279
+ },
1280
+ responseProfile: 'ebk-app-v1',
1281
+ slice: '${name}',
1282
+ summary: 'Read ${pascalName} API health',
1283
+ });
1284
+
1285
+ export const ${identifierPrefix}MachineAuthorizationProof = defineApiOperation({
1286
+ authentication: 'customer',
1287
+ authorizationActions: ['${name}:machine-proof-read'],
1288
+ contractVersion: '1.0.0',
1289
+ feature: 'authorization',
1290
+ lifecycle: { status: 'active' },
1291
+ method: 'GET',
1292
+ operationId: '${name}.machine-authorization-proof',
1293
+ path: '/authorization/machine-proof',
1294
+ problems: authorizationProblems,
1295
+ response: {
1296
+ body: apiObject({
1297
+ message: apiString({
1298
+ enum: ['Machine authorization accepted.'] as const,
1299
+ }),
1300
+ }),
1301
+ status: 200,
1302
+ },
1303
+ responseProfile: 'ebk-app-v1',
1304
+ slice: '${name}',
1305
+ summary: 'Prove narrow ${pascalName} machine authorization',
1306
+ });
1307
+
1308
+ export const ${identifierPrefix}IssueRecordDelegation = defineApiOperation({
1309
+ authentication: 'customer',
1310
+ authorizationActions: ['${name}:record-delegation-issue'],
1311
+ contractVersion: '1.0.0',
1312
+ feature: 'authorization',
1313
+ lifecycle: { status: 'active' },
1314
+ method: 'POST',
1315
+ operationId: '${name}.issue-record-delegation',
1316
+ path: '/records/{recordId}/delegations',
1317
+ problems: authorizationProblems,
1318
+ request: {
1319
+ body: apiObject({
1320
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1321
+ purposeReference: apiString({ maxLength: 256, minLength: 1 }),
1322
+ }),
1323
+ maxBodyBytes: 512,
1324
+ path: recordPath(),
1325
+ },
1326
+ response: {
1327
+ body: apiObject({
1328
+ capability: apiString({ maxLength: 43, minLength: 43 }),
1329
+ delegationId: apiString({ format: 'uuid' }),
1330
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1331
+ status: apiString({ enum: ['active'] as const }),
1332
+ }),
1333
+ status: 201,
1334
+ },
1335
+ responseProfile: 'ebk-app-v1',
1336
+ slice: '${name}',
1337
+ summary: 'Issue one attended ${pascalName} record delegation',
1338
+ });
1339
+
1340
+ export const ${identifierPrefix}RevokeRecordDelegation = defineApiOperation({
1341
+ authentication: 'customer',
1342
+ authorizationActions: ['${name}:record-delegation-revoke'],
1343
+ contractVersion: '1.0.0',
1344
+ feature: 'authorization',
1345
+ lifecycle: { status: 'active' },
1346
+ method: 'DELETE',
1347
+ operationId: '${name}.revoke-record-delegation',
1348
+ path: '/records/{recordId}/delegations/{delegationId}',
1349
+ problems: authorizationProblems,
1350
+ request: { path: delegationPath() },
1351
+ response: {
1352
+ body: apiObject({
1353
+ delegationId: apiString({ format: 'uuid' }),
1354
+ status: apiString({ enum: ['revoked'] as const }),
1355
+ }),
1356
+ status: 200,
1357
+ },
1358
+ responseProfile: 'ebk-app-v1',
1359
+ slice: '${name}',
1360
+ summary: 'Revoke one attended ${pascalName} record delegation',
1361
+ });
1362
+
1363
+ export const ${identifierPrefix}UseRecordDelegation = defineApiOperation({
1364
+ authentication: 'customer',
1365
+ authorizationActions: ['${name}:record-delegation-use'],
1366
+ contractVersion: '1.0.0',
1367
+ feature: 'authorization',
1368
+ lifecycle: { status: 'active' },
1369
+ method: 'POST',
1370
+ operationId: '${name}.use-record-delegation',
1371
+ path: '/records/{recordId}/delegations/{delegationId}/use',
1372
+ problems: delegatedRecordProblems,
1373
+ request: {
1374
+ body: apiObject({
1375
+ capability: apiString({ maxLength: 43, minLength: 43 }),
1376
+ }),
1377
+ maxBodyBytes: 256,
1378
+ path: delegationPath(),
1379
+ },
1380
+ response: { body: recordResponse(), status: 200 },
1381
+ responseProfile: 'ebk-app-v1',
1382
+ slice: '${name}',
1383
+ summary: 'Use one attended ${pascalName} record delegation',
1384
+ });
1385
+
1386
+ export const ${identifierPrefix}RequestRecordExport = defineApiOperation({
1387
+ authentication: 'customer',
1388
+ authorizationActions: ['${name}:record-export'],
1389
+ contractVersion: '1.0.0',
1390
+ feature: 'data-lifecycle',
1391
+ lifecycle: { status: 'active' },
1392
+ method: 'POST',
1393
+ operationId: '${name}.request-record-export',
1394
+ path: '/records/{recordId}/exports',
1395
+ problems: dataRightsProblems,
1396
+ request: { path: recordPath() },
1397
+ response: {
1398
+ body: apiObject({
1399
+ approvalRequestId: apiString({ format: 'uuid' }),
1400
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1401
+ requestDigest: apiString({ maxLength: 64, minLength: 64 }),
1402
+ status: apiString({ enum: ['pending'] as const }),
1403
+ }),
1404
+ status: 202,
1405
+ },
1406
+ responseProfile: 'ebk-app-v1',
1407
+ slice: '${name}',
1408
+ summary: 'Request one subject-bound ${pascalName} record export',
1409
+ });
1410
+
1411
+ export const ${identifierPrefix}DecideRecordExport = defineApiOperation({
1412
+ authentication: 'customer',
1413
+ authorizationActions: ['${name}:approval-review'],
1414
+ contractVersion: '1.0.0',
1415
+ feature: 'data-lifecycle',
1416
+ lifecycle: { status: 'active' },
1417
+ method: 'POST',
1418
+ operationId: '${name}.decide-record-export',
1419
+ path: '/records/{recordId}/exports/{approvalRequestId}/decision',
1420
+ problems: dataRightsProblems,
1421
+ request: {
1422
+ body: apiObject({
1423
+ expectedRequestDigest: apiString({ maxLength: 64, minLength: 64 }),
1424
+ outcome: apiString({ enum: ['approved', 'rejected'] as const }),
1425
+ reasonReference: apiString({ maxLength: 128, minLength: 1 }),
1426
+ }),
1427
+ maxBodyBytes: 512,
1428
+ path: exportPath(),
1429
+ },
1430
+ response: {
1431
+ body: apiObject({
1432
+ approvalRequestId: apiString({ format: 'uuid' }),
1433
+ status: apiString({ enum: ['approved', 'rejected'] as const }),
1434
+ }),
1435
+ status: 200,
1436
+ },
1437
+ responseProfile: 'ebk-app-v1',
1438
+ slice: '${name}',
1439
+ summary: 'Decide one ${pascalName} record export',
1440
+ });
1441
+
1442
+ export const ${identifierPrefix}ExecuteRecordExport = defineApiOperation({
1443
+ authentication: 'customer',
1444
+ authorizationActions: ['${name}:record-export'],
1445
+ contractVersion: '1.0.0',
1446
+ feature: 'data-lifecycle',
1447
+ lifecycle: { status: 'active' },
1448
+ method: 'POST',
1449
+ operationId: '${name}.execute-record-export',
1450
+ path: '/records/{recordId}/exports/{approvalRequestId}/execute',
1451
+ problems: dataRightsProblems,
1452
+ request: { path: exportPath() },
1453
+ response: {
1454
+ body: apiObject({
1455
+ artifactRef: apiOptional(
1456
+ apiString({ maxLength: 128, minLength: 1 }),
1457
+ ),
1458
+ expiresAt: apiOptional(
1459
+ apiString({ maxLength: 40, minLength: 20 }),
1460
+ ),
1461
+ status: apiString({ enum: ['held', 'ready'] as const }),
1462
+ }),
1463
+ status: 200,
1464
+ },
1465
+ responseProfile: 'ebk-app-v1',
1466
+ slice: '${name}',
1467
+ summary: 'Execute one approved ${pascalName} record export',
1468
+ });
1469
+
1470
+ export const ${identifierPrefix}DeliverRecordExport = defineApiOperation({
1471
+ authentication: 'customer',
1472
+ authorizationActions: ['${name}:record-export'],
1473
+ contractVersion: '1.0.0',
1474
+ feature: 'data-lifecycle',
1475
+ lifecycle: { status: 'active' },
1476
+ method: 'GET',
1477
+ operationId: '${name}.deliver-record-export',
1478
+ path: '/records/{recordId}/exports/{approvalRequestId}/delivery',
1479
+ problems: dataRightsProblems,
1480
+ request: { path: exportPath() },
1481
+ response: {
1482
+ body: apiObject({
1483
+ artifactRef: apiString({ maxLength: 128, minLength: 1 }),
1484
+ deliveredAt: apiString({ maxLength: 40, minLength: 20 }),
1485
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1486
+ record: recordResponse(),
1487
+ }),
1488
+ status: 200,
1489
+ },
1490
+ responseProfile: 'ebk-app-v1',
1491
+ slice: '${name}',
1492
+ summary: 'Deliver one unexpired ${pascalName} record export',
1493
+ });
1494
+
1495
+ export const ${identifierPrefix}CleanupRecordExport = defineApiOperation({
1496
+ authentication: 'customer',
1497
+ authorizationActions: ['${name}:record-export-cleanup'],
1498
+ contractVersion: '1.0.0',
1499
+ feature: 'data-lifecycle',
1500
+ lifecycle: { status: 'active' },
1501
+ method: 'DELETE',
1502
+ operationId: '${name}.cleanup-record-export',
1503
+ path: '/records/{recordId}/exports/{approvalRequestId}',
1504
+ problems: dataRightsProblems,
1505
+ request: { path: exportPath() },
1506
+ response: {
1507
+ body: apiObject({
1508
+ deletedVersions: apiNumber({ integer: true, minimum: 0 }),
1509
+ status: apiString({
1510
+ enum: ['completed', 'retry-required'] as const,
1511
+ }),
1512
+ }),
1513
+ status: 200,
1514
+ },
1515
+ responseProfile: 'ebk-app-v1',
1516
+ slice: '${name}',
1517
+ summary: 'Clean up one expired ${pascalName} record export',
1518
+ });
1519
+
1520
+ export const ${identifierPrefix}RequestRetentionApproval =
1521
+ defineApiOperation({
1522
+ authentication: 'customer',
1523
+ authorizationActions: ['${name}:retention-review'],
1524
+ contractVersion: '1.0.0',
1525
+ feature: 'data-lifecycle',
1526
+ lifecycle: { status: 'active' },
1527
+ method: 'POST',
1528
+ operationId: '${name}.request-retention-approval',
1529
+ path: '/data-retention/runs/{runId}/approval-requests',
1530
+ problems: retentionProblems,
1531
+ request: { path: retentionRunPath() },
1532
+ response: {
1533
+ body: apiObject({
1534
+ approvalRequestId: apiString({ format: 'uuid' }),
1535
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1536
+ requestDigest: apiString({ maxLength: 64, minLength: 64 }),
1537
+ status: apiString({ enum: ['pending'] as const }),
1538
+ }),
1539
+ status: 202,
1540
+ },
1541
+ responseProfile: 'ebk-app-v1',
1542
+ slice: '${name}',
1543
+ summary:
1544
+ 'Request direct-admin review of one ${pascalName} retention report',
1545
+ });
1546
+
1547
+ export const ${identifierPrefix}DecideRetentionApproval =
1548
+ defineApiOperation({
1549
+ authentication: 'customer',
1550
+ authorizationActions: ['${name}:retention-review'],
1551
+ contractVersion: '1.0.0',
1552
+ feature: 'data-lifecycle',
1553
+ lifecycle: { status: 'active' },
1554
+ method: 'POST',
1555
+ operationId: '${name}.decide-retention-approval',
1556
+ path:
1557
+ '/data-retention/runs/{runId}/approval-requests/{approvalRequestId}/decision',
1558
+ problems: retentionProblems,
1559
+ request: {
1560
+ body: apiObject({
1561
+ expectedRequestDigest: apiString({ maxLength: 64, minLength: 64 }),
1562
+ outcome: apiString({ enum: ['approved', 'rejected'] as const }),
1563
+ reasonReference: apiString({ maxLength: 128, minLength: 1 }),
1564
+ }),
1565
+ maxBodyBytes: 512,
1566
+ path: retentionApprovalPath(),
1567
+ },
1568
+ response: {
1569
+ body: apiObject({
1570
+ approvalRequestId: apiString({ format: 'uuid' }),
1571
+ status: apiString({ enum: ['approved', 'rejected'] as const }),
1572
+ }),
1573
+ status: 200,
1574
+ },
1575
+ responseProfile: 'ebk-app-v1',
1576
+ slice: '${name}',
1577
+ summary:
1578
+ 'Decide one ${pascalName} retention approval as a non-author admin',
1579
+ });
1580
+
1581
+ export const ${identifierPrefix}IssueRecordHold = defineApiOperation({
1582
+ authentication: 'customer',
1583
+ authorizationActions: ['${name}:record-hold-manage'],
1584
+ contractVersion: '1.0.0',
1585
+ feature: 'data-lifecycle',
1586
+ lifecycle: { status: 'active' },
1587
+ method: 'POST',
1588
+ operationId: '${name}.issue-record-hold',
1589
+ path: '/records/{recordId}/holds',
1590
+ problems: dataRightsProblems,
1591
+ request: {
1592
+ body: apiObject({
1593
+ effects: apiArray(
1594
+ apiString({
1595
+ enum: ['block-deletion', 'block-export'] as const,
1596
+ }),
1597
+ { maxItems: 2, minItems: 1 },
1598
+ ),
1599
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1600
+ purpose: apiString({
1601
+ enum: ['fraud', 'incident', 'legal', 'security', 'support'] as const,
1602
+ }),
1603
+ reviewAt: apiString({ maxLength: 40, minLength: 20 }),
1604
+ }),
1605
+ maxBodyBytes: 512,
1606
+ path: recordPath(),
1607
+ },
1608
+ response: { body: holdResponse(), status: 201 },
1609
+ responseProfile: 'ebk-app-v1',
1610
+ slice: '${name}',
1611
+ summary: 'Issue one bounded ${pascalName} record hold',
1612
+ });
1613
+
1614
+ export const ${identifierPrefix}ReviewRecordHold = defineApiOperation({
1615
+ authentication: 'customer',
1616
+ authorizationActions: ['${name}:record-hold-manage'],
1617
+ contractVersion: '1.0.0',
1618
+ feature: 'data-lifecycle',
1619
+ lifecycle: { status: 'active' },
1620
+ method: 'POST',
1621
+ operationId: '${name}.review-record-hold',
1622
+ path: '/records/{recordId}/holds/{holdId}/review',
1623
+ problems: dataRightsProblems,
1624
+ request: {
1625
+ body: apiObject({
1626
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1627
+ reviewAt: apiString({ maxLength: 40, minLength: 20 }),
1628
+ }),
1629
+ maxBodyBytes: 256,
1630
+ path: holdPath(),
1631
+ },
1632
+ response: { body: holdResponse(), status: 200 },
1633
+ responseProfile: 'ebk-app-v1',
1634
+ slice: '${name}',
1635
+ summary: 'Review one bounded ${pascalName} record hold',
1636
+ });
1637
+
1638
+ export const ${identifierPrefix}ReleaseRecordHold = defineApiOperation({
1639
+ authentication: 'customer',
1640
+ authorizationActions: ['${name}:record-hold-manage'],
1641
+ contractVersion: '1.0.0',
1642
+ feature: 'data-lifecycle',
1643
+ lifecycle: { status: 'active' },
1644
+ method: 'DELETE',
1645
+ operationId: '${name}.release-record-hold',
1646
+ path: '/records/{recordId}/holds/{holdId}',
1647
+ problems: dataRightsProblems,
1648
+ request: { path: holdPath() },
1649
+ response: { body: holdResponse(), status: 200 },
1650
+ responseProfile: 'ebk-app-v1',
1651
+ slice: '${name}',
1652
+ summary: 'Release one bounded ${pascalName} record hold',
1653
+ });
1654
+
1655
+ export const ${identifierPrefix}ExpireRecordHold = defineApiOperation({
1656
+ authentication: 'customer',
1657
+ authorizationActions: ['${name}:record-hold-manage'],
1658
+ contractVersion: '1.0.0',
1659
+ feature: 'data-lifecycle',
1660
+ lifecycle: { status: 'active' },
1661
+ method: 'POST',
1662
+ operationId: '${name}.expire-record-hold',
1663
+ path: '/records/{recordId}/holds/{holdId}/expire',
1664
+ problems: dataRightsProblems,
1665
+ request: { path: holdPath() },
1666
+ response: { body: holdResponse(), status: 200 },
1667
+ responseProfile: 'ebk-app-v1',
1668
+ slice: '${name}',
1669
+ summary: 'Expire one due ${pascalName} record hold',
1670
+ });
1671
+
1672
+ export const ${identifierPrefix}ProtectedExample = defineApiOperation({
1673
+ authentication: 'customer',
1674
+ authorizationActions: ['${name}:protected-read'],
1675
+ contractVersion: '1.0.0',
1676
+ feature: 'authorization',
1677
+ lifecycle: { status: 'active' },
1678
+ method: 'GET',
1679
+ operationId: '${name}.protected-example',
1680
+ path: '/protected',
1681
+ problems: authorizationProblems,
1682
+ response: {
1683
+ body: apiObject({
1684
+ message: apiString({
1685
+ enum: ['Authenticated request accepted.'] as const,
1686
+ }),
1687
+ }),
1688
+ status: 200,
1689
+ },
1690
+ responseProfile: 'ebk-app-v1',
1691
+ slice: '${name}',
1692
+ summary: 'Read the authenticated ${pascalName} example',
1693
+ });
1694
+
1695
+ export const ${identifierPrefix}DatabaseHealth = defineApiOperation({
1696
+ authentication: 'customer',
1697
+ authorizationActions: ['${name}:database-read'],
1698
+ contractVersion: '1.0.0',
1699
+ feature: 'database',
1700
+ lifecycle: { status: 'active' },
1701
+ method: 'GET',
1702
+ operationId: '${name}.database-health',
1703
+ path: '/database-health',
1704
+ problems: authorizationProblems,
1705
+ response: {
1706
+ body: apiObject({
1707
+ service: apiString({ enum: ['${name}'] as const }),
1708
+ status: apiString({ enum: ['ok'] as const }),
1709
+ }),
1710
+ status: 200,
1711
+ },
1712
+ responseProfile: 'ebk-app-v1',
1713
+ slice: '${name}',
1714
+ summary: 'Read ${pascalName} database health',
1715
+ });
1716
+
1717
+ export const ${identifierPrefix}DecideRecordDeletion = defineApiOperation({
1718
+ authentication: 'customer',
1719
+ authorizationActions: ['${name}:approval-review'],
1720
+ contractVersion: '1.0.0',
1721
+ feature: 'data-lifecycle',
1722
+ lifecycle: { status: 'active' },
1723
+ method: 'POST',
1724
+ operationId: '${name}.decide-record-deletion',
1725
+ path: '/records/{recordId}/deletion-requests/{approvalRequestId}/decision',
1726
+ problems: deletionProblems,
1727
+ request: {
1728
+ body: apiObject({
1729
+ expectedRequestDigest: apiString({ maxLength: 64, minLength: 64 }),
1730
+ outcome: apiString({ enum: ['approved', 'rejected'] as const }),
1731
+ reasonReference: apiString({ maxLength: 128, minLength: 1 }),
1732
+ }),
1733
+ maxBodyBytes: 512,
1734
+ path: deletionRequestPath(),
1735
+ },
1736
+ response: {
1737
+ body: apiObject({
1738
+ approvalRequestId: apiString({ format: 'uuid' }),
1739
+ status: apiString({ enum: ['approved', 'rejected'] as const }),
1740
+ }),
1741
+ status: 200,
1742
+ },
1743
+ responseProfile: 'ebk-app-v1',
1744
+ slice: '${name}',
1745
+ summary: 'Decide one pending ${pascalName} record deletion',
1746
+ });
1747
+
1748
+ export const ${identifierPrefix}DeleteRecord = defineApiOperation({
1749
+ authentication: 'customer',
1750
+ authorizationActions: ['${name}:record-delete'],
1751
+ contractVersion: '1.0.0',
1752
+ feature: 'database',
1753
+ lifecycle: { status: 'active' },
1754
+ method: 'DELETE',
1755
+ operationId: '${name}.delete-record',
1756
+ path: '/records/{recordId}',
1757
+ problems: deletionProblems,
1758
+ request: {
1759
+ path: recordPath(),
1760
+ query: apiObject({
1761
+ approvalRequestId: apiString({ format: 'uuid' }),
1762
+ reasonCode: apiString({ maxLength: 64, minLength: 1 }),
1763
+ }),
1764
+ },
1765
+ response: {
1766
+ body: apiObject({
1767
+ deleted: apiBoolean(),
1768
+ id: apiString({ format: 'uuid' }),
1769
+ }),
1770
+ status: 200,
1771
+ },
1772
+ responseProfile: 'ebk-app-v1',
1773
+ slice: '${name}',
1774
+ summary: 'Delete one owned ${pascalName} record',
1775
+ });
1776
+
1777
+ export const ${identifierPrefix}GetRecord = defineApiOperation({
1778
+ authentication: 'customer',
1779
+ authorizationActions: ['${name}:record-read'],
1780
+ contractVersion: '1.0.0',
1781
+ feature: 'database',
1782
+ lifecycle: { status: 'active' },
1783
+ method: 'GET',
1784
+ operationId: '${name}.get-record',
1785
+ path: '/records/{recordId}',
1786
+ problems: recordNotFoundProblems,
1787
+ request: { path: recordPath() },
1788
+ response: { body: recordResponse(), status: 200 },
1789
+ responseProfile: 'ebk-app-v1',
1790
+ slice: '${name}',
1791
+ summary: 'Read one owned ${pascalName} record',
1792
+ });
1793
+
1794
+ export const ${identifierPrefix}PublishCreated = defineApiOperation({
1795
+ authentication: 'customer',
1796
+ authorizationActions: ['${name}:event-publish'],
1797
+ contractVersion: '1.0.0',
1798
+ feature: 'events',
1799
+ lifecycle: { status: 'active' },
1800
+ method: 'POST',
1801
+ operationId: '${name}.publish-created',
1802
+ path: '/events/example',
1803
+ problems: authorizationProblems,
1804
+ response: {
1805
+ body: apiObject({
1806
+ eventId: apiString({ format: 'uuid' }),
1807
+ }),
1808
+ status: 200,
1809
+ },
1810
+ responseProfile: 'ebk-app-v1',
1811
+ slice: '${name}',
1812
+ summary: 'Publish a ${pascalName} example event',
1813
+ });
1814
+
1815
+ export const ${identifierPrefix}PutRecord = defineApiOperation({
1816
+ authentication: 'customer',
1817
+ authorizationActions: ['${name}:record-write'],
1818
+ contractVersion: '1.0.0',
1819
+ feature: 'database',
1820
+ lifecycle: { status: 'active' },
1821
+ method: 'PUT',
1822
+ operationId: '${name}.put-record',
1823
+ path: '/records/{recordId}',
1824
+ problems: recordConflictProblems,
1825
+ request: {
1826
+ body: apiObject({
1827
+ name: apiString({ maxLength: 128, minLength: 1 }),
1828
+ runScope: apiString({ maxLength: 128, minLength: 1 }),
1829
+ testExpiresAt: apiOptional(
1830
+ apiString({ maxLength: 40, minLength: 20 }),
1831
+ ),
1832
+ }),
1833
+ maxBodyBytes: 512,
1834
+ path: recordPath(),
1835
+ },
1836
+ response: { body: recordResponse(), status: 200 },
1837
+ responseProfile: 'ebk-app-v1',
1838
+ slice: '${name}',
1839
+ summary: 'Create or replace one owned ${pascalName} record',
1840
+ });
1841
+
1842
+ export const ${identifierPrefix}RequestRecordDeletion = defineApiOperation({
1843
+ authentication: 'customer',
1844
+ authorizationActions: ['${name}:record-delete'],
1845
+ contractVersion: '1.0.0',
1846
+ feature: 'data-lifecycle',
1847
+ lifecycle: { status: 'active' },
1848
+ method: 'POST',
1849
+ operationId: '${name}.request-record-deletion',
1850
+ path: '/records/{recordId}/deletion-requests',
1851
+ problems: recordNotFoundProblems,
1852
+ request: {
1853
+ body: apiObject({
1854
+ reasonCode: apiString({ maxLength: 64, minLength: 1 }),
1855
+ }),
1856
+ maxBodyBytes: 256,
1857
+ path: recordPath(),
1858
+ },
1859
+ response: {
1860
+ body: apiObject({
1861
+ approvalRequestId: apiString({ format: 'uuid' }),
1862
+ expiresAt: apiString({ maxLength: 40, minLength: 20 }),
1863
+ requestDigest: apiString({ maxLength: 64, minLength: 64 }),
1864
+ status: apiString({ enum: ['pending'] as const }),
1865
+ }),
1866
+ status: 202,
1867
+ },
1868
+ responseProfile: 'ebk-app-v1',
1869
+ slice: '${name}',
1870
+ summary: 'Request approval for one ${pascalName} record deletion',
1871
+ });
1872
+
1873
+ export const ${contractIdentifier} = defineApiContract({
1874
+ operations: [
1875
+ ${identifierPrefix}CleanupRecordExport,
1876
+ ${identifierPrefix}DatabaseHealth,
1877
+ ${identifierPrefix}DecideRecordExport,
1878
+ ${identifierPrefix}DecideRecordDeletion,
1879
+ ${identifierPrefix}DecideRetentionApproval,
1880
+ ${identifierPrefix}DeliverRecordExport,
1881
+ ${identifierPrefix}DeleteRecord,
1882
+ ${identifierPrefix}ExecuteRecordExport,
1883
+ ${identifierPrefix}ExpireRecordHold,
1884
+ ${identifierPrefix}GetRecord,
1885
+ ${identifierPrefix}Health,
1886
+ ${identifierPrefix}IssueRecordDelegation,
1887
+ ${identifierPrefix}IssueRecordHold,
1888
+ ${identifierPrefix}MachineAuthorizationProof,
1889
+ ${identifierPrefix}ProtectedExample,
1890
+ ${identifierPrefix}PublishCreated,
1891
+ ${identifierPrefix}PutRecord,
1892
+ ${identifierPrefix}RequestRecordDeletion,
1893
+ ${identifierPrefix}RequestRecordExport,
1894
+ ${identifierPrefix}RequestRetentionApproval,
1895
+ ${identifierPrefix}ReleaseRecordHold,
1896
+ ${identifierPrefix}ReviewRecordHold,
1897
+ ${identifierPrefix}RevokeRecordDelegation,
1898
+ ${identifierPrefix}UseRecordDelegation,
1899
+ ] as const,
1900
+ slice: '${name}',
1901
+ title: '${pascalName} API',
1902
+ version: '1.0.0',
1903
+ });
1904
+ `,
1905
+ 'api/contracts/index.ts': `export {
1906
+ ${contractIdentifier},
1907
+ ${identifierPrefix}CleanupRecordExport,
1908
+ ${identifierPrefix}DatabaseHealth,
1909
+ ${identifierPrefix}DecideRecordExport,
1910
+ ${identifierPrefix}DecideRecordDeletion,
1911
+ ${identifierPrefix}DecideRetentionApproval,
1912
+ ${identifierPrefix}DeliverRecordExport,
1913
+ ${identifierPrefix}DeleteRecord,
1914
+ ${identifierPrefix}ExecuteRecordExport,
1915
+ ${identifierPrefix}ExpireRecordHold,
1916
+ ${identifierPrefix}GetRecord,
1917
+ ${identifierPrefix}Health,
1918
+ ${identifierPrefix}IssueRecordDelegation,
1919
+ ${identifierPrefix}IssueRecordHold,
1920
+ ${identifierPrefix}MachineAuthorizationProof,
1921
+ ${identifierPrefix}ProtectedExample,
1922
+ ${identifierPrefix}PublishCreated,
1923
+ ${identifierPrefix}PutRecord,
1924
+ ${identifierPrefix}RequestRecordDeletion,
1925
+ ${identifierPrefix}RequestRecordExport,
1926
+ ${identifierPrefix}RequestRetentionApproval,
1927
+ ${identifierPrefix}ReleaseRecordHold,
1928
+ ${identifierPrefix}ReviewRecordHold,
1929
+ ${identifierPrefix}RevokeRecordDelegation,
1930
+ ${identifierPrefix}UseRecordDelegation,
1931
+ } from './protected.js';
1932
+ `,
1933
+ 'api/generated/client.ts': `import {
1934
+ createApiContractClient,
1935
+ type ApiContractClient,
1936
+ type CreateApiClientOptions,
1937
+ } from '@empire-builder-kit/runtime/api-client';
1938
+ import { ${contractIdentifier} } from '../contracts/index.js';
1939
+
1940
+ export type ${pascalName}ApiClient = ApiContractClient<
1941
+ typeof ${contractIdentifier}
1942
+ >;
1943
+
1944
+ export function create${pascalName}ApiClient(
1945
+ options: CreateApiClientOptions,
1946
+ ): ${pascalName}ApiClient {
1947
+ return createApiContractClient(${contractIdentifier}, options);
1948
+ }
1949
+ `,
1950
+ 'api/generated/contract.json': artifacts.normalizedJson,
1951
+ 'api/generated/openapi.json': artifacts.openApiJson,
1952
+ 'api/generated/baseline.json': baseline,
1953
+ 'docs/api-contracts.md': `# ${name} synchronous API
1954
+
1955
+ Author operation behavior in \`api/contracts/\`. The TypeScript contract is the
1956
+ source of truth. The normalized contract, OpenAPI document, and browser-safe
1957
+ client under \`api/generated/\` are managed output. The seeded compatibility
1958
+ baseline is reviewed product state and is never restamped by regeneration.
1959
+
1960
+ Transport declarations must be lossless on the wire. String request headers
1961
+ use \`apiString({ format: 'ebk-http-header-value' })\`: visible ASCII only,
1962
+ at most 8 KiB, with no empty value, leading or trailing whitespace, controls,
1963
+ DEL, or non-ASCII. Path strings must exclude the empty value, and repeated
1964
+ query arrays must require at least one item.
1965
+
1966
+ Every actionable authentication or authorization failure must be declared by
1967
+ the operation contract. An undeclared or inconsistent failure is treated as a
1968
+ contract defect and returned as a sanitized 500 response, never improvised as
1969
+ a new wire-visible 401 or 403 response.
1970
+
1971
+ Run \`pnpm nx run ${name}:api-contract-generate\` after changing an operation,
1972
+ then inspect the generated diff and run
1973
+ \`pnpm nx run ${name}:api-contract-check\`. The check is report-first and never
1974
+ updates the accepted baseline.
1975
+
1976
+ An intentional baseline update requires a reviewed JSON approval:
1977
+
1978
+ \`\`\`sh
1979
+ pnpm nx run ${name}:api-contract-baseline -- --approval=path/to/approval.json
1980
+ \`\`\`
1981
+
1982
+ Compatible approvals pin the exact candidate digest and reason. Conditional
1983
+ approvals also require semantic-review evidence. Breaking approvals require
1984
+ consumer evidence, rollout evidence, and an exact rollout-plan identity and
1985
+ digest. Baseline updates never occur during generation or verification.
1986
+
1987
+ Other Slices may import only \`@<workspace>/${name}/api-contract\`,
1988
+ \`@<workspace>/${name}/api-client\`, or the transport-neutral
1989
+ \`@<workspace>/${name}/contracts\` surface. They may not import handlers,
1990
+ database code, or other implementation paths.
1991
+ `,
1992
+ 'scripts/contract-dependencies.mjs': `import {
1993
+ existsSync,
1994
+ readFileSync,
1995
+ realpathSync,
1996
+ readdirSync,
1997
+ statSync,
1998
+ writeFileSync,
1999
+ } from 'node:fs';
2000
+ import { createRequire } from 'node:module';
2001
+ import { isAbsolute, join, relative, resolve, sep } from 'node:path';
2002
+
2003
+ const require = createRequire(import.meta.url);
2004
+ const {
2005
+ normalizeApiContractProjectDeclarations,
2006
+ resolveApiContractDependencies,
2007
+ } = require('@empire-builder-kit/nx/api-contract');
2008
+ const {
2009
+ validateGeneratedOwnershipRecord,
2010
+ } = require('@empire-builder-kit/nx/ownership');
2011
+
2012
+ const projectRoot = process.cwd();
2013
+ const workspaceRoot = resolve(projectRoot, '../..');
2014
+ const action = process.argv[2] ?? 'check';
2015
+ if (action !== 'check' && action !== 'sync') {
2016
+ throw new Error(
2017
+ 'Usage: node scripts/contract-dependencies.mjs <check|sync>',
2018
+ );
2019
+ }
2020
+ const readJson = (path) => {
2021
+ const contents = readFileSync(path, 'utf8');
2022
+ try {
2023
+ return JSON.parse(contents);
2024
+ } catch (error) {
2025
+ const qualifiedPath = relative(workspaceRoot, path)
2026
+ .split(sep)
2027
+ .join('/');
2028
+ throw new Error(
2029
+ qualifiedPath +
2030
+ ' contains malformed JSON: ' +
2031
+ (error instanceof Error ? error.message : String(error)),
2032
+ );
2033
+ }
2034
+ };
2035
+ const declarationPath = join(
2036
+ projectRoot,
2037
+ 'contracts',
2038
+ 'dependencies.json',
2039
+ );
2040
+ const ownershipPath = join(projectRoot, '.ebk', 'ownership.json');
2041
+ const allowedContractExports = new Map([
2042
+ ['./api-client', { exact: 'api/generated/client.ts' }],
2043
+ ['./api-contract', { surface: 'api/contracts' }],
2044
+ ['./contracts', { exact: 'contracts/index.ts' }],
2045
+ ]);
2046
+
2047
+ function isContained(root, candidate) {
2048
+ const pathFromRoot = relative(root, candidate);
2049
+ return (
2050
+ pathFromRoot !== '..' &&
2051
+ !pathFromRoot.startsWith('..' + sep) &&
2052
+ !isAbsolute(pathFromRoot)
2053
+ );
2054
+ }
2055
+
2056
+ function declaredExportTargets(declaration, packageName, exportName) {
2057
+ if (typeof declaration === 'string') return [declaration];
2058
+ if (
2059
+ !declaration ||
2060
+ typeof declaration !== 'object' ||
2061
+ Array.isArray(declaration) ||
2062
+ Object.keys(declaration).length === 0 ||
2063
+ Object.values(declaration).some((target) => typeof target !== 'string')
2064
+ ) {
2065
+ throw new Error(
2066
+ 'Package ' +
2067
+ packageName +
2068
+ ' has an invalid conditional export for ' +
2069
+ exportName +
2070
+ '.',
2071
+ );
2072
+ }
2073
+ return Object.values(declaration);
2074
+ }
2075
+
2076
+ function validateContractExports(root, packageJson, publications) {
2077
+ const exports = packageJson.exports;
2078
+ const packagePrefix = packageJson.name + '/';
2079
+ const requiredExports = new Set();
2080
+ for (const publication of publications) {
2081
+ if (publication === packagePrefix + 'api-contract') {
2082
+ requiredExports.add('./api-client');
2083
+ requiredExports.add('./api-contract');
2084
+ } else if (publication === packagePrefix + 'contracts') {
2085
+ requiredExports.add('./contracts');
2086
+ }
2087
+ }
2088
+ for (const exportName of [...requiredExports].sort()) {
2089
+ const expected = allowedContractExports.get(exportName);
2090
+ if (!expected) {
2091
+ throw new Error(
2092
+ 'Package ' +
2093
+ packageJson.name +
2094
+ ' requires an unsupported contract export ' +
2095
+ exportName +
2096
+ '.',
2097
+ );
2098
+ }
2099
+ if (!exports || !Object.hasOwn(exports, exportName)) {
2100
+ throw new Error(
2101
+ 'Package ' +
2102
+ packageJson.name +
2103
+ ' is missing contract export ' +
2104
+ exportName +
2105
+ '.',
2106
+ );
2107
+ }
2108
+ for (const target of declaredExportTargets(
2109
+ exports[exportName],
2110
+ packageJson.name,
2111
+ exportName,
2112
+ )) {
2113
+ if (!target.startsWith('./')) {
2114
+ throw new Error(
2115
+ 'Package ' +
2116
+ packageJson.name +
2117
+ ' contract export ' +
2118
+ exportName +
2119
+ ' must use a relative package target.',
2120
+ );
2121
+ }
2122
+ const absoluteTarget = resolve(root, target);
2123
+ if (
2124
+ !isContained(workspaceRoot, absoluteTarget) ||
2125
+ !isContained(root, absoluteTarget) ||
2126
+ !existsSync(absoluteTarget) ||
2127
+ !statSync(absoluteTarget).isFile()
2128
+ ) {
2129
+ throw new Error(
2130
+ 'Package ' +
2131
+ packageJson.name +
2132
+ ' contract export ' +
2133
+ exportName +
2134
+ ' points outside its package or to a missing file.',
2135
+ );
2136
+ }
2137
+ const realTarget = realpathSync(absoluteTarget);
2138
+ if (
2139
+ !isContained(realpathSync(workspaceRoot), realTarget) ||
2140
+ !isContained(realpathSync(root), realTarget)
2141
+ ) {
2142
+ throw new Error(
2143
+ 'Package ' +
2144
+ packageJson.name +
2145
+ ' contract export ' +
2146
+ exportName +
2147
+ ' escapes the repository through an aliased target.',
2148
+ );
2149
+ }
2150
+ const targetFromPackage = relative(root, absoluteTarget)
2151
+ .split(sep)
2152
+ .join('/');
2153
+ const expectedSurface = expected.exact ?? expected.surface;
2154
+ const mapsToSurface =
2155
+ expected.exact !== undefined
2156
+ ? targetFromPackage === expected.exact
2157
+ : targetFromPackage.endsWith('.ts') &&
2158
+ isContained(join(root, expectedSurface), absoluteTarget) &&
2159
+ absoluteTarget !== join(root, expectedSurface);
2160
+ if (!mapsToSurface) {
2161
+ throw new Error(
2162
+ 'Package ' +
2163
+ packageJson.name +
2164
+ ' contract export ' +
2165
+ exportName +
2166
+ ' is remapped outside its corresponding contract surface.',
2167
+ );
2168
+ }
2169
+ }
2170
+ }
2171
+ }
2172
+
2173
+ const declaration = readJson(declarationPath);
2174
+ if (
2175
+ !declaration ||
2176
+ typeof declaration !== 'object' ||
2177
+ Array.isArray(declaration) ||
2178
+ declaration.schemaVersion !== 1 ||
2179
+ !Array.isArray(declaration.consumes) ||
2180
+ Object.keys(declaration).some(
2181
+ (key) => !['consumes', 'schemaVersion'].includes(key),
2182
+ )
2183
+ ) {
2184
+ throw new Error(
2185
+ 'contracts/dependencies.json must be a v1 consumes declaration.',
2186
+ );
2187
+ }
2188
+ const ownership = readJson(ownershipPath);
2189
+ const [normalized] = normalizeApiContractProjectDeclarations([
2190
+ {
2191
+ contracts: {
2192
+ consumes: declaration.consumes,
2193
+ publishes: ownership.contracts?.publishes ?? [],
2194
+ },
2195
+ project: '${name}',
2196
+ },
2197
+ ]);
2198
+ if (!normalized) {
2199
+ throw new Error('The contract dependency declaration did not normalize.');
2200
+ }
2201
+
2202
+ const packagesRoot = join(workspaceRoot, 'packages');
2203
+ const projects = new Map();
2204
+ const packageNames = new Set();
2205
+ const declarations = [];
2206
+ for (const entry of readdirSync(packagesRoot, { withFileTypes: true })) {
2207
+ if (!entry.isDirectory() || entry.name === 'foundation') continue;
2208
+ const root = join(packagesRoot, entry.name);
2209
+ const candidateOwnershipPath = join(root, '.ebk', 'ownership.json');
2210
+ if (!existsSync(candidateOwnershipPath)) continue;
2211
+ const candidateOwnership =
2212
+ root === projectRoot
2213
+ ? {
2214
+ ...ownership,
2215
+ contracts: {
2216
+ ...ownership.contracts,
2217
+ consumes: normalized.contracts.consumes,
2218
+ },
2219
+ }
2220
+ : readJson(candidateOwnershipPath);
2221
+ const validation = validateGeneratedOwnershipRecord(candidateOwnership);
2222
+ if (!validation.valid) {
2223
+ throw new Error(
2224
+ 'Product Slice ' +
2225
+ entry.name +
2226
+ ' has invalid ownership metadata: ' +
2227
+ JSON.stringify(validation.issues),
2228
+ );
2229
+ }
2230
+ const project = validation.value.slice;
2231
+ const packageJson = readJson(join(root, 'package.json'));
2232
+ if (
2233
+ typeof packageJson.name !== 'string' ||
2234
+ packageJson.name.length === 0 ||
2235
+ projects.has(project) ||
2236
+ packageNames.has(packageJson.name)
2237
+ ) {
2238
+ throw new Error(
2239
+ 'Product Slice projects and package names must be unique and explicit.',
2240
+ );
2241
+ }
2242
+ packageNames.add(packageJson.name);
2243
+ validateContractExports(
2244
+ root,
2245
+ packageJson,
2246
+ validation.value.contracts.publishes,
2247
+ );
2248
+ projects.set(project, { packageJson, root });
2249
+ declarations.push({
2250
+ contracts: validation.value.contracts,
2251
+ project,
2252
+ });
2253
+ }
2254
+ if (!projects.has('${name}')) {
2255
+ throw new Error(
2256
+ 'The current Product Slice is absent from workspace ownership.',
2257
+ );
2258
+ }
2259
+ const resolution = resolveApiContractDependencies(declarations);
2260
+ for (const publication of resolution.contracts) {
2261
+ const producer = projects.get(publication.producer);
2262
+ if (!producer) {
2263
+ throw new Error(
2264
+ 'Resolved contract producer ' + publication.producer + ' is absent.',
2265
+ );
2266
+ }
2267
+ const prefix = producer.packageJson.name + '/';
2268
+ if (!publication.contract.startsWith(prefix)) {
2269
+ throw new Error(
2270
+ 'Published contract ' +
2271
+ publication.contract +
2272
+ ' is outside producer package ' +
2273
+ producer.packageJson.name +
2274
+ '.',
2275
+ );
2276
+ }
2277
+ const exportName = './' + publication.contract.slice(prefix.length);
2278
+ if (!allowedContractExports.has(exportName)) {
2279
+ throw new Error(
2280
+ 'Published contract ' +
2281
+ publication.contract +
2282
+ ' does not use an allowed package export ' +
2283
+ exportName +
2284
+ '.',
2285
+ );
2286
+ }
2287
+ for (const consumerName of publication.consumers) {
2288
+ const consumer = projects.get(consumerName);
2289
+ const version =
2290
+ consumer?.packageJson.dependencies?.[producer.packageJson.name];
2291
+ if (typeof version !== 'string' || !version.startsWith('workspace:')) {
2292
+ throw new Error(
2293
+ 'Consumed contract ' +
2294
+ publication.contract +
2295
+ ' requires ' +
2296
+ consumerName +
2297
+ ' to declare a workspace dependency on ' +
2298
+ producer.packageJson.name +
2299
+ '.',
2300
+ );
2301
+ }
2302
+ }
2303
+ }
2304
+ const current = [...(ownership.contracts?.consumes ?? [])].sort();
2305
+ const expected = [...normalized.contracts.consumes];
2306
+ if (action === 'check') {
2307
+ if (JSON.stringify(current) !== JSON.stringify(expected)) {
2308
+ throw new Error(
2309
+ 'Contract declarations are out of sync. Run ' +
2310
+ 'pnpm nx run ${name}:contract-dependencies-sync.',
2311
+ );
2312
+ }
2313
+ process.stdout.write(
2314
+ JSON.stringify({
2315
+ action,
2316
+ consumes: expected,
2317
+ project: '${name}',
2318
+ schemaVersion: 1,
2319
+ }) + '\\n',
2320
+ );
2321
+ } else {
2322
+ const candidate = {
2323
+ ...ownership,
2324
+ contracts: {
2325
+ ...ownership.contracts,
2326
+ consumes: expected,
2327
+ },
2328
+ };
2329
+ const validation = validateGeneratedOwnershipRecord(candidate);
2330
+ if (!validation.valid) {
2331
+ throw new Error(
2332
+ 'Contract dependency sync produced invalid ownership: ' +
2333
+ JSON.stringify(validation.issues),
2334
+ );
2335
+ }
2336
+ writeFileSync(
2337
+ ownershipPath,
2338
+ JSON.stringify(validation.value, null, 2) + '\\n',
2339
+ 'utf8',
2340
+ );
2341
+ process.stdout.write(
2342
+ JSON.stringify({
2343
+ action,
2344
+ consumes: expected,
2345
+ project: '${name}',
2346
+ schemaVersion: 1,
2347
+ }) + '\\n',
2348
+ );
2349
+ }
2350
+ `,
2351
+ 'scripts/api-contract.mjs': `import { createHash } from 'node:crypto';
2352
+ import { execFileSync } from 'node:child_process';
2353
+ import {
2354
+ mkdirSync,
2355
+ readFileSync,
2356
+ rmSync,
2357
+ writeFileSync,
2358
+ } from 'node:fs';
2359
+ import { createRequire } from 'node:module';
2360
+ import { join, resolve } from 'node:path';
2361
+ import { createApiContractArtifacts } from '@empire-builder-kit/runtime/api-contract';
2362
+ import { ${contractIdentifier} } from '../api/contracts/protected.ts';
2363
+
2364
+ const require = createRequire(import.meta.url);
2365
+ const {
2366
+ authorizeApiContractBaselineUpdate,
2367
+ compareApiContracts,
2368
+ createApiContractCompatibilityEvidence,
2369
+ planApiContractBaselineUpdate,
2370
+ } = require('@empire-builder-kit/nx/api-contract');
2371
+ const {
2372
+ createTestingEvidenceFromRunnerAttempts,
2373
+ inspectTestingEvidenceArtifact,
2374
+ normalizeVitestEvidenceAttempt,
2375
+ } = require('@empire-builder-kit/nx/testing-evidence');
2376
+ const {
2377
+ validateGeneratedOwnershipRecord,
2378
+ } = require('@empire-builder-kit/nx/ownership');
2379
+
2380
+ const projectRoot = process.cwd();
2381
+ const workspaceRoot = resolve(projectRoot, '../..');
2382
+ const generatedRoot = join(projectRoot, 'api', 'generated');
2383
+ const evidenceRoot = join(projectRoot, '.ebk', 'evidence');
2384
+ const ownershipPath = join(projectRoot, '.ebk', 'ownership.json');
2385
+ const normalizedPath = join(generatedRoot, 'contract.json');
2386
+ const openApiPath = join(generatedRoot, 'openapi.json');
2387
+ const baselinePath = join(generatedRoot, 'baseline.json');
2388
+ const reportPath = join(evidenceRoot, 'api-contract-compatibility.json');
2389
+ const resultPath = join(evidenceRoot, 'api-contract.json');
2390
+ const readJson = (path) => JSON.parse(readFileSync(path, 'utf8'));
2391
+ const workspacePackage = readJson(join(workspaceRoot, 'package.json'));
2392
+ const ownership = readJson(ownershipPath);
2393
+ const artifacts = createApiContractArtifacts(${contractIdentifier});
2394
+ const action = process.argv[2] ?? 'check';
2395
+ const digest = (contents) =>
2396
+ 'sha256:' + createHash('sha256').update(contents).digest('hex');
2397
+
2398
+ function sourceIdentity() {
2399
+ const commit =
2400
+ process.env.EBK_SOURCE_COMMIT ??
2401
+ execFileSync('git', ['rev-parse', 'HEAD'], {
2402
+ cwd: workspaceRoot,
2403
+ encoding: 'utf8',
2404
+ }).trim();
2405
+ const frameworkCandidate =
2406
+ workspacePackage.dependencies?.['@empire-builder-kit/runtime'];
2407
+ if (typeof frameworkCandidate !== 'string' || !frameworkCandidate) {
2408
+ throw new Error('The workspace runtime candidate is unavailable.');
2409
+ }
2410
+ return {
2411
+ blueprintCandidates: [
2412
+ ownership.blueprint.name + '@' + ownership.blueprint.version,
2413
+ ],
2414
+ commit,
2415
+ frameworkCandidate,
2416
+ };
2417
+ }
2418
+
2419
+ function writeManagedArtifacts() {
2420
+ mkdirSync(generatedRoot, { recursive: true });
2421
+ writeFileSync(normalizedPath, artifacts.normalizedJson, 'utf8');
2422
+ writeFileSync(openApiPath, artifacts.openApiJson, 'utf8');
2423
+ }
2424
+
2425
+ function restampManagedArtifacts() {
2426
+ const managedArtifacts = new Map([
2427
+ ['api/generated/contract.json', artifacts.normalizedJson],
2428
+ ['api/generated/openapi.json', artifacts.openApiJson],
2429
+ ]);
2430
+ const restamped = new Set();
2431
+ const candidate = {
2432
+ ...ownership,
2433
+ paths: ownership.paths.map((entry) => {
2434
+ const contents = managedArtifacts.get(entry.path);
2435
+ if (contents === undefined) return entry;
2436
+ if (entry.mode !== 'managed' || entry.managedJsonPointers !== undefined) {
2437
+ throw new Error(
2438
+ 'API contract generation can restamp only whole-file managed artifacts.',
2439
+ );
2440
+ }
2441
+ restamped.add(entry.path);
2442
+ return {
2443
+ ...entry,
2444
+ sha256: createHash('sha256').update(contents).digest('hex'),
2445
+ };
2446
+ }),
2447
+ };
2448
+ if (restamped.size !== managedArtifacts.size) {
2449
+ throw new Error(
2450
+ 'API contract generation could not find every managed artifact in ownership metadata.',
2451
+ );
2452
+ }
2453
+ const validation = validateGeneratedOwnershipRecord(candidate);
2454
+ if (!validation.valid) {
2455
+ throw new Error(
2456
+ 'API contract generation produced invalid ownership metadata: ' +
2457
+ JSON.stringify(validation.issues),
2458
+ );
2459
+ }
2460
+ writeFileSync(
2461
+ ownershipPath,
2462
+ JSON.stringify(validation.value, null, 2) + '\\n',
2463
+ 'utf8',
2464
+ );
2465
+ }
2466
+
2467
+ function approvalPath() {
2468
+ const inline = process.argv.find((value) => value.startsWith('--approval='));
2469
+ if (inline) return inline.slice('--approval='.length);
2470
+ const index = process.argv.indexOf('--approval');
2471
+ return index >= 0 ? process.argv[index + 1] : undefined;
2472
+ }
2473
+
2474
+ if (action === 'generate') {
2475
+ writeManagedArtifacts();
2476
+ restampManagedArtifacts();
2477
+ process.stdout.write(
2478
+ JSON.stringify({
2479
+ action,
2480
+ baselineUpdated: false,
2481
+ normalizedDigest: digest(artifacts.normalizedJson),
2482
+ openApiDigest: digest(artifacts.openApiJson),
2483
+ }) + '\\n',
2484
+ );
2485
+ } else if (action === 'baseline') {
2486
+ const currentBaseline = readJson(baselinePath);
2487
+ const plan = planApiContractBaselineUpdate(
2488
+ currentBaseline,
2489
+ artifacts.normalized,
2490
+ );
2491
+ if (plan.disposition === 'no-change') {
2492
+ process.stdout.write(
2493
+ JSON.stringify({
2494
+ action,
2495
+ baselineUpdated: false,
2496
+ candidateDigest: plan.candidate.digest,
2497
+ disposition: plan.disposition,
2498
+ }) + '\\n',
2499
+ );
2500
+ } else {
2501
+ const path = approvalPath();
2502
+ if (!path) {
2503
+ throw new Error(
2504
+ 'A baseline update requires --approval=<reviewed-json-path>.',
2505
+ );
2506
+ }
2507
+ const authorization = authorizeApiContractBaselineUpdate(
2508
+ plan,
2509
+ readJson(resolve(projectRoot, path)),
2510
+ );
2511
+ writeFileSync(baselinePath, authorization.candidateJson, 'utf8');
2512
+ process.stdout.write(
2513
+ JSON.stringify({
2514
+ acceptedClassification: authorization.acceptedClassification,
2515
+ action,
2516
+ baselineDigest: authorization.baselineDigest,
2517
+ baselineUpdated: true,
2518
+ candidateDigest: authorization.candidateDigest,
2519
+ }) + '\\n',
2520
+ );
2521
+ }
2522
+ } else if (action === 'check') {
2523
+ const startedAt = new Date().toISOString();
2524
+ mkdirSync(evidenceRoot, { recursive: true });
2525
+ rmSync(reportPath, { force: true });
2526
+ rmSync(resultPath, { force: true });
2527
+ try {
2528
+ const baseline = readJson(baselinePath);
2529
+ const report = compareApiContracts(baseline, artifacts.normalized);
2530
+ const reportJson = JSON.stringify(report, null, 2) + '\\n';
2531
+ const reportInspection = inspectTestingEvidenceArtifact({
2532
+ contents: reportJson,
2533
+ });
2534
+ const generatedDrift =
2535
+ readFileSync(normalizedPath, 'utf8') !== artifacts.normalizedJson ||
2536
+ readFileSync(openApiPath, 'utf8') !== artifacts.openApiJson;
2537
+ const completedAt = new Date().toISOString();
2538
+ const retainedArtifacts = [];
2539
+ if (reportInspection.safe) {
2540
+ writeFileSync(reportPath, reportJson, 'utf8');
2541
+ retainedArtifacts.push({
2542
+ digest: digest(reportJson),
2543
+ name: '.ebk/evidence/api-contract-compatibility.json',
2544
+ retentionClass: 'source-result',
2545
+ });
2546
+ }
2547
+ const evidenceOptions = {
2548
+ artifacts: retainedArtifacts,
2549
+ commandVersion: '1',
2550
+ completedAt,
2551
+ project: '${name}',
2552
+ report,
2553
+ source: sourceIdentity(),
2554
+ startedAt,
2555
+ target: 'api-contract-check',
2556
+ workspace: workspacePackage.name,
2557
+ };
2558
+ const result =
2559
+ generatedDrift || !reportInspection.safe
2560
+ ? createTestingEvidenceFromRunnerAttempts({
2561
+ artifacts: retainedArtifacts,
2562
+ attempts: [
2563
+ normalizeVitestEvidenceAttempt({
2564
+ attempt: 1,
2565
+ completedAt,
2566
+ failed: 1,
2567
+ findings: [
2568
+ {
2569
+ classification: generatedDrift
2570
+ ? 'environment-drift'
2571
+ : 'sensitive-artifact',
2572
+ summary: generatedDrift
2573
+ ? 'Managed API artifacts differ from the authoritative contract.'
2574
+ : 'The API compatibility report matched protected artifact data and was not retained.',
2575
+ },
2576
+ ],
2577
+ passed: 0,
2578
+ skipped: 0,
2579
+ startedAt,
2580
+ }),
2581
+ ],
2582
+ cleanup: { outcome: 'not-required' },
2583
+ environment: { class: 'source', deployed: false },
2584
+ operation: {
2585
+ commandVersion: '1',
2586
+ project: '${name}',
2587
+ proofLayer: 'contract-compatibility',
2588
+ target: 'api-contract-check',
2589
+ },
2590
+ proofStarted: true,
2591
+ slice: '${name}',
2592
+ source: evidenceOptions.source,
2593
+ workspace: workspacePackage.name,
2594
+ })
2595
+ : createApiContractCompatibilityEvidence(evidenceOptions);
2596
+ writeFileSync(
2597
+ resultPath,
2598
+ JSON.stringify(result, null, 2) + '\\n',
2599
+ 'utf8',
2600
+ );
2601
+ process.stdout.write(JSON.stringify(result) + '\\n');
2602
+ if (result.outcome !== 'passed') process.exitCode = 1;
2603
+ } catch (error) {
2604
+ const completedAt = new Date().toISOString();
2605
+ const missing =
2606
+ error &&
2607
+ typeof error === 'object' &&
2608
+ 'code' in error &&
2609
+ error.code === 'ENOENT';
2610
+ const result = createTestingEvidenceFromRunnerAttempts({
2611
+ artifacts: [],
2612
+ attempts: [],
2613
+ cleanup: { outcome: 'not-required' },
2614
+ environment: { class: 'source', deployed: false },
2615
+ operation: {
2616
+ commandVersion: '1',
2617
+ project: '${name}',
2618
+ proofLayer: 'contract-compatibility',
2619
+ target: 'api-contract-check',
2620
+ },
2621
+ preflight: {
2622
+ completedAt,
2623
+ findings: [
2624
+ {
2625
+ classification: missing
2626
+ ? 'prerequisite-missing'
2627
+ : 'environment-drift',
2628
+ summary: missing
2629
+ ? 'A required API contract artifact or baseline is missing.'
2630
+ : 'A required API contract artifact or baseline is invalid.',
2631
+ },
2632
+ ],
2633
+ startedAt,
2634
+ },
2635
+ proofStarted: false,
2636
+ slice: '${name}',
2637
+ source: sourceIdentity(),
2638
+ workspace: workspacePackage.name,
2639
+ });
2640
+ writeFileSync(
2641
+ resultPath,
2642
+ JSON.stringify(result, null, 2) + '\\n',
2643
+ 'utf8',
2644
+ );
2645
+ process.stdout.write(JSON.stringify(result) + '\\n');
2646
+ process.exitCode = 1;
2647
+ }
2648
+ } else {
2649
+ throw new Error(
2650
+ 'Usage: node scripts/api-contract.mjs <check|generate|baseline>',
2651
+ );
2652
+ }
2653
+ `,
2654
+ };
2655
+ }
2656
+ //# sourceMappingURL=built-in-plan-api-contract-files.js.map