@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,2314 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderProductAuthorizationFiles = renderProductAuthorizationFiles;
4
+ const built_in_plan_shared_js_1 = require("./built-in-plan-shared.js");
5
+ /** @internal */
6
+ function renderProductAuthorizationFiles(name, pascalName) {
7
+ const identifierPrefix = (0, built_in_plan_shared_js_1.lowerCamelIdentifier)(pascalName);
8
+ return {
9
+ 'authorization/policy.ts': `import {
10
+ defineAuthorizationPolicy,
11
+ defineCoarseAdmission,
12
+ type AuthorizationContext,
13
+ type AuthorizationInput,
14
+ type AuthorizationResource,
15
+ } from '@empire-builder-kit/runtime/authorization';
16
+
17
+ export const ${identifierPrefix}AuthorizationActions = {
18
+ approvalReview: '${name}:approval-review',
19
+ dataExportCleanup: '${name}:data-export-cleanup',
20
+ databaseRead: '${name}:database-read',
21
+ eventPublish: '${name}:event-publish',
22
+ lifecycleConsume: '${name}:lifecycle-consume',
23
+ machineProofRead: '${name}:machine-proof-read',
24
+ protectedRead: '${name}:protected-read',
25
+ recordDelegationIssue: '${name}:record-delegation-issue',
26
+ recordDelegationRevoke: '${name}:record-delegation-revoke',
27
+ recordDelegationUse: '${name}:record-delegation-use',
28
+ recordDelete: '${name}:record-delete',
29
+ recordExport: '${name}:record-export',
30
+ recordExportCleanup: '${name}:record-export-cleanup',
31
+ recordHoldManage: '${name}:record-hold-manage',
32
+ recordRead: '${name}:record-read',
33
+ recordWrite: '${name}:record-write',
34
+ retentionApply: '${name}:retention-apply',
35
+ retentionMaintenance: '${name}:retention-maintenance',
36
+ retentionReport: '${name}:retention-report',
37
+ retentionReview: '${name}:retention-review',
38
+ } as const;
39
+
40
+ export type ${pascalName}AuthorizationAction =
41
+ (typeof ${identifierPrefix}AuthorizationActions)[keyof typeof ${identifierPrefix}AuthorizationActions];
42
+
43
+ /**
44
+ * Cognito resource-server scopes are not application action identifiers.
45
+ * Keep this mapping explicit so adding an action never grants it to the
46
+ * Standard confidential client implicitly.
47
+ */
48
+ export function ${identifierPrefix}MachineScopes(stage: string) {
49
+ if (!/^[a-z][a-z0-9-]{0,62}$/.test(stage)) {
50
+ throw new Error('Machine authorization requires a safe deployed stage.');
51
+ }
52
+ const resourceServer = '${name}-' + stage;
53
+ return {
54
+ delegationUse: resourceServer + '/delegation-use',
55
+ proofReader: resourceServer + '/proof-read',
56
+ } as const;
57
+ }
58
+
59
+ export function ${identifierPrefix}MachineScopeForAction(
60
+ action: ${pascalName}AuthorizationAction,
61
+ stage: string,
62
+ ): string | undefined {
63
+ const scopes = ${identifierPrefix}MachineScopes(stage);
64
+ switch (action) {
65
+ case ${identifierPrefix}AuthorizationActions.machineProofRead:
66
+ return scopes.proofReader;
67
+ case ${identifierPrefix}AuthorizationActions.recordDelegationUse:
68
+ return scopes.delegationUse;
69
+ default:
70
+ return undefined;
71
+ }
72
+ }
73
+
74
+ export interface ${pascalName}ResourceAttributes {
75
+ collection?: boolean;
76
+ ownerId?: string;
77
+ syntheticTestData?: boolean;
78
+ }
79
+
80
+ export type ${pascalName}AuthorizationResource = AuthorizationResource<
81
+ 'record' | 'slice',
82
+ Readonly<${pascalName}ResourceAttributes>
83
+ >;
84
+
85
+ export type ${pascalName}AuthorizationInput = AuthorizationInput<
86
+ ${pascalName}AuthorizationAction,
87
+ ${pascalName}AuthorizationResource,
88
+ AuthorizationContext<Readonly<{ operationId: string }>>
89
+ >;
90
+
91
+ const recordActions = new Set<${pascalName}AuthorizationAction>([
92
+ ${identifierPrefix}AuthorizationActions.recordDelegationIssue,
93
+ ${identifierPrefix}AuthorizationActions.recordDelegationRevoke,
94
+ ${identifierPrefix}AuthorizationActions.recordDelegationUse,
95
+ ${identifierPrefix}AuthorizationActions.recordDelete,
96
+ ${identifierPrefix}AuthorizationActions.recordExport,
97
+ ${identifierPrefix}AuthorizationActions.recordExportCleanup,
98
+ ${identifierPrefix}AuthorizationActions.recordHoldManage,
99
+ ${identifierPrefix}AuthorizationActions.recordRead,
100
+ ${identifierPrefix}AuthorizationActions.recordWrite,
101
+ ]);
102
+
103
+ export function ${identifierPrefix}InternalWorkloadIdentityForAction(
104
+ action: ${pascalName}AuthorizationAction,
105
+ ): string | undefined {
106
+ switch (action) {
107
+ case ${identifierPrefix}AuthorizationActions.lifecycleConsume:
108
+ return '${name}:event-consumer';
109
+ case ${identifierPrefix}AuthorizationActions.dataExportCleanup:
110
+ return '${name}:data-export-cleanup';
111
+ case ${identifierPrefix}AuthorizationActions.retentionApply:
112
+ case ${identifierPrefix}AuthorizationActions.retentionMaintenance:
113
+ case ${identifierPrefix}AuthorizationActions.retentionReport:
114
+ return '${name}:data-retention-job';
115
+ default:
116
+ return undefined;
117
+ }
118
+ }
119
+
120
+ export function create${pascalName}CoarseAdmission(stage: string) {
121
+ return defineCoarseAdmission({
122
+ anyOf: [
123
+ {
124
+ kinds: ['admin', 'customer'],
125
+ subjectTypes: ['user'],
126
+ },
127
+ {
128
+ anyScope: Object.values(${identifierPrefix}MachineScopes(stage)),
129
+ kinds: ['agent'],
130
+ subjectTypes: ['service'],
131
+ },
132
+ ],
133
+ });
134
+ }
135
+
136
+ /**
137
+ * Product actions and rules are seeded and Slice-owned. Keep policy inputs
138
+ * minimal and advance the version whenever observable allow/deny behavior
139
+ * changes.
140
+ */
141
+ export const ${identifierPrefix}AuthorizationPolicy =
142
+ defineAuthorizationPolicy<${pascalName}AuthorizationInput>({
143
+ version: '1.0.0',
144
+ evaluate(input) {
145
+ const { action, principal, resource } = input;
146
+
147
+ const internalWorkloadIdentity =
148
+ ${identifierPrefix}InternalWorkloadIdentityForAction(action);
149
+ if (internalWorkloadIdentity !== undefined) {
150
+ return principal.kind === 'agent' &&
151
+ principal.actor.type === 'service' &&
152
+ principal.actor.id === internalWorkloadIdentity &&
153
+ principal.subject.id === internalWorkloadIdentity &&
154
+ principal.authority.mode === 'machine' &&
155
+ principal.authority.machineIdentityId === internalWorkloadIdentity &&
156
+ principal.scopes.length === 0 &&
157
+ resource.type === 'slice' &&
158
+ resource.attributes.collection === true
159
+ ? { decision: 'allow' }
160
+ : { decision: 'deny' };
161
+ }
162
+
163
+ if (
164
+ action ===
165
+ ${identifierPrefix}AuthorizationActions.machineProofRead &&
166
+ (principal.kind !== 'agent' ||
167
+ principal.actor.type !== 'service' ||
168
+ principal.subject.type !== 'service' ||
169
+ principal.authority.mode !== 'machine')
170
+ ) {
171
+ return { decision: 'deny' };
172
+ }
173
+
174
+ const directHuman =
175
+ principal.actor.type === 'user' &&
176
+ principal.subject.type === 'user' &&
177
+ principal.authority.mode === 'direct';
178
+ if (
179
+ action === ${identifierPrefix}AuthorizationActions.recordWrite &&
180
+ resource.attributes.syntheticTestData === true &&
181
+ (!directHuman ||
182
+ !principal.roles.includes('${name}-test-writer'))
183
+ ) {
184
+ return { decision: 'deny' };
185
+ }
186
+ if (
187
+ action === ${identifierPrefix}AuthorizationActions.recordExport
188
+ ) {
189
+ return directHuman &&
190
+ resource.type === 'record' &&
191
+ resource.attributes.ownerId === principal.actor.id
192
+ ? { decision: 'allow' }
193
+ : { decision: 'deny' };
194
+ }
195
+ if (
196
+ action ===
197
+ ${identifierPrefix}AuthorizationActions.recordExportCleanup ||
198
+ action === ${identifierPrefix}AuthorizationActions.recordHoldManage
199
+ ) {
200
+ return directHuman && principal.kind === 'admin'
201
+ ? { decision: 'allow' }
202
+ : { decision: 'deny' };
203
+ }
204
+
205
+ // A direct, authenticated admin remains an independently testable
206
+ // recovery authority. No generated universal break-glass role exists.
207
+ if (
208
+ principal.kind === 'admin' &&
209
+ principal.actor.type === 'user' &&
210
+ principal.authority.mode === 'direct'
211
+ ) {
212
+ return { decision: 'allow' };
213
+ }
214
+
215
+ if (
216
+ action === ${identifierPrefix}AuthorizationActions.approvalReview ||
217
+ action === ${identifierPrefix}AuthorizationActions.retentionReview
218
+ ) {
219
+ return { decision: 'deny' };
220
+ }
221
+
222
+ // Cognito client-credentials callers are admitted only for an exact
223
+ // action scope; an audience match alone never authorizes.
224
+ if (
225
+ principal.kind === 'agent' &&
226
+ principal.actor.type === 'service' &&
227
+ principal.authority.mode === 'machine'
228
+ ) {
229
+ const requiredScope = ${identifierPrefix}MachineScopeForAction(
230
+ action,
231
+ input.context.stage,
232
+ );
233
+ return requiredScope !== undefined &&
234
+ principal.scopes.includes(requiredScope)
235
+ ? { decision: 'allow' }
236
+ : { decision: 'deny' };
237
+ }
238
+
239
+ if (!recordActions.has(action)) {
240
+ return principal.actor.type === 'user' &&
241
+ principal.authority.mode === 'direct'
242
+ ? { decision: 'allow' }
243
+ : { decision: 'deny' };
244
+ }
245
+
246
+ // The use endpoint is admitted only for the generated machine scope.
247
+ // Its second decision is evaluated below under delegated authority.
248
+ if (
249
+ action === ${identifierPrefix}AuthorizationActions.recordDelegationUse
250
+ ) {
251
+ return { decision: 'deny' };
252
+ }
253
+
254
+ const effectiveOwner =
255
+ principal.authority.mode === 'delegated'
256
+ ? principal.authority.delegatedBy.id
257
+ : principal.actor.type === 'user' &&
258
+ principal.authority.mode === 'direct'
259
+ ? principal.actor.id
260
+ : undefined;
261
+ return resource.type === 'record' &&
262
+ effectiveOwner !== undefined &&
263
+ resource.attributes.ownerId === effectiveOwner
264
+ ? { decision: 'allow' }
265
+ : { decision: 'deny' };
266
+ },
267
+ });
268
+ `,
269
+ 'authorization/runtime.ts': `import { createHash } from 'node:crypto';
270
+ import type { RuntimeHttpEvent } from '@empire-builder-kit/runtime';
271
+ import {
272
+ createBetterAuthConfig,
273
+ type Principal,
274
+ } from '@empire-builder-kit/runtime/auth';
275
+ import { createAuthGuard } from '@empire-builder-kit/runtime/auth-backend';
276
+ import type { ApiAuthorizationInput } from '@empire-builder-kit/runtime/api-server';
277
+ import type { ApiOperationDefinition } from '@empire-builder-kit/runtime/api-contract';
278
+ import {
279
+ createAuthorizationEvaluator,
280
+ composeAuthorizationPrincipal,
281
+ createDirectAuthorizationPrincipal,
282
+ createMachineAuthorizationPrincipal,
283
+ defineCoarseAdmission,
284
+ toAuthorizationAuditRecord,
285
+ type AuthorizationDecision,
286
+ type AuthorizationDecisionSinkInput,
287
+ type AuthorizationObligation,
288
+ type AuthorizationPrincipal,
289
+ } from '@empire-builder-kit/runtime/authorization';
290
+ import { isBoundedSafeReference } from '@empire-builder-kit/runtime/safe-reference';
291
+ import { withPrimaryDatabase } from '../database/runtime-client.js';
292
+ import {
293
+ ${identifierPrefix}AuthorizationActions,
294
+ ${identifierPrefix}MachineScopes,
295
+ ${identifierPrefix}AuthorizationPolicy,
296
+ create${pascalName}CoarseAdmission,
297
+ type ${pascalName}AuthorizationAction,
298
+ type ${pascalName}AuthorizationInput,
299
+ type ${pascalName}AuthorizationResource,
300
+ } from './policy.js';
301
+
302
+ let guard: ReturnType<typeof createAuthGuard> | undefined;
303
+
304
+ function acceptedMachineClientIds(): readonly string[] {
305
+ const current = process.env.AUTH_MACHINE_CLIENT_ID;
306
+ const encoded = process.env.AUTH_MACHINE_ACCEPTED_CLIENT_IDS;
307
+ if (current === undefined && encoded === undefined) return [];
308
+ if (!current || !encoded || !isBoundedSafeReference(current)) {
309
+ throw new Error('Machine authorization client configuration is invalid.');
310
+ }
311
+ let candidate: unknown;
312
+ try {
313
+ candidate = JSON.parse(encoded);
314
+ } catch {
315
+ throw new Error('Machine authorization client configuration is invalid.');
316
+ }
317
+ if (
318
+ !Array.isArray(candidate) ||
319
+ candidate.length < 1 ||
320
+ candidate.length > 2 ||
321
+ new Set(candidate).size !== candidate.length ||
322
+ candidate.some(
323
+ (clientId) =>
324
+ typeof clientId !== 'string' ||
325
+ !isBoundedSafeReference(clientId),
326
+ ) ||
327
+ !candidate.includes(current)
328
+ ) {
329
+ throw new Error('Machine authorization client configuration is invalid.');
330
+ }
331
+ return Object.freeze([...candidate] as string[]);
332
+ }
333
+
334
+ function getGuard() {
335
+ const stage = process.env.EBK_STAGE ?? '';
336
+ const webClientId = process.env.AUTH_CLIENT_ID ?? '';
337
+ const machineClientIds = acceptedMachineClientIds();
338
+ return guard ??= createAuthGuard({
339
+ config: createBetterAuthConfig({
340
+ clientId: webClientId,
341
+ region: process.env.AWS_REGION ?? '',
342
+ userPoolId: process.env.AUTH_USER_POOL_ID ?? '',
343
+ }),
344
+ verifierOptions: {
345
+ acceptedClientIds: [webClientId, ...machineClientIds],
346
+ },
347
+ policy: {
348
+ admin: { groups: ['${name}-admin'] },
349
+ agent: {
350
+ scopes: Object.values(${identifierPrefix}MachineScopes(stage)),
351
+ },
352
+ defaultKind: 'customer',
353
+ },
354
+ });
355
+ }
356
+
357
+ function operationAction(
358
+ operation: ApiOperationDefinition,
359
+ ): ${pascalName}AuthorizationAction {
360
+ if (operation.authorizationActions.length !== 1) {
361
+ throw new Error(
362
+ 'Standard protected operations require exactly one Slice-owned authorization action.',
363
+ );
364
+ }
365
+ const action = operation.authorizationActions[0];
366
+ if (
367
+ !Object.values(${identifierPrefix}AuthorizationActions).includes(
368
+ action as ${pascalName}AuthorizationAction,
369
+ )
370
+ ) {
371
+ throw new Error('The API operation declares an unknown authorization action.');
372
+ }
373
+ return action as ${pascalName}AuthorizationAction;
374
+ }
375
+
376
+ async function operationResource(
377
+ operation: ApiOperationDefinition,
378
+ request: unknown,
379
+ ownerId: string,
380
+ correlationId: string,
381
+ ): Promise<${pascalName}AuthorizationResource> {
382
+ const candidate = request as {
383
+ body?: { testExpiresAt?: unknown };
384
+ path?: { delegationId?: unknown; recordId?: unknown };
385
+ query?: { approvalRequestId?: unknown };
386
+ };
387
+ const recordId = candidate.path?.recordId;
388
+ const recordAction = operation.authorizationActions[0]?.includes(':record-');
389
+ if (recordAction) {
390
+ if (typeof recordId !== 'string') {
391
+ throw new Error(
392
+ 'A record authorization action requires its validated record path.',
393
+ );
394
+ }
395
+ const existing = await withPrimaryDatabase(
396
+ { correlationId },
397
+ 'api-database-records',
398
+ async (client) => {
399
+ const record = await client.query<{ ownerId: string }>(
400
+ \`SELECT owner_id AS "ownerId"
401
+ FROM records
402
+ WHERE id = $1::uuid\`,
403
+ [recordId],
404
+ );
405
+ if (record.rows[0]) return record.rows[0];
406
+
407
+ const delegationId = candidate.path?.delegationId;
408
+ if (
409
+ operation.authorizationActions[0] ===
410
+ ${identifierPrefix}AuthorizationActions.recordDelegationRevoke &&
411
+ typeof delegationId === 'string'
412
+ ) {
413
+ const delegation = await client.query<{
414
+ grantJson: {
415
+ delegator?: { id?: unknown };
416
+ resourceBoundary?: {
417
+ kind?: unknown;
418
+ resourceIds?: unknown;
419
+ resourceType?: unknown;
420
+ };
421
+ };
422
+ }>(
423
+ \`SELECT grant_json AS "grantJson"
424
+ FROM delegation_grants
425
+ WHERE id = $1::uuid\`,
426
+ [delegationId],
427
+ );
428
+ const grant = delegation.rows[0]?.grantJson;
429
+ if (
430
+ grant?.resourceBoundary?.kind === 'exact' &&
431
+ grant.resourceBoundary.resourceType === 'record' &&
432
+ Array.isArray(grant.resourceBoundary.resourceIds) &&
433
+ grant.resourceBoundary.resourceIds.includes(recordId) &&
434
+ typeof grant.delegator?.id === 'string'
435
+ ) {
436
+ return { ownerId: grant.delegator.id };
437
+ }
438
+ }
439
+
440
+ // A deletion retry may run after primary deletion committed. Only its
441
+ // exact durable approval can recover the original owner boundary; a
442
+ // bare missing row remains unauthorized.
443
+ const approvalRequestId = candidate.query?.approvalRequestId;
444
+ if (
445
+ operation.authorizationActions[0] !==
446
+ ${identifierPrefix}AuthorizationActions.recordDelete ||
447
+ typeof approvalRequestId !== 'string'
448
+ ) {
449
+ return undefined;
450
+ }
451
+ const approval = await client.query<{ ownerId: string }>(
452
+ \`SELECT author_reference AS "ownerId"
453
+ FROM approval_requests
454
+ WHERE id = $1::uuid
455
+ AND request_json->'resource'->>'id' = $2
456
+ AND request_json->>'action' = $3\`,
457
+ [
458
+ approvalRequestId,
459
+ recordId,
460
+ ${identifierPrefix}AuthorizationActions.recordDelete,
461
+ ],
462
+ );
463
+ return approval.rows[0];
464
+ },
465
+ );
466
+ const missingOwnerId =
467
+ operation.authorizationActions[0] ===
468
+ ${identifierPrefix}AuthorizationActions.recordWrite
469
+ ? ownerId
470
+ : 'missing-resource-owner';
471
+ return {
472
+ // PUT may authorize creation against the caller's owner boundary.
473
+ // Read/deletion misses use a non-owner sentinel so missing and adjacent
474
+ // protected identifiers produce the same denial class.
475
+ attributes: {
476
+ ownerId: existing?.ownerId ?? missingOwnerId,
477
+ syntheticTestData: candidate.body?.testExpiresAt !== undefined,
478
+ },
479
+ id: recordId,
480
+ type: 'record',
481
+ };
482
+ }
483
+ return { attributes: { collection: true }, type: 'slice' };
484
+ }
485
+
486
+ function pseudonymousSubjectId(subjectId: string): string {
487
+ return createHash('sha256').update('${name}\\0' + subjectId).digest('hex');
488
+ }
489
+
490
+ function pseudonymousResourceReference(
491
+ resourceId: string | undefined,
492
+ ): string | undefined {
493
+ return resourceId === undefined
494
+ ? undefined
495
+ : 'sha256:' +
496
+ createHash('sha256')
497
+ .update('${name}\\0resource\\0' + resourceId)
498
+ .digest('hex');
499
+ }
500
+
501
+ export type ${pascalName}AuthorizationDecisionSink = (
502
+ input: AuthorizationDecisionSinkInput<${pascalName}AuthorizationInput, never>,
503
+ ) => Promise<void> | void;
504
+
505
+ async function persistAuthorizationDecision<
506
+ Obligation extends AuthorizationObligation,
507
+ >(
508
+ decisionInput: ${pascalName}AuthorizationInput,
509
+ decision: AuthorizationDecision<Obligation>,
510
+ correlationId: string,
511
+ workload:
512
+ | 'api-database-records'
513
+ | 'data-export-cleanup'
514
+ | 'data-retention-job'
515
+ | 'event-consumer',
516
+ ) {
517
+ const audit = toAuthorizationAuditRecord(decisionInput, decision, {
518
+ correlationId,
519
+ pseudonymousSubjectId: pseudonymousSubjectId(
520
+ decisionInput.principal.actor.id,
521
+ ),
522
+ resourceReference: pseudonymousResourceReference(
523
+ decisionInput.resource.id,
524
+ ),
525
+ slice: '${name}',
526
+ stage: decisionInput.context.stage,
527
+ timestamp: decisionInput.context.now,
528
+ });
529
+ await withPrimaryDatabase(
530
+ { correlationId },
531
+ workload,
532
+ (client) =>
533
+ client.query(
534
+ \`INSERT INTO authorization_audit
535
+ (action, approval_reference, authority_mode, correlation_id,
536
+ decision, delegation_reference, policy_version,
537
+ principal_kind, pseudonymous_subject_id, reason_category,
538
+ resource_reference, resource_type, slice, stage, subject_type)
539
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12,
540
+ $13, $14, $15)\`,
541
+ [
542
+ audit.action,
543
+ null,
544
+ audit.authorityMode,
545
+ audit.correlationId,
546
+ audit.decision,
547
+ decisionInput.principal.authority.mode === 'delegated'
548
+ ? decisionInput.principal.authority.delegationId
549
+ : null,
550
+ audit.policyVersion,
551
+ decisionInput.principal.kind,
552
+ audit.pseudonymousSubjectId,
553
+ audit.reasonCategory,
554
+ audit.resourceReference ?? null,
555
+ audit.resourceType,
556
+ audit.slice,
557
+ audit.stage,
558
+ decisionInput.principal.actor.type,
559
+ ],
560
+ ),
561
+ );
562
+ return audit;
563
+ }
564
+
565
+ export async function authorize${pascalName}InternalOperation(input: {
566
+ action:
567
+ | typeof ${identifierPrefix}AuthorizationActions.dataExportCleanup
568
+ | typeof ${identifierPrefix}AuthorizationActions.lifecycleConsume
569
+ | typeof ${identifierPrefix}AuthorizationActions.retentionApply
570
+ | typeof ${identifierPrefix}AuthorizationActions.retentionMaintenance
571
+ | typeof ${identifierPrefix}AuthorizationActions.retentionReport;
572
+ correlationId: string;
573
+ operationId: string;
574
+ workloadIdentity: string;
575
+ }): Promise<void> {
576
+ const principal: AuthorizationPrincipal = {
577
+ actor: { id: input.workloadIdentity, type: 'service' },
578
+ audience: input.workloadIdentity,
579
+ authority: {
580
+ machineIdentityId: input.workloadIdentity,
581
+ mode: 'machine',
582
+ },
583
+ kind: 'agent',
584
+ roles: [],
585
+ scopes: [],
586
+ subject: { id: input.workloadIdentity, type: 'service' },
587
+ };
588
+ const authorizationInput: ${pascalName}AuthorizationInput = {
589
+ action: input.action,
590
+ context: {
591
+ facts: { operationId: input.operationId },
592
+ now: new Date().toISOString(),
593
+ stage: process.env.EBK_STAGE ?? 'development',
594
+ },
595
+ principal,
596
+ resource: { attributes: { collection: true }, type: 'slice' },
597
+ };
598
+ const evaluator = createAuthorizationEvaluator({
599
+ admission: defineCoarseAdmission({
600
+ anyOf: [{ kinds: ['agent'], subjectTypes: ['service'] }],
601
+ }),
602
+ policy: ${identifierPrefix}AuthorizationPolicy,
603
+ decisionSink: async ({ decision, input: decisionInput }) => {
604
+ await persistAuthorizationDecision(
605
+ decisionInput,
606
+ decision,
607
+ input.correlationId,
608
+ input.action ===
609
+ ${identifierPrefix}AuthorizationActions.lifecycleConsume
610
+ ? 'event-consumer'
611
+ : input.action ===
612
+ ${identifierPrefix}AuthorizationActions.dataExportCleanup
613
+ ? 'data-export-cleanup'
614
+ : 'data-retention-job',
615
+ );
616
+ },
617
+ });
618
+ await evaluator.authorize(authorizationInput);
619
+ }
620
+
621
+ async function evaluate${pascalName}Operation<
622
+ Operation extends ApiOperationDefinition,
623
+ >(
624
+ input: ApiAuthorizationInput<Operation, RuntimeHttpEvent>,
625
+ ): Promise<{
626
+ authenticated: Principal;
627
+ principal: AuthorizationPrincipal;
628
+ }> {
629
+ const authenticated = await getGuard().authorize(input.event, {
630
+ logger: input.logger,
631
+ });
632
+ const action = operationAction(input.operation);
633
+ const recognizedMachineScopes = Object.values(
634
+ ${identifierPrefix}MachineScopes(process.env.EBK_STAGE ?? ''),
635
+ ).filter((scope) => authenticated.scopes.includes(scope));
636
+ const principal =
637
+ authenticated.session.subject.type === 'service'
638
+ ? recognizedMachineScopes.length > 0
639
+ ? createMachineAuthorizationPrincipal(authenticated, {
640
+ audience: authenticated.audience ?? '',
641
+ capability: action,
642
+ machineIdentityId: authenticated.id,
643
+ requiredScopes: recognizedMachineScopes,
644
+ slice: '${name}',
645
+ })
646
+ : composeAuthorizationPrincipal(authenticated, {
647
+ machineIdentityId: authenticated.id,
648
+ mode: 'machine',
649
+ })
650
+ : createDirectAuthorizationPrincipal(authenticated);
651
+ const effectiveOwnerId =
652
+ principal.authority.mode === 'delegated'
653
+ ? principal.authority.delegatedBy.id
654
+ : authenticated.id;
655
+ const authorizationInput: ${pascalName}AuthorizationInput = {
656
+ action,
657
+ context: {
658
+ facts: { operationId: input.operation.operationId },
659
+ now: new Date().toISOString(),
660
+ stage: process.env.EBK_STAGE ?? 'development',
661
+ },
662
+ principal,
663
+ resource: await operationResource(
664
+ input.operation,
665
+ input.request,
666
+ effectiveOwnerId,
667
+ input.context.correlationId,
668
+ ),
669
+ };
670
+ const evaluator = createAuthorizationEvaluator({
671
+ admission: create${pascalName}CoarseAdmission(
672
+ authorizationInput.context.stage,
673
+ ),
674
+ policy: ${identifierPrefix}AuthorizationPolicy,
675
+ decisionSink: async ({ decision, input: decisionInput }) => {
676
+ const audit = await persistAuthorizationDecision(
677
+ decisionInput,
678
+ decision,
679
+ input.context.correlationId,
680
+ 'api-database-records',
681
+ );
682
+ input.logger.info('Authorization decision evaluated', {
683
+ attributes: {
684
+ action: audit.action,
685
+ authorityMode: audit.authorityMode,
686
+ decision: audit.decision,
687
+ policyVersion: audit.policyVersion,
688
+ reasonCategory: audit.reasonCategory,
689
+ resourceType: audit.resourceType,
690
+ },
691
+ outcome: decision.decision === 'allow' ? 'success' : 'failure',
692
+ });
693
+ },
694
+ });
695
+ await evaluator.authorize(authorizationInput);
696
+ return { authenticated, principal };
697
+ }
698
+
699
+ export async function authorize${pascalName}Operation<
700
+ Operation extends ApiOperationDefinition,
701
+ >(
702
+ input: ApiAuthorizationInput<Operation, RuntimeHttpEvent>,
703
+ ): Promise<Principal> {
704
+ return (await evaluate${pascalName}Operation(input)).authenticated;
705
+ }
706
+
707
+ /**
708
+ * Data-rights services receive the exact rich principal that was evaluated,
709
+ * rather than reconstructing authority from the transport principal.
710
+ */
711
+ export async function authorize${pascalName}DataRightsOperation<
712
+ Operation extends ApiOperationDefinition,
713
+ >(
714
+ input: ApiAuthorizationInput<Operation, RuntimeHttpEvent>,
715
+ ): Promise<AuthorizationPrincipal> {
716
+ return (await evaluate${pascalName}Operation(input)).principal;
717
+ }
718
+ `,
719
+ 'authorization/store.ts': `import type {
720
+ ApprovalRequest,
721
+ DelegationGrant,
722
+ DelegationStore,
723
+ } from '@empire-builder-kit/runtime/authorization';
724
+ import { withPrimaryDatabase } from '../database/runtime-client.js';
725
+ import type { ${pascalName}AuthorizationAction } from './policy.js';
726
+
727
+ /**
728
+ * Slice-owned online delegation state. The opaque capability is never stored;
729
+ * grantJson contains only the runtime's digest-bearing safe grant record.
730
+ */
731
+ export function create${pascalName}DelegationStore(
732
+ correlationId: string,
733
+ ): DelegationStore<${pascalName}AuthorizationAction> {
734
+ return {
735
+ async create(grant) {
736
+ const result = await withPrimaryDatabase(
737
+ { correlationId },
738
+ 'api-database-records',
739
+ (client) =>
740
+ client.query(
741
+ \`INSERT INTO delegation_grants
742
+ (id, capability_digest, expires_at, grant_json, issued_at,
743
+ policy_version, revision, status)
744
+ VALUES ($1::uuid, $2, $3, $4::jsonb, $5, $6, $7, $8)
745
+ ON CONFLICT (id) DO NOTHING\`,
746
+ [
747
+ grant.id,
748
+ grant.capabilityDigest,
749
+ grant.expiresAt,
750
+ JSON.stringify(grant),
751
+ grant.issuedAt,
752
+ grant.issuedUnderPolicyVersion,
753
+ grant.revision,
754
+ grant.status,
755
+ ],
756
+ ),
757
+ );
758
+ return result.rowCount === 1;
759
+ },
760
+ async read(delegationId) {
761
+ const result = await withPrimaryDatabase(
762
+ { correlationId },
763
+ 'api-database-records',
764
+ (client) =>
765
+ client.query<{ grantJson: DelegationGrant<${pascalName}AuthorizationAction> }>(
766
+ \`SELECT grant_json AS "grantJson"
767
+ FROM delegation_grants
768
+ WHERE id = $1::uuid\`,
769
+ [delegationId],
770
+ ),
771
+ );
772
+ return result.rows[0]?.grantJson;
773
+ },
774
+ async write(delegationId, expectedRevision, grant) {
775
+ const result = await withPrimaryDatabase(
776
+ { correlationId },
777
+ 'api-database-records',
778
+ (client) =>
779
+ client.query(
780
+ \`UPDATE delegation_grants
781
+ SET capability_digest = $3,
782
+ expires_at = $4,
783
+ grant_json = $5::jsonb,
784
+ policy_version = $6,
785
+ revision = $7,
786
+ status = $8
787
+ WHERE id = $1::uuid AND revision = $2\`,
788
+ [
789
+ delegationId,
790
+ expectedRevision,
791
+ grant.capabilityDigest,
792
+ grant.expiresAt,
793
+ JSON.stringify(grant),
794
+ grant.issuedUnderPolicyVersion,
795
+ grant.revision,
796
+ grant.status,
797
+ ],
798
+ ),
799
+ );
800
+ return result.rowCount === 1;
801
+ },
802
+ };
803
+ }
804
+
805
+ export interface ${pascalName}ApprovalStore {
806
+ create(
807
+ request: ApprovalRequest<${pascalName}AuthorizationAction>,
808
+ ): Promise<boolean>;
809
+ read(
810
+ requestId: string,
811
+ ): Promise<ApprovalRequest<${pascalName}AuthorizationAction> | undefined>;
812
+ write(
813
+ requestId: string,
814
+ expectedRevision: number,
815
+ request: ApprovalRequest<${pascalName}AuthorizationAction>,
816
+ ): Promise<boolean>;
817
+ }
818
+
819
+ /**
820
+ * Approval transitions are persisted with the same compare-and-set boundary
821
+ * used by delegation, so two reviewers or executors cannot claim one request.
822
+ */
823
+ export function create${pascalName}ApprovalStore(
824
+ correlationId: string,
825
+ ): ${pascalName}ApprovalStore {
826
+ return {
827
+ async create(request) {
828
+ const result = await withPrimaryDatabase(
829
+ { correlationId },
830
+ 'api-database-records',
831
+ (client) =>
832
+ client.query(
833
+ \`INSERT INTO approval_requests
834
+ (id, author_reference, expires_at, policy_version,
835
+ request_digest, request_json, revision, status)
836
+ VALUES ($1::uuid, $2, $3, $4, $5, $6::jsonb, $7, $8)
837
+ ON CONFLICT (id) DO NOTHING\`,
838
+ [
839
+ request.id,
840
+ request.author.effectiveHumanId ?? request.author.actorId,
841
+ request.expiresAt,
842
+ request.policyVersion,
843
+ request.requestDigest,
844
+ JSON.stringify(request),
845
+ request.revision,
846
+ request.status,
847
+ ],
848
+ ),
849
+ );
850
+ return result.rowCount === 1;
851
+ },
852
+ async read(requestId) {
853
+ const result = await withPrimaryDatabase(
854
+ { correlationId },
855
+ 'api-database-records',
856
+ (client) =>
857
+ client.query<{ requestJson: ApprovalRequest<${pascalName}AuthorizationAction> }>(
858
+ \`SELECT request_json AS "requestJson"
859
+ FROM approval_requests
860
+ WHERE id = $1::uuid\`,
861
+ [requestId],
862
+ ),
863
+ );
864
+ return result.rows[0]?.requestJson;
865
+ },
866
+ async write(requestId, expectedRevision, request) {
867
+ const result = await withPrimaryDatabase(
868
+ { correlationId },
869
+ 'api-database-records',
870
+ (client) =>
871
+ client.query(
872
+ \`UPDATE approval_requests
873
+ SET expires_at = $3,
874
+ policy_version = $4,
875
+ request_digest = $5,
876
+ request_json = $6::jsonb,
877
+ revision = $7,
878
+ status = $8
879
+ WHERE id = $1::uuid AND revision = $2\`,
880
+ [
881
+ requestId,
882
+ expectedRevision,
883
+ request.expiresAt,
884
+ request.policyVersion,
885
+ request.requestDigest,
886
+ JSON.stringify(request),
887
+ request.revision,
888
+ request.status,
889
+ ],
890
+ ),
891
+ );
892
+ return result.rowCount === 1;
893
+ },
894
+ };
895
+ }
896
+ `,
897
+ 'authorization/workflows.ts': `import { createHash } from 'node:crypto';
898
+ import type { Principal } from '@empire-builder-kit/runtime/auth';
899
+ import {
900
+ assertAuthorizationAllowed,
901
+ createAuthorizationEvaluator,
902
+ createDirectAuthorizationPrincipal,
903
+ createMachineAuthorizationPrincipal,
904
+ issueDelegation,
905
+ revokeDelegation,
906
+ useDelegation,
907
+ type AuthorizationDecision,
908
+ type AuthorizationPrincipal,
909
+ type DelegationGrant,
910
+ type IssuedDelegation,
911
+ } from '@empire-builder-kit/runtime/authorization';
912
+ import { RuntimeError } from '@empire-builder-kit/runtime/response';
913
+ import { isBoundedSafeReference } from '@empire-builder-kit/runtime/safe-reference';
914
+ import { withPrimaryDatabase } from '../database/runtime-client.js';
915
+ import {
916
+ ${identifierPrefix}AuthorizationActions,
917
+ ${identifierPrefix}AuthorizationPolicy,
918
+ ${identifierPrefix}MachineScopes,
919
+ create${pascalName}CoarseAdmission,
920
+ type ${pascalName}AuthorizationAction,
921
+ type ${pascalName}AuthorizationInput,
922
+ } from './policy.js';
923
+ import { create${pascalName}DelegationStore } from './store.js';
924
+
925
+ const POLICY_VERSION = ${identifierPrefix}AuthorizationPolicy.version;
926
+
927
+ interface RecordResult {
928
+ id: string;
929
+ name: string;
930
+ runScope: string;
931
+ }
932
+
933
+ function stage(): string {
934
+ return process.env.EBK_STAGE ?? 'development';
935
+ }
936
+
937
+ function acceptedMachineClientIds(): readonly string[] {
938
+ const current = process.env.AUTH_MACHINE_CLIENT_ID ?? '';
939
+ const encoded = process.env.AUTH_MACHINE_ACCEPTED_CLIENT_IDS ?? '';
940
+ let candidate: unknown;
941
+ try {
942
+ candidate = JSON.parse(encoded);
943
+ } catch {
944
+ unavailable();
945
+ }
946
+ if (
947
+ !Array.isArray(candidate) ||
948
+ candidate.length < 1 ||
949
+ candidate.length > 2 ||
950
+ new Set(candidate).size !== candidate.length ||
951
+ candidate.some(
952
+ (clientId) =>
953
+ !isBoundedSafeReference(clientId),
954
+ ) ||
955
+ !isBoundedSafeReference(current) ||
956
+ !candidate.includes(current)
957
+ ) {
958
+ unavailable();
959
+ }
960
+ return candidate as string[];
961
+ }
962
+
963
+ function machineClientId(): string {
964
+ const value = process.env.AUTH_MACHINE_CLIENT_ID ?? '';
965
+ if (
966
+ !isBoundedSafeReference(value) ||
967
+ !acceptedMachineClientIds().includes(value)
968
+ ) {
969
+ unavailable();
970
+ }
971
+ return value;
972
+ }
973
+
974
+ function authenticatedMachineClientId(principal: Principal): string {
975
+ const value = principal.audience;
976
+ if (
977
+ principal.kind !== 'agent' ||
978
+ principal.session.subject.type !== 'service' ||
979
+ typeof value !== 'string' ||
980
+ principal.id !== value ||
981
+ !acceptedMachineClientIds().includes(value)
982
+ ) {
983
+ denied();
984
+ }
985
+ return value;
986
+ }
987
+
988
+ function pseudonymousReference(namespace: string, value: string): string {
989
+ return (
990
+ 'sha256:' +
991
+ createHash('sha256')
992
+ .update('${name}\\0' + namespace + '\\0' + value)
993
+ .digest('hex')
994
+ );
995
+ }
996
+
997
+ function invalidInput(): never {
998
+ throw new RuntimeError({
999
+ code: 'authorization_input_invalid',
1000
+ message: 'Authorization input is invalid.',
1001
+ retryable: false,
1002
+ status: 403,
1003
+ });
1004
+ }
1005
+
1006
+ function denied(): never {
1007
+ throw new RuntimeError({
1008
+ code: 'authorization_denied',
1009
+ message: 'Authorization denied.',
1010
+ retryable: false,
1011
+ status: 403,
1012
+ });
1013
+ }
1014
+
1015
+ function notFound(): never {
1016
+ throw new RuntimeError({
1017
+ code: 'record_not_found',
1018
+ message: 'The record was not found.',
1019
+ retryable: false,
1020
+ status: 404,
1021
+ });
1022
+ }
1023
+
1024
+ function unavailable(): never {
1025
+ throw new RuntimeError({
1026
+ code: 'authorization_unavailable',
1027
+ message: 'Authorization is temporarily unavailable.',
1028
+ retryable: true,
1029
+ status: 503,
1030
+ });
1031
+ }
1032
+
1033
+ function targetMachinePrincipal(): AuthorizationPrincipal {
1034
+ const clientId = machineClientId();
1035
+ return {
1036
+ actor: { id: clientId, type: 'service' },
1037
+ audience: clientId,
1038
+ authority: { machineIdentityId: clientId, mode: 'machine' },
1039
+ kind: 'agent',
1040
+ roles: [],
1041
+ scopes: [${identifierPrefix}MachineScopes(stage()).delegationUse],
1042
+ subject: { id: clientId, type: 'service' },
1043
+ };
1044
+ }
1045
+
1046
+ async function writeDelegationAudit(input: {
1047
+ action: ${pascalName}AuthorizationAction;
1048
+ correlationId: string;
1049
+ decision: AuthorizationDecision;
1050
+ delegationId: string;
1051
+ principal: AuthorizationPrincipal;
1052
+ recordId: string;
1053
+ reasonCategory: string;
1054
+ }): Promise<void> {
1055
+ await withPrimaryDatabase(
1056
+ { correlationId: input.correlationId },
1057
+ 'api-database-records',
1058
+ (client) =>
1059
+ client.query(
1060
+ \`INSERT INTO authorization_audit
1061
+ (action, approval_reference, authority_mode, correlation_id,
1062
+ decision, delegation_reference, policy_version, principal_kind,
1063
+ pseudonymous_subject_id, reason_category, resource_reference,
1064
+ resource_type, slice, stage, subject_type)
1065
+ VALUES ($1, NULL, $2, $3, $4, $5, $6, $7, $8, $9, $10,
1066
+ 'record', $11, $12, $13)\`,
1067
+ [
1068
+ input.action,
1069
+ input.principal.authority.mode,
1070
+ input.correlationId,
1071
+ input.decision.decision,
1072
+ pseudonymousReference('delegation', input.delegationId),
1073
+ input.decision.policyVersion,
1074
+ input.principal.kind,
1075
+ pseudonymousReference('subject', input.principal.actor.id),
1076
+ input.reasonCategory,
1077
+ pseudonymousReference('record', input.recordId),
1078
+ '${name}',
1079
+ stage(),
1080
+ input.principal.actor.type,
1081
+ ],
1082
+ ),
1083
+ );
1084
+ }
1085
+
1086
+ export async function issue${pascalName}RecordDelegation(input: {
1087
+ correlationId: string;
1088
+ expiresAt: string;
1089
+ principal: Principal;
1090
+ purposeReference: string;
1091
+ recordId: string;
1092
+ }): Promise<IssuedDelegation<${pascalName}AuthorizationAction>> {
1093
+ const now = new Date();
1094
+ const expiresAt = Date.parse(input.expiresAt);
1095
+ if (
1096
+ !isBoundedSafeReference(input.purposeReference) ||
1097
+ !Number.isFinite(expiresAt) ||
1098
+ expiresAt <= now.getTime() ||
1099
+ expiresAt - now.getTime() > 60 * 60 * 1_000
1100
+ ) {
1101
+ invalidInput();
1102
+ }
1103
+ const ownership = await withPrimaryDatabase(
1104
+ { correlationId: input.correlationId },
1105
+ 'api-database-records',
1106
+ (client) =>
1107
+ client.query<{ ownerId: string }>(
1108
+ \`SELECT owner_id AS "ownerId"
1109
+ FROM records
1110
+ WHERE id = $1::uuid\`,
1111
+ [input.recordId],
1112
+ ),
1113
+ );
1114
+ if (ownership.rows[0]?.ownerId !== input.principal.id) denied();
1115
+ const delegator = createDirectAuthorizationPrincipal(input.principal);
1116
+ let issued: IssuedDelegation<${pascalName}AuthorizationAction>;
1117
+ try {
1118
+ issued = await issueDelegation(
1119
+ create${pascalName}DelegationStore(input.correlationId),
1120
+ {
1121
+ actions: [${identifierPrefix}AuthorizationActions.recordRead],
1122
+ agent: targetMachinePrincipal(),
1123
+ audience: machineClientId(),
1124
+ capabilityScopes: [
1125
+ ${identifierPrefix}MachineScopes(stage()).delegationUse,
1126
+ ],
1127
+ delegator,
1128
+ expiresAt: new Date(expiresAt).toISOString(),
1129
+ issuedUnderPolicyVersion: POLICY_VERSION,
1130
+ maxUses: 20,
1131
+ now: now.toISOString(),
1132
+ purposeReference: input.purposeReference,
1133
+ rateLimit: { maximumUses: 5, windowSeconds: 60 },
1134
+ resourceBoundary: {
1135
+ kind: 'exact',
1136
+ resourceIds: [input.recordId],
1137
+ resourceType: 'record',
1138
+ },
1139
+ slice: '${name}',
1140
+ },
1141
+ );
1142
+ } catch {
1143
+ unavailable();
1144
+ }
1145
+ const decision = {
1146
+ decision: 'allow',
1147
+ obligations: [],
1148
+ policyVersion: POLICY_VERSION,
1149
+ } as const;
1150
+ await writeDelegationAudit({
1151
+ action: ${identifierPrefix}AuthorizationActions.recordDelegationIssue,
1152
+ correlationId: input.correlationId,
1153
+ decision,
1154
+ delegationId: issued.grant.id,
1155
+ principal: delegator,
1156
+ recordId: input.recordId,
1157
+ reasonCategory: 'delegation-issued',
1158
+ });
1159
+ return issued;
1160
+ }
1161
+
1162
+ export async function use${pascalName}RecordDelegation(input: {
1163
+ capability: string;
1164
+ correlationId: string;
1165
+ delegationId: string;
1166
+ principal: Principal;
1167
+ recordId: string;
1168
+ }): Promise<RecordResult> {
1169
+ const currentStage = stage();
1170
+ const requiredScope =
1171
+ ${identifierPrefix}MachineScopes(currentStage).delegationUse;
1172
+ const authenticatedClientId = authenticatedMachineClientId(input.principal);
1173
+ let machine: AuthorizationPrincipal;
1174
+ try {
1175
+ machine = createMachineAuthorizationPrincipal(input.principal, {
1176
+ audience: authenticatedClientId,
1177
+ capability:
1178
+ ${identifierPrefix}AuthorizationActions.recordDelegationUse,
1179
+ machineIdentityId: authenticatedClientId,
1180
+ requiredScopes: [requiredScope],
1181
+ slice: '${name}',
1182
+ });
1183
+ } catch {
1184
+ denied();
1185
+ }
1186
+ const owner = await withPrimaryDatabase(
1187
+ { correlationId: input.correlationId },
1188
+ 'api-database-records',
1189
+ (client) =>
1190
+ client.query<{ ownerId: string }>(
1191
+ \`SELECT owner_id AS "ownerId"
1192
+ FROM records
1193
+ WHERE id = $1::uuid\`,
1194
+ [input.recordId],
1195
+ ),
1196
+ );
1197
+ const resource = {
1198
+ attributes: {
1199
+ ownerId: owner.rows[0]?.ownerId ?? 'missing-resource-owner',
1200
+ },
1201
+ id: input.recordId,
1202
+ type: 'record' as const,
1203
+ };
1204
+ const context = {
1205
+ facts: { operationId: '${name}.use-record-delegation' },
1206
+ now: new Date().toISOString(),
1207
+ stage: currentStage,
1208
+ };
1209
+ const result = await useDelegation({
1210
+ action: ${identifierPrefix}AuthorizationActions.recordRead,
1211
+ agent: machine,
1212
+ audience: authenticatedClientId,
1213
+ capability: input.capability,
1214
+ context,
1215
+ delegationId: input.delegationId,
1216
+ evaluator: createAuthorizationEvaluator<${pascalName}AuthorizationInput>({
1217
+ admission: create${pascalName}CoarseAdmission(currentStage),
1218
+ policy: ${identifierPrefix}AuthorizationPolicy,
1219
+ }),
1220
+ resolveDelegator: ({ delegator, resource: currentResource }) =>
1221
+ currentResource.attributes.ownerId === delegator.id
1222
+ ? {
1223
+ actor: delegator,
1224
+ authority: { mode: 'direct' },
1225
+ kind: 'customer',
1226
+ roles: [],
1227
+ scopes: [],
1228
+ subject: delegator,
1229
+ }
1230
+ : undefined,
1231
+ requiredCapabilityScopes: [requiredScope],
1232
+ resource,
1233
+ store: create${pascalName}DelegationStore(input.correlationId),
1234
+ });
1235
+ const auditPrincipal = result.principal ?? machine;
1236
+ await writeDelegationAudit({
1237
+ action: ${identifierPrefix}AuthorizationActions.recordRead,
1238
+ correlationId: input.correlationId,
1239
+ decision: result.decision,
1240
+ delegationId: input.delegationId,
1241
+ principal: auditPrincipal,
1242
+ recordId: input.recordId,
1243
+ reasonCategory:
1244
+ result.decision.decision === 'allow'
1245
+ ? 'delegation-used'
1246
+ : result.decision.category,
1247
+ });
1248
+ assertAuthorizationAllowed(result.decision);
1249
+ if (!result.grant || !owner.rows[0]) notFound();
1250
+
1251
+ const record = await withPrimaryDatabase(
1252
+ { correlationId: input.correlationId },
1253
+ 'api-database-records',
1254
+ (client) =>
1255
+ client.query<RecordResult>(
1256
+ \`SELECT id::text, name, run_scope AS "runScope"
1257
+ FROM records
1258
+ WHERE id = $1::uuid AND owner_id = $2\`,
1259
+ [input.recordId, result.grant?.delegator.id],
1260
+ ),
1261
+ );
1262
+ return record.rows[0] ?? notFound();
1263
+ }
1264
+
1265
+ function grantMatchesRecord(
1266
+ grant: DelegationGrant<${pascalName}AuthorizationAction>,
1267
+ recordId: string,
1268
+ ): boolean {
1269
+ return (
1270
+ grant.resourceBoundary.kind === 'exact' &&
1271
+ grant.resourceBoundary.resourceType === 'record' &&
1272
+ grant.resourceBoundary.resourceIds.includes(recordId)
1273
+ );
1274
+ }
1275
+
1276
+ export async function revoke${pascalName}RecordDelegation(input: {
1277
+ correlationId: string;
1278
+ delegationId: string;
1279
+ principal: Principal;
1280
+ recordId: string;
1281
+ }): Promise<DelegationGrant<${pascalName}AuthorizationAction>> {
1282
+ const store = create${pascalName}DelegationStore(input.correlationId);
1283
+ const grant = await store.read(input.delegationId);
1284
+ const revoker = createDirectAuthorizationPrincipal(input.principal);
1285
+ if (
1286
+ !grant ||
1287
+ !grantMatchesRecord(grant, input.recordId) ||
1288
+ (input.principal.kind !== 'admin' &&
1289
+ grant.delegator.id !== input.principal.id)
1290
+ ) {
1291
+ denied();
1292
+ }
1293
+ const revoked = await revokeDelegation(store, {
1294
+ delegationId: input.delegationId,
1295
+ now: new Date().toISOString(),
1296
+ revokedBy: revoker,
1297
+ });
1298
+ if (!revoked) denied();
1299
+ const decision = {
1300
+ decision: 'allow',
1301
+ obligations: [],
1302
+ policyVersion: POLICY_VERSION,
1303
+ } as const;
1304
+ await writeDelegationAudit({
1305
+ action: ${identifierPrefix}AuthorizationActions.recordDelegationRevoke,
1306
+ correlationId: input.correlationId,
1307
+ decision,
1308
+ delegationId: revoked.id,
1309
+ principal: revoker,
1310
+ recordId: input.recordId,
1311
+ reasonCategory: 'delegation-revoked',
1312
+ });
1313
+ return revoked;
1314
+ }
1315
+ `,
1316
+ 'authorization/machine-authorization-proof.ts': `import {
1317
+ createMachineTokenProvider,
1318
+ type MachineTokenExchangeResult,
1319
+ } from '@empire-builder-kit/runtime/authorization';
1320
+ import {
1321
+ bindServerSecretRuntime,
1322
+ createAwsSecretsManagerSource,
1323
+ createServerSecretResolver,
1324
+ defineSecrets,
1325
+ secret,
1326
+ } from '@empire-builder-kit/runtime/secrets';
1327
+
1328
+ interface MachineCredentialDocument {
1329
+ clientId: string;
1330
+ clientSecret: string;
1331
+ generation: string;
1332
+ }
1333
+
1334
+ const MachineAuthorizationSecrets = defineSecrets({
1335
+ ${pascalName}MachineClientCredential: {
1336
+ cache: { freshTtlMs: 0, staleTtlMs: 0 },
1337
+ owner: '${name}',
1338
+ requiredStages: ['development', 'staging', 'production'],
1339
+ retention: { mode: 'retain' },
1340
+ rotation: {
1341
+ mode: 'manual',
1342
+ runbook: 'docs/runbooks/rotate-machine-authorization.md',
1343
+ },
1344
+ source: 'aws-managed',
1345
+ value: secret.json<MachineCredentialDocument>({
1346
+ validate(value): value is MachineCredentialDocument {
1347
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
1348
+ return false;
1349
+ }
1350
+ const candidate = value as Partial<MachineCredentialDocument>;
1351
+ return (
1352
+ typeof candidate.clientId === 'string' &&
1353
+ typeof candidate.clientSecret === 'string' &&
1354
+ typeof candidate.generation === 'string' &&
1355
+ candidate.clientSecret.length >= 1 &&
1356
+ candidate.clientSecret.length <= 4_096 &&
1357
+ /^(?:blue|green)-[1-9][0-9]{0,11}$/.test(candidate.generation)
1358
+ );
1359
+ },
1360
+ }),
1361
+ },
1362
+ });
1363
+
1364
+ function requiredEnvironment(name: string): string {
1365
+ const value = process.env[name]?.trim();
1366
+ if (!value || value.length > 2_048 || /[\\r\\n]/.test(value)) {
1367
+ throw new Error('Machine authorization proof configuration is invalid.');
1368
+ }
1369
+ return value;
1370
+ }
1371
+
1372
+ function credentialDocument(
1373
+ candidate: MachineCredentialDocument,
1374
+ ): MachineCredentialDocument {
1375
+ if (
1376
+ candidate.clientId !== requiredEnvironment('AUTH_MACHINE_CLIENT_ID')
1377
+ ) {
1378
+ throw new Error('Machine authorization credential is invalid.');
1379
+ }
1380
+ return candidate;
1381
+ }
1382
+
1383
+ function machineCredentialResolver() {
1384
+ return createServerSecretResolver({
1385
+ binding: bindServerSecretRuntime({
1386
+ stage: requiredEnvironment('EBK_STAGE'),
1387
+ workload: '${name}:machine-authorization-proof',
1388
+ }),
1389
+ cache: { freshTtlMs: 0, staleTtlMs: 0 },
1390
+ source: createAwsSecretsManagerSource(),
1391
+ });
1392
+ }
1393
+
1394
+ async function exchange(input: {
1395
+ audience: string;
1396
+ clientId: string;
1397
+ clientSecret: string;
1398
+ scopes: readonly string[];
1399
+ }): Promise<MachineTokenExchangeResult> {
1400
+ const response = await fetch(
1401
+ requiredEnvironment('AUTH_MACHINE_TOKEN_ENDPOINT'),
1402
+ {
1403
+ body: new URLSearchParams({
1404
+ grant_type: 'client_credentials',
1405
+ scope: input.scopes.join(' '),
1406
+ }),
1407
+ headers: {
1408
+ authorization:
1409
+ 'Basic ' +
1410
+ Buffer.from(input.clientId + ':' + input.clientSecret).toString(
1411
+ 'base64',
1412
+ ),
1413
+ 'content-type': 'application/x-www-form-urlencoded',
1414
+ },
1415
+ method: 'POST',
1416
+ signal: AbortSignal.timeout(10_000),
1417
+ },
1418
+ );
1419
+ if (!response.ok) {
1420
+ throw new Error('Machine token exchange was denied.');
1421
+ }
1422
+ const value = (await response.json()) as {
1423
+ access_token?: unknown;
1424
+ expires_in?: unknown;
1425
+ scope?: unknown;
1426
+ token_type?: unknown;
1427
+ };
1428
+ const expiresIn = Number(value.expires_in);
1429
+ const scopes =
1430
+ typeof value.scope === 'string'
1431
+ ? value.scope.split(/\\s+/).filter(Boolean)
1432
+ : [];
1433
+ if (
1434
+ typeof value.access_token !== 'string' ||
1435
+ value.token_type !== 'Bearer' ||
1436
+ !Number.isFinite(expiresIn) ||
1437
+ expiresIn < 1
1438
+ ) {
1439
+ throw new Error('Machine token exchange returned an invalid response.');
1440
+ }
1441
+ return {
1442
+ accessToken: value.access_token,
1443
+ audience: input.audience,
1444
+ expiresAt: Date.now() / 1_000 + expiresIn,
1445
+ scopes,
1446
+ tokenType: 'Bearer',
1447
+ };
1448
+ }
1449
+
1450
+ export async function handler() {
1451
+ const clientId = requiredEnvironment('AUTH_MACHINE_CLIENT_ID');
1452
+ const scope = requiredEnvironment('AUTH_MACHINE_PROOF_SCOPE');
1453
+ let generation = 'unresolved';
1454
+ const provider = createMachineTokenProvider({
1455
+ audience: requiredEnvironment('AUTH_MACHINE_RESOURCE_SERVER'),
1456
+ clientId,
1457
+ exchange,
1458
+ machineIdentityId: clientId,
1459
+ resolveClientSecret: async () => {
1460
+ const credential = credentialDocument(
1461
+ await machineCredentialResolver().get(
1462
+ MachineAuthorizationSecrets.${pascalName}MachineClientCredential,
1463
+ {
1464
+ logicalName:
1465
+ MachineAuthorizationSecrets.${pascalName}MachineClientCredential
1466
+ .logicalName,
1467
+ provider: 'aws-secrets-manager',
1468
+ secretArn: requiredEnvironment(
1469
+ 'AUTH_MACHINE_CLIENT_SECRET_ARN',
1470
+ ),
1471
+ },
1472
+ ),
1473
+ );
1474
+ generation = credential.generation;
1475
+ return { value: credential.clientSecret };
1476
+ },
1477
+ scopes: [scope],
1478
+ });
1479
+ const token = await provider.getToken();
1480
+ const response = await fetch(
1481
+ requiredEnvironment('AUTH_MACHINE_PROBE_URL'),
1482
+ {
1483
+ headers: { authorization: token.tokenType + ' ' + token.accessToken },
1484
+ method: 'GET',
1485
+ signal: AbortSignal.timeout(10_000),
1486
+ },
1487
+ );
1488
+ if (response.status !== 200) {
1489
+ throw new Error('Machine authorization allow probe was denied.');
1490
+ }
1491
+ return {
1492
+ audit: provider.auditSnapshot(),
1493
+ clientId,
1494
+ credentialGeneration: generation,
1495
+ outcome: 'success' as const,
1496
+ probeStatus: response.status,
1497
+ scope,
1498
+ };
1499
+ }
1500
+ `,
1501
+ 'authorization/policy.spec.ts': `import {
1502
+ createAuthorizationEvaluator,
1503
+ defineCoarseAdmission,
1504
+ type AuthorizationPrincipal,
1505
+ } from '@empire-builder-kit/runtime/authorization';
1506
+ import { describe, expect, it } from 'vitest';
1507
+ import {
1508
+ ${identifierPrefix}AuthorizationActions,
1509
+ ${identifierPrefix}MachineScopes,
1510
+ ${identifierPrefix}AuthorizationPolicy,
1511
+ create${pascalName}CoarseAdmission,
1512
+ type ${pascalName}AuthorizationAction,
1513
+ type ${pascalName}AuthorizationInput,
1514
+ } from './policy.js';
1515
+
1516
+ function principal(
1517
+ overrides: Partial<AuthorizationPrincipal> = {},
1518
+ ): AuthorizationPrincipal {
1519
+ return {
1520
+ actor: { id: 'subject-owner', type: 'user' },
1521
+ authority: { mode: 'direct' },
1522
+ kind: 'customer',
1523
+ roles: [],
1524
+ scopes: [],
1525
+ subject: { id: 'subject-owner', type: 'user' },
1526
+ ...overrides,
1527
+ };
1528
+ }
1529
+
1530
+ function input(
1531
+ overrides: Partial<${pascalName}AuthorizationInput> = {},
1532
+ ): ${pascalName}AuthorizationInput {
1533
+ return {
1534
+ action: ${identifierPrefix}AuthorizationActions.recordRead,
1535
+ context: {
1536
+ facts: { operationId: '${name}.get-record' },
1537
+ now: '2026-07-27T12:00:00.000Z',
1538
+ stage: 'development',
1539
+ },
1540
+ principal: principal(),
1541
+ resource: {
1542
+ attributes: { ownerId: 'subject-owner' },
1543
+ id: '00000000-0000-4000-8000-000000000001',
1544
+ type: 'record',
1545
+ },
1546
+ ...overrides,
1547
+ };
1548
+ }
1549
+
1550
+ describe('${pascalName} authorization policy', () => {
1551
+ const evaluator = createAuthorizationEvaluator({
1552
+ admission: create${pascalName}CoarseAdmission('development'),
1553
+ policy: ${identifierPrefix}AuthorizationPolicy,
1554
+ });
1555
+
1556
+ it('allows an owner and denies an adjacent resource', async () => {
1557
+ await expect(evaluator.evaluate(input())).resolves.toMatchObject({
1558
+ decision: 'allow',
1559
+ });
1560
+ await expect(
1561
+ evaluator.evaluate(
1562
+ input({
1563
+ resource: {
1564
+ attributes: { ownerId: 'subject-adjacent' },
1565
+ id: '00000000-0000-4000-8000-000000000002',
1566
+ type: 'record',
1567
+ },
1568
+ }),
1569
+ ),
1570
+ ).resolves.toMatchObject({
1571
+ category: 'domain-authorization-denied',
1572
+ decision: 'deny',
1573
+ });
1574
+ });
1575
+
1576
+ it('limits TTL-bearing synthetic records to the generated test-writer role', async () => {
1577
+ const syntheticResource = {
1578
+ attributes: {
1579
+ ownerId: 'subject-owner',
1580
+ syntheticTestData: true,
1581
+ },
1582
+ id: '00000000-0000-4000-8000-000000000001',
1583
+ type: 'record' as const,
1584
+ };
1585
+ await expect(
1586
+ evaluator.evaluate(
1587
+ input({
1588
+ action: ${identifierPrefix}AuthorizationActions.recordWrite,
1589
+ resource: syntheticResource,
1590
+ }),
1591
+ ),
1592
+ ).resolves.toMatchObject({
1593
+ category: 'domain-authorization-denied',
1594
+ decision: 'deny',
1595
+ });
1596
+ await expect(
1597
+ evaluator.evaluate(
1598
+ input({
1599
+ action: ${identifierPrefix}AuthorizationActions.recordWrite,
1600
+ principal: principal({ roles: ['${name}-test-writer'] }),
1601
+ resource: syntheticResource,
1602
+ }),
1603
+ ),
1604
+ ).resolves.toMatchObject({ decision: 'allow' });
1605
+ });
1606
+
1607
+ it('separates owner export from direct-admin cleanup and hold authority', async () => {
1608
+ await expect(
1609
+ evaluator.evaluate(
1610
+ input({
1611
+ action: ${identifierPrefix}AuthorizationActions.recordExport,
1612
+ }),
1613
+ ),
1614
+ ).resolves.toMatchObject({ decision: 'allow' });
1615
+ const admin = principal({
1616
+ actor: { id: 'admin-reviewer', type: 'user' },
1617
+ kind: 'admin',
1618
+ roles: ['${name}-admin'],
1619
+ subject: { id: 'admin-reviewer', type: 'user' },
1620
+ });
1621
+ await expect(
1622
+ evaluator.evaluate(
1623
+ input({
1624
+ action: ${identifierPrefix}AuthorizationActions.recordExport,
1625
+ principal: admin,
1626
+ }),
1627
+ ),
1628
+ ).resolves.toMatchObject({ decision: 'deny' });
1629
+ await expect(
1630
+ evaluator.evaluate(
1631
+ input({
1632
+ action:
1633
+ ${identifierPrefix}AuthorizationActions.recordExportCleanup,
1634
+ }),
1635
+ ),
1636
+ ).resolves.toMatchObject({ decision: 'deny' });
1637
+ for (const action of [
1638
+ ${identifierPrefix}AuthorizationActions.recordExportCleanup,
1639
+ ${identifierPrefix}AuthorizationActions.recordHoldManage,
1640
+ ]) {
1641
+ await expect(
1642
+ evaluator.evaluate(input({ action, principal: admin })),
1643
+ ).resolves.toMatchObject({ decision: 'allow' });
1644
+ }
1645
+ });
1646
+
1647
+ it('requires an exact action scope for a machine principal', async () => {
1648
+ const machine = principal({
1649
+ actor: { id: 'machine-client', type: 'service' },
1650
+ audience: 'machine-client',
1651
+ authority: {
1652
+ machineIdentityId: 'machine-client',
1653
+ mode: 'machine',
1654
+ },
1655
+ kind: 'agent',
1656
+ scopes: [
1657
+ ${identifierPrefix}MachineScopes('development').delegationUse,
1658
+ ],
1659
+ subject: { id: 'machine-client', type: 'service' },
1660
+ });
1661
+ await expect(
1662
+ evaluator.evaluate(input({ principal: machine })),
1663
+ ).resolves.toMatchObject({
1664
+ category: 'domain-authorization-denied',
1665
+ decision: 'deny',
1666
+ });
1667
+ await expect(
1668
+ evaluator.evaluate(
1669
+ input({
1670
+ action: ${identifierPrefix}AuthorizationActions.machineProofRead,
1671
+ principal: {
1672
+ ...machine,
1673
+ scopes: [
1674
+ ${identifierPrefix}MachineScopes('development').proofReader,
1675
+ ],
1676
+ },
1677
+ }),
1678
+ ),
1679
+ ).resolves.toMatchObject({ decision: 'allow' });
1680
+ await expect(
1681
+ evaluator.evaluate(
1682
+ input({
1683
+ principal: {
1684
+ ...machine,
1685
+ scopes: ['${name}-development/record-read'],
1686
+ },
1687
+ }),
1688
+ ),
1689
+ ).resolves.toMatchObject({
1690
+ category: 'admission-scope-denied',
1691
+ decision: 'deny',
1692
+ });
1693
+ });
1694
+
1695
+ it('fails closed for system and non-agent service principals', async () => {
1696
+ for (const unsupported of [
1697
+ principal({
1698
+ actor: { id: 'system-subject', type: 'system' },
1699
+ audience: 'system-subject',
1700
+ authority: {
1701
+ machineIdentityId: 'system-subject',
1702
+ mode: 'machine',
1703
+ },
1704
+ kind: 'agent',
1705
+ subject: { id: 'system-subject', type: 'system' },
1706
+ }),
1707
+ principal({
1708
+ actor: { id: 'service-member', type: 'service' },
1709
+ kind: 'customer',
1710
+ subject: { id: 'service-member', type: 'service' },
1711
+ }),
1712
+ ]) {
1713
+ await expect(
1714
+ evaluator.evaluate(input({ principal: unsupported })),
1715
+ ).resolves.toMatchObject({ decision: 'deny' });
1716
+ }
1717
+ });
1718
+
1719
+ it('keeps the machine proof action unavailable to direct humans', async () => {
1720
+ for (const directHuman of [
1721
+ principal(),
1722
+ principal({
1723
+ actor: { id: 'admin-reviewer', type: 'user' },
1724
+ kind: 'admin',
1725
+ roles: ['${name}-admin'],
1726
+ subject: { id: 'admin-reviewer', type: 'user' },
1727
+ }),
1728
+ ]) {
1729
+ await expect(
1730
+ evaluator.evaluate(
1731
+ input({
1732
+ action: ${identifierPrefix}AuthorizationActions.machineProofRead,
1733
+ principal: directHuman,
1734
+ resource: { attributes: { collection: true }, type: 'slice' },
1735
+ }),
1736
+ ),
1737
+ ).resolves.toMatchObject({
1738
+ category: 'domain-authorization-denied',
1739
+ decision: 'deny',
1740
+ });
1741
+ }
1742
+ });
1743
+
1744
+ it('allows only exact internal workload action and identity pairs', async () => {
1745
+ const internalEvaluator = createAuthorizationEvaluator({
1746
+ admission: defineCoarseAdmission({
1747
+ anyOf: [{ kinds: ['agent'], subjectTypes: ['service'] }],
1748
+ }),
1749
+ policy: ${identifierPrefix}AuthorizationPolicy,
1750
+ });
1751
+ const service = (identity: string): AuthorizationPrincipal =>
1752
+ principal({
1753
+ actor: { id: identity, type: 'service' },
1754
+ audience: identity,
1755
+ authority: { machineIdentityId: identity, mode: 'machine' },
1756
+ kind: 'agent',
1757
+ scopes: [],
1758
+ subject: { id: identity, type: 'service' },
1759
+ });
1760
+ const internalInput = (
1761
+ action: ${pascalName}AuthorizationAction,
1762
+ identity: string,
1763
+ ): ${pascalName}AuthorizationInput =>
1764
+ input({
1765
+ action,
1766
+ principal: service(identity),
1767
+ resource: { attributes: { collection: true }, type: 'slice' },
1768
+ });
1769
+
1770
+ await expect(
1771
+ internalEvaluator.evaluate(
1772
+ internalInput(
1773
+ ${identifierPrefix}AuthorizationActions.lifecycleConsume,
1774
+ '${name}:event-consumer',
1775
+ ),
1776
+ ),
1777
+ ).resolves.toMatchObject({ decision: 'allow' });
1778
+ await expect(
1779
+ internalEvaluator.evaluate(
1780
+ internalInput(
1781
+ ${identifierPrefix}AuthorizationActions.retentionApply,
1782
+ '${name}:data-retention-job',
1783
+ ),
1784
+ ),
1785
+ ).resolves.toMatchObject({ decision: 'allow' });
1786
+ await expect(
1787
+ internalEvaluator.evaluate(
1788
+ internalInput(
1789
+ ${identifierPrefix}AuthorizationActions.retentionReport,
1790
+ '${name}:data-retention-job',
1791
+ ),
1792
+ ),
1793
+ ).resolves.toMatchObject({ decision: 'allow' });
1794
+ await expect(
1795
+ internalEvaluator.evaluate(
1796
+ internalInput(
1797
+ ${identifierPrefix}AuthorizationActions.retentionMaintenance,
1798
+ '${name}:data-retention-job',
1799
+ ),
1800
+ ),
1801
+ ).resolves.toMatchObject({ decision: 'allow' });
1802
+ await expect(
1803
+ internalEvaluator.evaluate(
1804
+ internalInput(
1805
+ ${identifierPrefix}AuthorizationActions.dataExportCleanup,
1806
+ '${name}:data-export-cleanup',
1807
+ ),
1808
+ ),
1809
+ ).resolves.toMatchObject({ decision: 'allow' });
1810
+ for (const rejected of [
1811
+ internalInput(
1812
+ ${identifierPrefix}AuthorizationActions.dataExportCleanup,
1813
+ '${name}:data-retention-job',
1814
+ ),
1815
+ internalInput(
1816
+ ${identifierPrefix}AuthorizationActions.retentionApply,
1817
+ '${name}:event-consumer',
1818
+ ),
1819
+ internalInput(
1820
+ ${identifierPrefix}AuthorizationActions.retentionReport,
1821
+ '${name}:event-consumer',
1822
+ ),
1823
+ internalInput(
1824
+ ${identifierPrefix}AuthorizationActions.retentionMaintenance,
1825
+ '${name}:event-consumer',
1826
+ ),
1827
+ internalInput(
1828
+ ${identifierPrefix}AuthorizationActions.lifecycleConsume,
1829
+ 'ordinary-machine-client',
1830
+ ),
1831
+ input({
1832
+ action: ${identifierPrefix}AuthorizationActions.lifecycleConsume,
1833
+ principal: principal(),
1834
+ resource: { attributes: { collection: true }, type: 'slice' },
1835
+ }),
1836
+ ]) {
1837
+ await expect(
1838
+ internalEvaluator.evaluate(rejected),
1839
+ ).resolves.toMatchObject({ decision: 'deny' });
1840
+ }
1841
+ });
1842
+
1843
+ it('fails closed when the policy evaluator is unavailable', async () => {
1844
+ const unavailable = createAuthorizationEvaluator<${pascalName}AuthorizationInput>({
1845
+ admission: create${pascalName}CoarseAdmission('development'),
1846
+ policy: {
1847
+ evaluate() {
1848
+ throw new Error('provider unavailable');
1849
+ },
1850
+ version: '1.0.0',
1851
+ },
1852
+ });
1853
+ await expect(unavailable.evaluate(input())).resolves.toMatchObject({
1854
+ category: 'authorization-unavailable',
1855
+ decision: 'deny',
1856
+ });
1857
+ });
1858
+ });
1859
+ `,
1860
+ 'authorization/workflows.spec.ts': `import {
1861
+ authorizeApprovalExecution,
1862
+ beginApprovalExecution,
1863
+ createApprovalRequest,
1864
+ createAuthorizationEvaluator,
1865
+ decideApprovalRequest,
1866
+ issueDelegation,
1867
+ revokeDelegation,
1868
+ useDelegation,
1869
+ type AuthorizationPrincipal,
1870
+ type DelegationGrant,
1871
+ type DelegationStore,
1872
+ } from '@empire-builder-kit/runtime/authorization';
1873
+ import { describe, expect, it } from 'vitest';
1874
+ import {
1875
+ ${identifierPrefix}AuthorizationActions,
1876
+ ${identifierPrefix}AuthorizationPolicy,
1877
+ ${identifierPrefix}MachineScopes,
1878
+ create${pascalName}CoarseAdmission,
1879
+ type ${pascalName}AuthorizationAction,
1880
+ } from './policy.js';
1881
+
1882
+ class MemoryDelegationStore
1883
+ implements DelegationStore<${pascalName}AuthorizationAction>
1884
+ {
1885
+ readonly grants = new Map<
1886
+ string,
1887
+ DelegationGrant<${pascalName}AuthorizationAction>
1888
+ >();
1889
+
1890
+ create(grant: DelegationGrant<${pascalName}AuthorizationAction>) {
1891
+ if (this.grants.has(grant.id)) return false;
1892
+ this.grants.set(grant.id, structuredClone(grant));
1893
+ return true;
1894
+ }
1895
+
1896
+ read(id: string) {
1897
+ const grant = this.grants.get(id);
1898
+ return grant ? structuredClone(grant) : undefined;
1899
+ }
1900
+
1901
+ write(
1902
+ id: string,
1903
+ expectedRevision: number,
1904
+ grant: DelegationGrant<${pascalName}AuthorizationAction>,
1905
+ ) {
1906
+ const current = this.grants.get(id);
1907
+ if (!current || current.revision !== expectedRevision) return false;
1908
+ this.grants.set(id, structuredClone(grant));
1909
+ return true;
1910
+ }
1911
+ }
1912
+
1913
+ function human(id: string, kind: 'admin' | 'customer' = 'customer') {
1914
+ return {
1915
+ actor: { id, type: 'user' as const },
1916
+ authority: { mode: 'direct' as const },
1917
+ kind,
1918
+ roles: kind === 'admin' ? ['${name}-admin'] : [],
1919
+ scopes: [],
1920
+ subject: { id, type: 'user' as const },
1921
+ } satisfies AuthorizationPrincipal;
1922
+ }
1923
+
1924
+ function agent(): AuthorizationPrincipal {
1925
+ return {
1926
+ actor: { id: '${name}-agent-api', type: 'service' },
1927
+ audience: '${name}-agent-api',
1928
+ authority: {
1929
+ machineIdentityId: '${name}-attended-agent',
1930
+ mode: 'machine',
1931
+ },
1932
+ kind: 'agent',
1933
+ roles: [],
1934
+ scopes: [
1935
+ ${identifierPrefix}MachineScopes('development').delegationUse,
1936
+ ],
1937
+ subject: { id: '${name}-agent-api', type: 'service' },
1938
+ };
1939
+ }
1940
+
1941
+ const recordId = '00000000-0000-4000-8000-000000000001';
1942
+ const context = {
1943
+ facts: { operationId: '${name}.get-record' },
1944
+ now: '2026-07-27T12:01:00.000Z',
1945
+ stage: 'development',
1946
+ };
1947
+ const resource = {
1948
+ attributes: { ownerId: 'record-owner' },
1949
+ id: recordId,
1950
+ type: 'record' as const,
1951
+ };
1952
+
1953
+ describe('${pascalName} delegated authorization and approvals', () => {
1954
+ it('uses online delegation within exact bounds and denies rate/revocation', async () => {
1955
+ const store = new MemoryDelegationStore();
1956
+ const actingAgent = agent();
1957
+ const issued = await issueDelegation(store, {
1958
+ actions: [${identifierPrefix}AuthorizationActions.recordRead],
1959
+ agent: actingAgent,
1960
+ audience: '${name}-agent-api',
1961
+ capabilityScopes: [
1962
+ ${identifierPrefix}MachineScopes('development').delegationUse,
1963
+ ],
1964
+ delegator: human('record-owner'),
1965
+ expiresAt: '2026-07-27T12:30:00.000Z',
1966
+ issuedUnderPolicyVersion: '1.0.0',
1967
+ now: '2026-07-27T12:00:00.000Z',
1968
+ purposeReference: 'work-item-123',
1969
+ rateLimit: { maximumUses: 1, windowSeconds: 60 },
1970
+ resourceBoundary: {
1971
+ kind: 'exact',
1972
+ resourceIds: [recordId],
1973
+ resourceType: 'record',
1974
+ },
1975
+ slice: '${name}',
1976
+ });
1977
+ const evaluator = createAuthorizationEvaluator({
1978
+ admission: create${pascalName}CoarseAdmission('development'),
1979
+ policy: ${identifierPrefix}AuthorizationPolicy,
1980
+ });
1981
+ const use = () =>
1982
+ useDelegation({
1983
+ action: ${identifierPrefix}AuthorizationActions.recordRead,
1984
+ agent: actingAgent,
1985
+ audience: '${name}-agent-api',
1986
+ capability: issued.capability,
1987
+ context,
1988
+ delegationId: issued.grant.id,
1989
+ evaluator,
1990
+ resolveDelegator: ({ delegator }) => human(delegator.id),
1991
+ requiredCapabilityScopes: [
1992
+ ${identifierPrefix}MachineScopes('development').delegationUse,
1993
+ ],
1994
+ resource,
1995
+ store,
1996
+ });
1997
+
1998
+ await expect(use()).resolves.toMatchObject({
1999
+ decision: { decision: 'allow' },
2000
+ grant: { usage: { totalUses: 1 } },
2001
+ });
2002
+ await expect(use()).resolves.toMatchObject({
2003
+ decision: {
2004
+ category: 'delegation-rate-limited',
2005
+ decision: 'deny',
2006
+ },
2007
+ });
2008
+ await revokeDelegation(store, {
2009
+ delegationId: issued.grant.id,
2010
+ now: '2026-07-27T12:02:00.000Z',
2011
+ revokedBy: human('record-owner'),
2012
+ });
2013
+ await expect(use()).resolves.toMatchObject({
2014
+ decision: { category: 'delegation-revoked', decision: 'deny' },
2015
+ });
2016
+ });
2017
+
2018
+ it('denies attended use when the delegator no longer owns the resource', async () => {
2019
+ const store = new MemoryDelegationStore();
2020
+ const actingAgent = agent();
2021
+ const issued = await issueDelegation(store, {
2022
+ actions: [${identifierPrefix}AuthorizationActions.recordRead],
2023
+ agent: actingAgent,
2024
+ audience: '${name}-agent-api',
2025
+ capabilityScopes: [
2026
+ ${identifierPrefix}MachineScopes('development').delegationUse,
2027
+ ],
2028
+ delegator: human('former-owner'),
2029
+ expiresAt: '2026-07-27T12:30:00.000Z',
2030
+ issuedUnderPolicyVersion: '1.0.0',
2031
+ now: '2026-07-27T12:00:00.000Z',
2032
+ purposeReference: 'work-item-delegator-ceiling',
2033
+ resourceBoundary: {
2034
+ kind: 'exact',
2035
+ resourceIds: [recordId],
2036
+ resourceType: 'record',
2037
+ },
2038
+ slice: '${name}',
2039
+ });
2040
+ await expect(
2041
+ useDelegation({
2042
+ action: ${identifierPrefix}AuthorizationActions.recordRead,
2043
+ agent: actingAgent,
2044
+ audience: '${name}-agent-api',
2045
+ capability: issued.capability,
2046
+ context,
2047
+ delegationId: issued.grant.id,
2048
+ evaluator: createAuthorizationEvaluator({
2049
+ admission: create${pascalName}CoarseAdmission('development'),
2050
+ policy: ${identifierPrefix}AuthorizationPolicy,
2051
+ }),
2052
+ resolveDelegator: ({ delegator }) => human(delegator.id),
2053
+ requiredCapabilityScopes: [
2054
+ ${identifierPrefix}MachineScopes('development').delegationUse,
2055
+ ],
2056
+ resource,
2057
+ store,
2058
+ }),
2059
+ ).resolves.toMatchObject({
2060
+ decision: {
2061
+ category: 'delegation-out-of-bounds',
2062
+ decision: 'deny',
2063
+ },
2064
+ });
2065
+ expect(store.read(issued.grant.id)?.usage.totalUses).toBe(0);
2066
+ });
2067
+
2068
+ it('denies attended use when the issuing policy version is stale', async () => {
2069
+ const store = new MemoryDelegationStore();
2070
+ const actingAgent = agent();
2071
+ const issued = await issueDelegation(store, {
2072
+ actions: [${identifierPrefix}AuthorizationActions.recordRead],
2073
+ agent: actingAgent,
2074
+ audience: '${name}-agent-api',
2075
+ capabilityScopes: [
2076
+ ${identifierPrefix}MachineScopes('development').delegationUse,
2077
+ ],
2078
+ delegator: human('record-owner'),
2079
+ expiresAt: '2026-07-27T12:30:00.000Z',
2080
+ issuedUnderPolicyVersion: '1.0.0',
2081
+ now: '2026-07-27T12:00:00.000Z',
2082
+ purposeReference: 'work-item-policy-version',
2083
+ resourceBoundary: {
2084
+ kind: 'exact',
2085
+ resourceIds: [recordId],
2086
+ resourceType: 'record',
2087
+ },
2088
+ slice: '${name}',
2089
+ });
2090
+ const evaluator = createAuthorizationEvaluator({
2091
+ admission: create${pascalName}CoarseAdmission('development'),
2092
+ policy: {
2093
+ ...${identifierPrefix}AuthorizationPolicy,
2094
+ version: '2.0.0',
2095
+ },
2096
+ });
2097
+
2098
+ await expect(
2099
+ useDelegation({
2100
+ action: ${identifierPrefix}AuthorizationActions.recordRead,
2101
+ agent: actingAgent,
2102
+ audience: '${name}-agent-api',
2103
+ capability: issued.capability,
2104
+ context,
2105
+ delegationId: issued.grant.id,
2106
+ evaluator,
2107
+ resolveDelegator: ({ delegator }) => human(delegator.id),
2108
+ requiredCapabilityScopes: [
2109
+ ${identifierPrefix}MachineScopes('development').delegationUse,
2110
+ ],
2111
+ resource,
2112
+ store,
2113
+ }),
2114
+ ).resolves.toMatchObject({
2115
+ decision: {
2116
+ category: 'policy-stale',
2117
+ decision: 'deny',
2118
+ policyVersion: '2.0.0',
2119
+ },
2120
+ });
2121
+ expect(store.read(issued.grant.id)?.usage.totalUses).toBe(0);
2122
+ });
2123
+
2124
+ it('denies an expired attended capability online', async () => {
2125
+ const store = new MemoryDelegationStore();
2126
+ const actingAgent = agent();
2127
+ const issued = await issueDelegation(store, {
2128
+ actions: [${identifierPrefix}AuthorizationActions.recordRead],
2129
+ agent: actingAgent,
2130
+ audience: '${name}-agent-api',
2131
+ delegator: human('record-owner'),
2132
+ expiresAt: '2026-07-27T12:02:00.000Z',
2133
+ issuedUnderPolicyVersion: '1.0.0',
2134
+ now: '2026-07-27T12:00:00.000Z',
2135
+ purposeReference: 'work-item-124',
2136
+ resourceBoundary: {
2137
+ kind: 'exact',
2138
+ resourceIds: [recordId],
2139
+ resourceType: 'record',
2140
+ },
2141
+ slice: '${name}',
2142
+ });
2143
+ await expect(
2144
+ useDelegation({
2145
+ action: ${identifierPrefix}AuthorizationActions.recordRead,
2146
+ agent: actingAgent,
2147
+ audience: '${name}-agent-api',
2148
+ capability: issued.capability,
2149
+ context: { ...context, now: '2026-07-27T12:03:00.000Z' },
2150
+ delegationId: issued.grant.id,
2151
+ evaluator: createAuthorizationEvaluator({
2152
+ admission: create${pascalName}CoarseAdmission('development'),
2153
+ policy: ${identifierPrefix}AuthorizationPolicy,
2154
+ }),
2155
+ resolveDelegator: ({ delegator }) => human(delegator.id),
2156
+ resource,
2157
+ store,
2158
+ }),
2159
+ ).resolves.toMatchObject({
2160
+ decision: { category: 'delegation-expired', decision: 'deny' },
2161
+ });
2162
+ });
2163
+
2164
+ it('keeps a high-impact record deletion pending until non-author approval', () => {
2165
+ const command = { reasonCode: 'subject-request', recordId };
2166
+ const pending = createApprovalRequest({
2167
+ action: ${identifierPrefix}AuthorizationActions.recordDelete,
2168
+ author: agent(),
2169
+ command,
2170
+ expiresAt: '2026-07-27T13:00:00.000Z',
2171
+ now: '2026-07-27T12:00:00.000Z',
2172
+ policyVersion: '1.0.0',
2173
+ resource: { id: recordId, type: 'record' },
2174
+ slice: '${name}',
2175
+ });
2176
+ expect(
2177
+ authorizeApprovalExecution(pending, {
2178
+ action: ${identifierPrefix}AuthorizationActions.recordDelete,
2179
+ command,
2180
+ now: '2026-07-27T12:05:00.000Z',
2181
+ requiredPolicyVersion: '1.0.0',
2182
+ resource: { id: recordId, type: 'record' },
2183
+ }),
2184
+ ).toMatchObject({
2185
+ category: 'approval-pending',
2186
+ decision: 'deny',
2187
+ });
2188
+ const approved = decideApprovalRequest(pending, {
2189
+ approver: human('privacy-reviewer', 'admin'),
2190
+ expectedRequestDigest: pending.requestDigest,
2191
+ now: '2026-07-27T12:10:00.000Z',
2192
+ outcome: 'approved',
2193
+ reasonReference: 'review-123',
2194
+ requiredPolicyVersion: '1.0.0',
2195
+ });
2196
+ expect(approved.decision.decision).toBe('allow');
2197
+ expect(
2198
+ beginApprovalExecution(approved.request, {
2199
+ action: ${identifierPrefix}AuthorizationActions.recordDelete,
2200
+ command,
2201
+ executionId: 'deletion-execution-stale',
2202
+ now: '2026-07-27T12:11:00.000Z',
2203
+ requiredPolicyVersion: '2.0.0',
2204
+ resource: { id: recordId, type: 'record' },
2205
+ }),
2206
+ ).toMatchObject({
2207
+ decision: {
2208
+ category: 'policy-stale',
2209
+ decision: 'deny',
2210
+ policyVersion: '2.0.0',
2211
+ },
2212
+ request: { status: 'approved' },
2213
+ });
2214
+ expect(
2215
+ beginApprovalExecution(approved.request, {
2216
+ action: ${identifierPrefix}AuthorizationActions.recordDelete,
2217
+ command,
2218
+ executionId: 'deletion-execution-123',
2219
+ now: '2026-07-27T12:11:00.000Z',
2220
+ requiredPolicyVersion: '1.0.0',
2221
+ resource: { id: recordId, type: 'record' },
2222
+ }),
2223
+ ).toMatchObject({
2224
+ decision: { decision: 'allow' },
2225
+ request: { status: 'executing' },
2226
+ });
2227
+ expect(
2228
+ authorizeApprovalExecution(approved.request, {
2229
+ action: ${identifierPrefix}AuthorizationActions.recordDelete,
2230
+ command: { ...command, recordId: recordId.replace(/1$/, '2') },
2231
+ now: '2026-07-27T12:11:00.000Z',
2232
+ requiredPolicyVersion: '1.0.0',
2233
+ resource: { id: recordId, type: 'record' },
2234
+ }),
2235
+ ).toMatchObject({
2236
+ category: 'approval-invalid',
2237
+ decision: 'deny',
2238
+ });
2239
+ });
2240
+
2241
+ it('denies direct self-review of the exact request digest', () => {
2242
+ const author = human('record-owner');
2243
+ const pending = createApprovalRequest({
2244
+ action: ${identifierPrefix}AuthorizationActions.recordDelete,
2245
+ author,
2246
+ command: { recordId },
2247
+ expiresAt: '2026-07-27T13:00:00.000Z',
2248
+ now: '2026-07-27T12:00:00.000Z',
2249
+ policyVersion: '1.0.0',
2250
+ resource: { id: recordId, type: 'record' },
2251
+ slice: '${name}',
2252
+ });
2253
+ expect(
2254
+ decideApprovalRequest(pending, {
2255
+ approver: author,
2256
+ expectedRequestDigest: pending.requestDigest,
2257
+ now: '2026-07-27T12:10:00.000Z',
2258
+ outcome: 'approved',
2259
+ reasonReference: 'self-review',
2260
+ requiredPolicyVersion: '1.0.0',
2261
+ }),
2262
+ ).toMatchObject({
2263
+ decision: { category: 'approval-invalid', decision: 'deny' },
2264
+ request: { status: 'pending' },
2265
+ });
2266
+ });
2267
+ });
2268
+ `,
2269
+ 'docs/runbooks/authorization.md': `# Authorization
2270
+
2271
+ Every protected operation declares one Slice-owned action and passes through
2272
+ the generated authentication-plus-domain-authorization adapter before business
2273
+ logic. The seeded policy in \`authorization/policy.ts\` is deny by default.
2274
+ Roles and OAuth scopes are coarse admission only; resource/action policy still
2275
+ decides each operation.
2276
+
2277
+ Advance the policy version when observable behavior changes. Run
2278
+ \`pnpm nx run ${name}:authorization-check\` and review policy compatibility before
2279
+ deployment. Permission broadening requires explicit security review; a
2280
+ reduction is breaking until callers and recovery authority are reconciled.
2281
+
2282
+ The Standard machine client exposes only the exact \`proof-read\` and
2283
+ \`delegation-use\` Cognito scopes. It cannot read a product record directly;
2284
+ resource access requires the attended, server-side delegation decision.
2285
+ Attended delegation uses an audience-bound opaque capability and never exposes
2286
+ the delegator's token. Every use resolves the delegator from current
2287
+ Slice-owned state and requires both the direct delegator and delegated agent
2288
+ policy decisions to allow the exact action and resource. High-impact actions
2289
+ use a digest-bound approval from a different direct human. Neither agents nor
2290
+ machines may approve their own grant or action.
2291
+
2292
+ Deployment provisions the empty \`${name}-admin\` Cognito group used for direct
2293
+ human recovery, deletion approval, and retention review. Add or remove group
2294
+ membership only through a reviewed identity-administration action; never seed a
2295
+ member, reuse the group for machines, or treat group admission as the final
2296
+ domain decision.
2297
+
2298
+ The generated event consumer and data-retention Job use internal-only
2299
+ \`${name}:event-consumer\` and \`${name}:data-retention-job\` workload identities.
2300
+ They are not Cognito clients or scopes. Each is accepted only for its exact
2301
+ Slice-collection action, and the internal helper must run before the protected
2302
+ effect so a missing, swapped, or externally supplied identity fails closed.
2303
+ These workloads are represented as \`kind: agent\`, \`subject.type: service\`.
2304
+ System subjects and non-agent service principals are intentionally unsupported
2305
+ in the Standard v1 policy and receive a default-deny decision.
2306
+
2307
+ Audit output contains only pseudonymous subject, action, resource type/safe
2308
+ reference, authority mode, decision category, policy version, correlation,
2309
+ Slice, stage, and timestamp. Never add tokens, claims, email, record content,
2310
+ policy input, roles, or scopes.
2311
+ `,
2312
+ };
2313
+ }
2314
+ //# sourceMappingURL=built-in-plan-authorization-files.js.map