@msn-control/liftoff 0.10.4 → 0.11.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 (700) hide show
  1. package/DEVELOPER.md +238 -77
  2. package/README.md +38 -33
  3. package/assets/supported-stack.json +3 -136
  4. package/dist/adapters/azure/governance-assessment.d.ts +2 -0
  5. package/dist/adapters/azure/governance-assessment.js +21 -0
  6. package/dist/adapters/azure/governance-assessment.js.map +1 -0
  7. package/dist/adapters/filesystem/atomic-write.d.ts +2 -0
  8. package/dist/adapters/filesystem/atomic-write.js +74 -0
  9. package/dist/adapters/filesystem/atomic-write.js.map +1 -0
  10. package/dist/adapters/filesystem/errors.d.ts +2 -0
  11. package/dist/adapters/filesystem/errors.js +8 -0
  12. package/dist/adapters/filesystem/errors.js.map +1 -0
  13. package/dist/adapters/filesystem/manifest-file.d.ts +1 -0
  14. package/dist/adapters/filesystem/manifest-file.js +21 -0
  15. package/dist/adapters/filesystem/manifest-file.js.map +1 -0
  16. package/dist/adapters/filesystem/project-config.d.ts +4 -0
  17. package/dist/adapters/filesystem/project-config.js +157 -0
  18. package/dist/adapters/filesystem/project-config.js.map +1 -0
  19. package/dist/adapters/filesystem/project-discovery.d.ts +2 -0
  20. package/dist/adapters/filesystem/project-discovery.js +30 -0
  21. package/dist/adapters/filesystem/project-discovery.js.map +1 -0
  22. package/dist/adapters/filesystem/project-files.d.ts +6 -0
  23. package/dist/adapters/filesystem/project-files.js +68 -0
  24. package/dist/adapters/filesystem/project-files.js.map +1 -0
  25. package/dist/adapters/filesystem/project-lock.d.ts +8 -0
  26. package/dist/adapters/filesystem/project-lock.js +164 -0
  27. package/dist/adapters/filesystem/project-lock.js.map +1 -0
  28. package/dist/adapters/filesystem/project-paths.d.ts +2 -0
  29. package/dist/adapters/filesystem/project-paths.js +60 -0
  30. package/dist/adapters/filesystem/project-paths.js.map +1 -0
  31. package/dist/adapters/filesystem/project-transaction.d.ts +24 -0
  32. package/dist/adapters/filesystem/project-transaction.js +177 -0
  33. package/dist/adapters/filesystem/project-transaction.js.map +1 -0
  34. package/dist/adapters/filesystem/reviewed-update-transaction.d.ts +53 -0
  35. package/dist/adapters/filesystem/reviewed-update-transaction.js +864 -0
  36. package/dist/adapters/filesystem/reviewed-update-transaction.js.map +1 -0
  37. package/dist/adapters/filesystem/update-previews.d.ts +50 -0
  38. package/dist/adapters/filesystem/update-previews.js +613 -0
  39. package/dist/adapters/filesystem/update-previews.js.map +1 -0
  40. package/dist/adapters/git/governance-assessment.d.ts +22 -0
  41. package/dist/adapters/git/governance-assessment.js +161 -0
  42. package/dist/adapters/git/governance-assessment.js.map +1 -0
  43. package/dist/adapters/github/governance-assessment.d.ts +2 -0
  44. package/dist/adapters/github/governance-assessment.js +18 -0
  45. package/dist/adapters/github/governance-assessment.js.map +1 -0
  46. package/dist/adapters/packaged-assets/package-root.d.ts +3 -0
  47. package/dist/adapters/packaged-assets/package-root.js +21 -0
  48. package/dist/adapters/packaged-assets/package-root.js.map +1 -0
  49. package/dist/adapters/packaged-assets/supported-stack.d.ts +4 -0
  50. package/dist/adapters/packaged-assets/supported-stack.js +18 -0
  51. package/dist/adapters/packaged-assets/supported-stack.js.map +1 -0
  52. package/dist/adapters/packaged-assets/template-assets.d.ts +23 -0
  53. package/dist/adapters/packaged-assets/template-assets.js +36 -0
  54. package/dist/adapters/packaged-assets/template-assets.js.map +1 -0
  55. package/dist/adapters/process/shell-command.d.ts +6 -0
  56. package/dist/adapters/process/shell-command.js +27 -0
  57. package/dist/adapters/process/shell-command.js.map +1 -0
  58. package/dist/application/context.d.ts +25 -0
  59. package/dist/application/context.js +2 -0
  60. package/dist/application/context.js.map +1 -0
  61. package/dist/application/diagnose/doctor.d.ts +21 -0
  62. package/dist/application/diagnose/doctor.js +580 -0
  63. package/dist/application/diagnose/doctor.js.map +1 -0
  64. package/dist/application/diagnose/generated-project.d.ts +1 -0
  65. package/dist/application/diagnose/generated-project.js +105 -0
  66. package/dist/application/diagnose/generated-project.js.map +1 -0
  67. package/dist/application/diagnose/validate.d.ts +6 -0
  68. package/dist/application/diagnose/validate.js +27 -0
  69. package/dist/application/diagnose/validate.js.map +1 -0
  70. package/dist/application/initialize/fixture.d.ts +2 -0
  71. package/dist/application/initialize/fixture.js +39 -0
  72. package/dist/application/initialize/fixture.js.map +1 -0
  73. package/dist/application/initialize/inputs.d.ts +3 -0
  74. package/dist/application/initialize/inputs.js +35 -0
  75. package/dist/application/initialize/inputs.js.map +1 -0
  76. package/dist/application/initialize/use-case.d.ts +23 -0
  77. package/dist/application/initialize/use-case.js +360 -0
  78. package/dist/application/initialize/use-case.js.map +1 -0
  79. package/dist/application/migrate/use-case.d.ts +7 -0
  80. package/dist/application/migrate/use-case.js +378 -0
  81. package/dist/application/migrate/use-case.js.map +1 -0
  82. package/dist/application/project/catalog.d.ts +46 -0
  83. package/dist/application/project/catalog.js +12 -0
  84. package/dist/application/project/catalog.js.map +1 -0
  85. package/dist/application/project/manifest.d.ts +2 -0
  86. package/dist/application/project/manifest.js +29 -0
  87. package/dist/application/project/manifest.js.map +1 -0
  88. package/dist/application/project/planning.d.ts +6 -0
  89. package/dist/application/project/planning.js +12 -0
  90. package/dist/application/project/planning.js.map +1 -0
  91. package/dist/application/update/approval.d.ts +39 -0
  92. package/dist/application/update/approval.js +54 -0
  93. package/dist/application/update/approval.js.map +1 -0
  94. package/dist/application/update/command-guidance.d.ts +2 -0
  95. package/dist/application/update/command-guidance.js +14 -0
  96. package/dist/application/update/command-guidance.js.map +1 -0
  97. package/dist/application/update/inspection.d.ts +37 -0
  98. package/dist/application/update/inspection.js +235 -0
  99. package/dist/application/update/inspection.js.map +1 -0
  100. package/dist/application/update/migration-runtime.d.ts +14 -0
  101. package/dist/application/update/migration-runtime.js +178 -0
  102. package/dist/application/update/migration-runtime.js.map +1 -0
  103. package/dist/application/update/output.d.ts +134 -0
  104. package/dist/application/update/output.js +182 -0
  105. package/dist/application/update/output.js.map +1 -0
  106. package/dist/application/update/planning.d.ts +40 -0
  107. package/dist/application/update/planning.js +293 -0
  108. package/dist/application/update/planning.js.map +1 -0
  109. package/dist/application/update/preview.d.ts +49 -0
  110. package/dist/application/update/preview.js +220 -0
  111. package/dist/application/update/preview.js.map +1 -0
  112. package/dist/application/update/protected-source.d.ts +25 -0
  113. package/dist/application/update/protected-source.js +81 -0
  114. package/dist/application/update/protected-source.js.map +1 -0
  115. package/dist/application/update/reporting.d.ts +42 -0
  116. package/dist/application/update/reporting.js +326 -0
  117. package/dist/application/update/reporting.js.map +1 -0
  118. package/dist/application/update/revalidation-plan.d.ts +22 -0
  119. package/dist/application/update/revalidation-plan.js +108 -0
  120. package/dist/application/update/revalidation-plan.js.map +1 -0
  121. package/dist/application/update/revalidation.d.ts +70 -0
  122. package/dist/application/update/revalidation.js +337 -0
  123. package/dist/application/update/revalidation.js.map +1 -0
  124. package/dist/application/update/review-plan.d.ts +25 -0
  125. package/dist/application/update/review-plan.js +89 -0
  126. package/dist/application/update/review-plan.js.map +1 -0
  127. package/dist/application/update/transaction-approval.d.ts +29 -0
  128. package/dist/application/update/transaction-approval.js +82 -0
  129. package/dist/application/update/transaction-approval.js.map +1 -0
  130. package/dist/application/update/use-case.d.ts +9 -0
  131. package/dist/application/update/use-case.js +271 -0
  132. package/dist/application/update/use-case.js.map +1 -0
  133. package/dist/application/update/write-plan.d.ts +15 -0
  134. package/dist/application/update/write-plan.js +115 -0
  135. package/dist/application/update/write-plan.js.map +1 -0
  136. package/dist/application/upgrade/use-case.d.ts +6 -0
  137. package/dist/application/upgrade/use-case.js +82 -0
  138. package/dist/application/upgrade/use-case.js.map +1 -0
  139. package/dist/args.d.ts +5 -65
  140. package/dist/args.js +4 -472
  141. package/dist/args.js.map +1 -1
  142. package/dist/artifact-lifecycle.d.ts +1 -21
  143. package/dist/artifact-lifecycle.js +1 -75
  144. package/dist/artifact-lifecycle.js.map +1 -1
  145. package/dist/catalogs.d.ts +1 -50
  146. package/dist/catalogs.js +1 -472
  147. package/dist/catalogs.js.map +1 -1
  148. package/dist/cli/args/contracts.d.ts +51 -0
  149. package/dist/cli/args/contracts.js +2 -0
  150. package/dist/cli/args/contracts.js.map +1 -0
  151. package/dist/cli/args/definitions.d.ts +6 -0
  152. package/dist/cli/args/definitions.js +188 -0
  153. package/dist/cli/args/definitions.js.map +1 -0
  154. package/dist/cli/args/help.d.ts +5 -0
  155. package/dist/cli/args/help.js +142 -0
  156. package/dist/cli/args/help.js.map +1 -0
  157. package/dist/cli/args/parser.d.ts +5 -0
  158. package/dist/cli/args/parser.js +160 -0
  159. package/dist/cli/args/parser.js.map +1 -0
  160. package/dist/cli/args/readers.d.ts +4 -0
  161. package/dist/cli/args/readers.js +19 -0
  162. package/dist/cli/args/readers.js.map +1 -0
  163. package/dist/cli/commands/diagnose.d.ts +4 -0
  164. package/dist/cli/commands/diagnose.js +12 -0
  165. package/dist/cli/commands/diagnose.js.map +1 -0
  166. package/dist/cli/commands/dispatch.d.ts +3 -0
  167. package/dist/cli/commands/dispatch.js +94 -0
  168. package/dist/cli/commands/dispatch.js.map +1 -0
  169. package/dist/cli/commands/help.d.ts +3 -0
  170. package/dist/cli/commands/help.js +32 -0
  171. package/dist/cli/commands/help.js.map +1 -0
  172. package/dist/cli/commands/helpers.d.ts +8 -0
  173. package/dist/cli/commands/helpers.js +97 -0
  174. package/dist/cli/commands/helpers.js.map +1 -0
  175. package/dist/cli/commands/initialize.d.ts +3 -0
  176. package/dist/cli/commands/initialize.js +7 -0
  177. package/dist/cli/commands/initialize.js.map +1 -0
  178. package/dist/cli/commands/migrate.d.ts +3 -0
  179. package/dist/cli/commands/migrate.js +8 -0
  180. package/dist/cli/commands/migrate.js.map +1 -0
  181. package/dist/cli/commands/plan.d.ts +3 -0
  182. package/dist/cli/commands/plan.js +34 -0
  183. package/dist/cli/commands/plan.js.map +1 -0
  184. package/dist/cli/commands/reference.d.ts +5 -0
  185. package/dist/cli/commands/reference.js +43 -0
  186. package/dist/cli/commands/reference.js.map +1 -0
  187. package/dist/cli/commands/update.d.ts +3 -0
  188. package/dist/cli/commands/update.js +10 -0
  189. package/dist/cli/commands/update.js.map +1 -0
  190. package/dist/cli/commands/upgrade.d.ts +3 -0
  191. package/dist/cli/commands/upgrade.js +7 -0
  192. package/dist/cli/commands/upgrade.js.map +1 -0
  193. package/dist/cli/context.d.ts +1 -0
  194. package/dist/cli/context.js +2 -0
  195. package/dist/cli/context.js.map +1 -0
  196. package/dist/cli/project-options.d.ts +3 -0
  197. package/dist/cli/project-options.js +41 -0
  198. package/dist/cli/project-options.js.map +1 -0
  199. package/dist/cli.d.ts +3 -3
  200. package/dist/cli.js +2 -2
  201. package/dist/cli.js.map +1 -1
  202. package/dist/commands.d.ts +4 -35
  203. package/dist/commands.js +3 -2969
  204. package/dist/commands.js.map +1 -1
  205. package/dist/container-validation.d.ts +1 -1
  206. package/dist/domain/governance/activation/approvals.d.ts +351 -0
  207. package/dist/domain/governance/activation/approvals.js +528 -0
  208. package/dist/domain/governance/activation/approvals.js.map +1 -0
  209. package/dist/domain/governance/activation/canonical-json.d.ts +4 -0
  210. package/dist/domain/governance/activation/canonical-json.js +39 -0
  211. package/dist/domain/governance/activation/canonical-json.js.map +1 -0
  212. package/dist/domain/governance/activation/capabilities.d.ts +7 -0
  213. package/dist/domain/governance/activation/capabilities.js +33 -0
  214. package/dist/domain/governance/activation/capabilities.js.map +1 -0
  215. package/dist/domain/governance/activation/evidence.d.ts +63 -0
  216. package/dist/domain/governance/activation/evidence.js +444 -0
  217. package/dist/domain/governance/activation/evidence.js.map +1 -0
  218. package/dist/domain/governance/activation/graph.d.ts +397 -0
  219. package/dist/domain/governance/activation/graph.js +441 -0
  220. package/dist/domain/governance/activation/graph.js.map +1 -0
  221. package/dist/domain/governance/activation/inputs.d.ts +25 -0
  222. package/dist/domain/governance/activation/inputs.js +63 -0
  223. package/dist/domain/governance/activation/inputs.js.map +1 -0
  224. package/dist/domain/governance/activation/operations.d.ts +19 -0
  225. package/dist/domain/governance/activation/operations.js +181 -0
  226. package/dist/domain/governance/activation/operations.js.map +1 -0
  227. package/dist/domain/governance/activation/readiness.d.ts +27 -0
  228. package/dist/domain/governance/activation/readiness.js +269 -0
  229. package/dist/domain/governance/activation/readiness.js.map +1 -0
  230. package/dist/domain/governance/activation/types.d.ts +399 -0
  231. package/dist/domain/governance/activation/types.js +109 -0
  232. package/dist/domain/governance/activation/types.js.map +1 -0
  233. package/dist/domain/governance/activation/validators.d.ts +22 -0
  234. package/dist/domain/governance/activation/validators.js +1347 -0
  235. package/dist/domain/governance/activation/validators.js.map +1 -0
  236. package/dist/domain/governance/assessment/catalog.d.ts +14 -0
  237. package/dist/domain/governance/assessment/catalog.js +105 -0
  238. package/dist/domain/governance/assessment/catalog.js.map +1 -0
  239. package/dist/domain/governance/assessment/errors.d.ts +10 -0
  240. package/dist/domain/governance/assessment/errors.js +22 -0
  241. package/dist/domain/governance/assessment/errors.js.map +1 -0
  242. package/dist/domain/governance/assessment/index.d.ts +8 -0
  243. package/dist/domain/governance/assessment/index.js +9 -0
  244. package/dist/domain/governance/assessment/index.js.map +1 -0
  245. package/dist/domain/governance/assessment/live-normalize.d.ts +19 -0
  246. package/dist/domain/governance/assessment/live-normalize.js +403 -0
  247. package/dist/domain/governance/assessment/live-normalize.js.map +1 -0
  248. package/dist/domain/governance/assessment/predicates.d.ts +36 -0
  249. package/dist/domain/governance/assessment/predicates.js +545 -0
  250. package/dist/domain/governance/assessment/predicates.js.map +1 -0
  251. package/dist/domain/governance/assessment/report.d.ts +23 -0
  252. package/dist/domain/governance/assessment/report.js +266 -0
  253. package/dist/domain/governance/assessment/report.js.map +1 -0
  254. package/dist/domain/governance/assessment/sanitize.d.ts +8 -0
  255. package/dist/domain/governance/assessment/sanitize.js +60 -0
  256. package/dist/domain/governance/assessment/sanitize.js.map +1 -0
  257. package/dist/domain/governance/assessment/types.d.ts +174 -0
  258. package/dist/domain/governance/assessment/types.js +13 -0
  259. package/dist/domain/governance/assessment/types.js.map +1 -0
  260. package/dist/domain/governance/assessment/yaml.d.ts +6 -0
  261. package/dist/domain/governance/assessment/yaml.js +30 -0
  262. package/dist/domain/governance/assessment/yaml.js.map +1 -0
  263. package/dist/domain/governance/policy/identity.d.ts +64 -0
  264. package/dist/domain/governance/policy/identity.js +112 -0
  265. package/dist/domain/governance/policy/identity.js.map +1 -0
  266. package/dist/domain/migration/dependencies.d.ts +7 -0
  267. package/dist/domain/migration/dependencies.js +221 -0
  268. package/dist/domain/migration/dependencies.js.map +1 -0
  269. package/dist/domain/migration/inventory.d.ts +3 -0
  270. package/dist/domain/migration/inventory.js +15 -0
  271. package/dist/domain/migration/inventory.js.map +1 -0
  272. package/dist/domain/project/artifact-lifecycle.d.ts +69 -0
  273. package/dist/domain/project/artifact-lifecycle.js +137 -0
  274. package/dist/domain/project/artifact-lifecycle.js.map +1 -0
  275. package/dist/domain/project/catalog.d.ts +48 -0
  276. package/dist/domain/project/catalog.js +507 -0
  277. package/dist/domain/project/catalog.js.map +1 -0
  278. package/dist/domain/project/contracts.d.ts +247 -0
  279. package/dist/domain/project/contracts.js +2 -0
  280. package/dist/domain/project/contracts.js.map +1 -0
  281. package/dist/domain/project/errors.d.ts +3 -0
  282. package/dist/domain/project/errors.js +7 -0
  283. package/dist/domain/project/errors.js.map +1 -0
  284. package/dist/domain/project/infrastructure-layout.d.ts +26 -0
  285. package/dist/domain/project/infrastructure-layout.js +125 -0
  286. package/dist/domain/project/infrastructure-layout.js.map +1 -0
  287. package/dist/domain/project/inputs.d.ts +21 -0
  288. package/dist/domain/project/inputs.js +41 -0
  289. package/dist/domain/project/inputs.js.map +1 -0
  290. package/dist/domain/project/manifest/artifacts.d.ts +8 -0
  291. package/dist/domain/project/manifest/artifacts.js +150 -0
  292. package/dist/domain/project/manifest/artifacts.js.map +1 -0
  293. package/dist/domain/project/manifest/context.d.ts +13 -0
  294. package/dist/domain/project/manifest/context.js +2 -0
  295. package/dist/domain/project/manifest/context.js.map +1 -0
  296. package/dist/domain/project/manifest/fields.d.ts +6 -0
  297. package/dist/domain/project/manifest/fields.js +36 -0
  298. package/dist/domain/project/manifest/fields.js.map +1 -0
  299. package/dist/domain/project/manifest/governance.d.ts +8 -0
  300. package/dist/domain/project/manifest/governance.js +161 -0
  301. package/dist/domain/project/manifest/governance.js.map +1 -0
  302. package/dist/domain/project/manifest/project-identity.d.ts +6 -0
  303. package/dist/domain/project/manifest/project-identity.js +273 -0
  304. package/dist/domain/project/manifest/project-identity.js.map +1 -0
  305. package/dist/domain/project/manifest/reader.d.ts +9 -0
  306. package/dist/domain/project/manifest/reader.js +141 -0
  307. package/dist/domain/project/manifest/reader.js.map +1 -0
  308. package/dist/domain/project/paths.d.ts +2 -0
  309. package/dist/domain/project/paths.js +29 -0
  310. package/dist/domain/project/paths.js.map +1 -0
  311. package/dist/domain/project/planning.d.ts +19 -0
  312. package/dist/domain/project/planning.js +329 -0
  313. package/dist/domain/project/planning.js.map +1 -0
  314. package/dist/domain/project/retired-workload.d.ts +4 -0
  315. package/dist/domain/project/retired-workload.js +18 -0
  316. package/dist/domain/project/retired-workload.js.map +1 -0
  317. package/dist/domain/project/reviewed-update-artifacts.d.ts +2 -0
  318. package/dist/domain/project/reviewed-update-artifacts.js +3 -0
  319. package/dist/domain/project/reviewed-update-artifacts.js.map +1 -0
  320. package/dist/domain/project/supported-stack.d.ts +113 -0
  321. package/dist/domain/project/supported-stack.js +426 -0
  322. package/dist/domain/project/supported-stack.js.map +1 -0
  323. package/dist/domain/workstation/constraints.d.ts +6 -0
  324. package/dist/domain/workstation/constraints.js +8 -0
  325. package/dist/domain/workstation/constraints.js.map +1 -0
  326. package/dist/file-system.d.ts +10 -44
  327. package/dist/file-system.js +9 -1245
  328. package/dist/file-system.js.map +1 -1
  329. package/dist/framework-adapters.d.ts +1 -1
  330. package/dist/framework-validation.d.ts +1 -1
  331. package/dist/framework-validation.js +1 -1
  332. package/dist/framework-validation.js.map +1 -1
  333. package/dist/genai-templates.d.ts +2 -9
  334. package/dist/genai-templates.js +4 -5
  335. package/dist/genai-templates.js.map +1 -1
  336. package/dist/generators/common/artifacts.d.ts +6 -0
  337. package/dist/generators/common/artifacts.js +30 -0
  338. package/dist/generators/common/artifacts.js.map +1 -0
  339. package/dist/generators/common/base.d.ts +17 -0
  340. package/dist/generators/common/base.js +425 -0
  341. package/dist/generators/common/base.js.map +1 -0
  342. package/dist/generators/common/dotenv-validation.d.ts +2 -0
  343. package/dist/generators/common/dotenv-validation.js +80 -0
  344. package/dist/generators/common/dotenv-validation.js.map +1 -0
  345. package/dist/generators/common/environments.d.ts +3 -0
  346. package/dist/generators/common/environments.js +15 -0
  347. package/dist/generators/common/environments.js.map +1 -0
  348. package/dist/generators/common/frontend.d.ts +15 -0
  349. package/dist/generators/common/frontend.js +166 -0
  350. package/dist/generators/common/frontend.js.map +1 -0
  351. package/dist/generators/common/python-settings.d.ts +2 -0
  352. package/dist/generators/common/python-settings.js +70 -0
  353. package/dist/generators/common/python-settings.js.map +1 -0
  354. package/dist/generators/common/spec-workflow.d.ts +28 -0
  355. package/dist/generators/common/spec-workflow.js +567 -0
  356. package/dist/generators/common/spec-workflow.js.map +1 -0
  357. package/dist/generators/common/values.d.ts +13 -0
  358. package/dist/generators/common/values.js +16 -0
  359. package/dist/generators/common/values.js.map +1 -0
  360. package/dist/generators/containers/compose.d.ts +7 -0
  361. package/dist/generators/containers/compose.js +196 -0
  362. package/dist/generators/containers/compose.js.map +1 -0
  363. package/dist/generators/containers/context.d.ts +1 -0
  364. package/dist/generators/containers/context.js +43 -0
  365. package/dist/generators/containers/context.js.map +1 -0
  366. package/dist/generators/containers/images.d.ts +7 -0
  367. package/dist/generators/containers/images.js +119 -0
  368. package/dist/generators/containers/images.js.map +1 -0
  369. package/dist/generators/context.d.ts +42 -0
  370. package/dist/generators/context.js +38 -0
  371. package/dist/generators/context.js.map +1 -0
  372. package/dist/generators/genai/backend.d.ts +20 -0
  373. package/dist/generators/genai/backend.js +667 -0
  374. package/dist/generators/genai/backend.js.map +1 -0
  375. package/dist/generators/genai/configuration.d.ts +3 -0
  376. package/dist/generators/genai/configuration.js +43 -0
  377. package/dist/generators/genai/configuration.js.map +1 -0
  378. package/dist/generators/genai/database.d.ts +7 -0
  379. package/dist/generators/genai/database.js +71 -0
  380. package/dist/generators/genai/database.js.map +1 -0
  381. package/dist/generators/genai/functions.d.ts +15 -0
  382. package/dist/generators/genai/functions.js +156 -0
  383. package/dist/generators/genai/functions.js.map +1 -0
  384. package/dist/generators/genai/index.d.ts +8 -0
  385. package/dist/generators/genai/index.js +11 -0
  386. package/dist/generators/genai/index.js.map +1 -0
  387. package/dist/generators/genai/patterns.d.ts +9 -0
  388. package/dist/generators/genai/patterns.js +309 -0
  389. package/dist/generators/genai/patterns.js.map +1 -0
  390. package/dist/generators/infrastructure/azure.d.ts +18 -0
  391. package/dist/generators/infrastructure/azure.js +655 -0
  392. package/dist/generators/infrastructure/azure.js.map +1 -0
  393. package/dist/generators/infrastructure/names.d.ts +23 -0
  394. package/dist/generators/infrastructure/names.js +51 -0
  395. package/dist/generators/infrastructure/names.js.map +1 -0
  396. package/dist/generators/standard/configuration.d.ts +3 -0
  397. package/dist/generators/standard/configuration.js +26 -0
  398. package/dist/generators/standard/configuration.js.map +1 -0
  399. package/dist/generators/standard/go.d.ts +17 -0
  400. package/dist/generators/standard/go.js +338 -0
  401. package/dist/generators/standard/go.js.map +1 -0
  402. package/dist/generators/standard/index.d.ts +12 -0
  403. package/dist/generators/standard/index.js +12 -0
  404. package/dist/generators/standard/index.js.map +1 -0
  405. package/dist/generators/standard/node.d.ts +20 -0
  406. package/dist/generators/standard/node.js +314 -0
  407. package/dist/generators/standard/node.js.map +1 -0
  408. package/dist/generators/standard/python.d.ts +18 -0
  409. package/dist/generators/standard/python.js +191 -0
  410. package/dist/generators/standard/python.js.map +1 -0
  411. package/dist/go-template-assets.js +3 -3
  412. package/dist/go-template-assets.js.map +1 -1
  413. package/dist/governance-activation/activation-state.d.ts +1 -1
  414. package/dist/governance-activation/activation-state.js +49 -9
  415. package/dist/governance-activation/activation-state.js.map +1 -1
  416. package/dist/governance-activation/approvals.d.ts +1 -188
  417. package/dist/governance-activation/approvals.js +1 -507
  418. package/dist/governance-activation/approvals.js.map +1 -1
  419. package/dist/governance-activation/canonical-json.d.ts +1 -3
  420. package/dist/governance-activation/canonical-json.js +1 -35
  421. package/dist/governance-activation/canonical-json.js.map +1 -1
  422. package/dist/governance-activation/commands.d.ts +6 -1
  423. package/dist/governance-activation/commands.js +135 -107
  424. package/dist/governance-activation/commands.js.map +1 -1
  425. package/dist/governance-activation/compatibility.d.ts +30 -5
  426. package/dist/governance-activation/compatibility.js +74 -8
  427. package/dist/governance-activation/compatibility.js.map +1 -1
  428. package/dist/governance-activation/credentials.d.ts +3 -3
  429. package/dist/governance-activation/credentials.js +5 -5
  430. package/dist/governance-activation/credentials.js.map +1 -1
  431. package/dist/governance-activation/doctor.d.ts +1 -1
  432. package/dist/governance-activation/doctor.js +59 -100
  433. package/dist/governance-activation/doctor.js.map +1 -1
  434. package/dist/governance-activation/evidence.d.ts +1 -49
  435. package/dist/governance-activation/evidence.js +1 -245
  436. package/dist/governance-activation/evidence.js.map +1 -1
  437. package/dist/governance-activation/git-ignore.d.ts +9 -0
  438. package/dist/governance-activation/git-ignore.js +76 -0
  439. package/dist/governance-activation/git-ignore.js.map +1 -0
  440. package/dist/governance-activation/graph.d.ts +1 -397
  441. package/dist/governance-activation/graph.js +1 -440
  442. package/dist/governance-activation/graph.js.map +1 -1
  443. package/dist/governance-activation/historical-state.d.ts +81 -0
  444. package/dist/governance-activation/historical-state.js +817 -0
  445. package/dist/governance-activation/historical-state.js.map +1 -0
  446. package/dist/governance-activation/history-contracts.d.ts +109 -0
  447. package/dist/governance-activation/history-contracts.js +303 -0
  448. package/dist/governance-activation/history-contracts.js.map +1 -0
  449. package/dist/governance-activation/identity.d.ts +1 -35
  450. package/dist/governance-activation/identity.js +1 -88
  451. package/dist/governance-activation/identity.js.map +1 -1
  452. package/dist/governance-activation/index.d.ts +3 -0
  453. package/dist/governance-activation/index.js +3 -0
  454. package/dist/governance-activation/index.js.map +1 -1
  455. package/dist/governance-activation/inputs.d.ts +10 -0
  456. package/dist/governance-activation/inputs.js +158 -0
  457. package/dist/governance-activation/inputs.js.map +1 -0
  458. package/dist/governance-activation/migration-history.d.ts +97 -0
  459. package/dist/governance-activation/migration-history.js +388 -0
  460. package/dist/governance-activation/migration-history.js.map +1 -0
  461. package/dist/governance-activation/migration.d.ts +4 -3
  462. package/dist/governance-activation/migration.js +14 -6
  463. package/dist/governance-activation/migration.js.map +1 -1
  464. package/dist/governance-activation/phase-bootstrap-state.d.ts +3 -0
  465. package/dist/governance-activation/phase-bootstrap-state.js +128 -0
  466. package/dist/governance-activation/phase-bootstrap-state.js.map +1 -0
  467. package/dist/governance-activation/phase-discovery.d.ts +2 -0
  468. package/dist/governance-activation/phase-discovery.js +88 -0
  469. package/dist/governance-activation/phase-discovery.js.map +1 -0
  470. package/dist/governance-activation/phase-governance.d.ts +4 -0
  471. package/dist/governance-activation/phase-governance.js +141 -0
  472. package/dist/governance-activation/phase-governance.js.map +1 -0
  473. package/dist/governance-activation/phase-publication.d.ts +8 -0
  474. package/dist/governance-activation/phase-publication.js +318 -0
  475. package/dist/governance-activation/phase-publication.js.map +1 -0
  476. package/dist/governance-activation/proof-records.d.ts +3 -0
  477. package/dist/governance-activation/proof-records.js +78 -0
  478. package/dist/governance-activation/proof-records.js.map +1 -0
  479. package/dist/governance-activation/read-only.d.ts +30 -0
  480. package/dist/governance-activation/read-only.js +33 -0
  481. package/dist/governance-activation/read-only.js.map +1 -0
  482. package/dist/governance-activation/readiness.d.ts +1 -25
  483. package/dist/governance-activation/readiness.js +1 -222
  484. package/dist/governance-activation/readiness.js.map +1 -1
  485. package/dist/governance-activation/reconciliation.d.ts +1 -1
  486. package/dist/governance-activation/reconciliation.js +3 -3
  487. package/dist/governance-activation/reconciliation.js.map +1 -1
  488. package/dist/governance-activation/release-integrity.d.ts +1 -1
  489. package/dist/governance-activation/release-integrity.js +2 -2
  490. package/dist/governance-activation/release-integrity.js.map +1 -1
  491. package/dist/governance-activation/seed-lifecycle.d.ts +36 -6
  492. package/dist/governance-activation/seed-lifecycle.js +444 -77
  493. package/dist/governance-activation/seed-lifecycle.js.map +1 -1
  494. package/dist/governance-activation/source-of-truth.d.ts +5 -3
  495. package/dist/governance-activation/source-of-truth.js +32 -52
  496. package/dist/governance-activation/source-of-truth.js.map +1 -1
  497. package/dist/governance-activation/spec-kit-seed.d.ts +9 -0
  498. package/dist/governance-activation/spec-kit-seed.js +43 -0
  499. package/dist/governance-activation/spec-kit-seed.js.map +1 -0
  500. package/dist/governance-activation/task-projection.d.ts +1 -1
  501. package/dist/governance-activation/transition-planning.d.ts +17 -0
  502. package/dist/governance-activation/transition-planning.js +259 -0
  503. package/dist/governance-activation/transition-planning.js.map +1 -0
  504. package/dist/governance-activation/transition-ports.d.ts +150 -0
  505. package/dist/governance-activation/transition-ports.js +2 -0
  506. package/dist/governance-activation/transition-ports.js.map +1 -0
  507. package/dist/governance-activation/transition-process.d.ts +7 -0
  508. package/dist/governance-activation/transition-process.js +21 -0
  509. package/dist/governance-activation/transition-process.js.map +1 -0
  510. package/dist/governance-activation/transition-records.d.ts +56 -0
  511. package/dist/governance-activation/transition-records.js +208 -0
  512. package/dist/governance-activation/transition-records.js.map +1 -0
  513. package/dist/governance-activation/transitions.d.ts +14 -167
  514. package/dist/governance-activation/transitions.js +173 -2061
  515. package/dist/governance-activation/transitions.js.map +1 -1
  516. package/dist/governance-activation/types.d.ts +1 -390
  517. package/dist/governance-activation/types.js +1 -107
  518. package/dist/governance-activation/types.js.map +1 -1
  519. package/dist/governance-activation/validators.d.ts +1 -17
  520. package/dist/governance-activation/validators.js +1 -1304
  521. package/dist/governance-activation/validators.js.map +1 -1
  522. package/dist/governance-assessment/catalog.d.ts +1 -2
  523. package/dist/governance-assessment/catalog.js +18 -85
  524. package/dist/governance-assessment/catalog.js.map +1 -1
  525. package/dist/governance-assessment/command.d.ts +1 -1
  526. package/dist/governance-assessment/command.js +8 -12
  527. package/dist/governance-assessment/command.js.map +1 -1
  528. package/dist/governance-assessment/engine.d.ts +6 -11
  529. package/dist/governance-assessment/engine.js +490 -114
  530. package/dist/governance-assessment/engine.js.map +1 -1
  531. package/dist/governance-assessment/live-normalize.d.ts +1 -19
  532. package/dist/governance-assessment/live-normalize.js +1 -402
  533. package/dist/governance-assessment/live-normalize.js.map +1 -1
  534. package/dist/governance-assessment/live-transport.d.ts +2 -6
  535. package/dist/governance-assessment/live-transport.js +10 -22
  536. package/dist/governance-assessment/live-transport.js.map +1 -1
  537. package/dist/governance-assessment/live.js +55 -5
  538. package/dist/governance-assessment/live.js.map +1 -1
  539. package/dist/governance-assessment/predicates.d.ts +1 -27
  540. package/dist/governance-assessment/predicates.js +1 -329
  541. package/dist/governance-assessment/predicates.js.map +1 -1
  542. package/dist/governance-assessment/project.d.ts +20 -17
  543. package/dist/governance-assessment/project.js +101 -151
  544. package/dist/governance-assessment/project.js.map +1 -1
  545. package/dist/governance-assessment/readers.d.ts +1 -5
  546. package/dist/governance-assessment/readers.js +5 -13
  547. package/dist/governance-assessment/readers.js.map +1 -1
  548. package/dist/governance-assessment/report.d.ts +1 -23
  549. package/dist/governance-assessment/report.js +1 -265
  550. package/dist/governance-assessment/report.js.map +1 -1
  551. package/dist/governance-assessment/sanitize.d.ts +1 -8
  552. package/dist/governance-assessment/sanitize.js +1 -56
  553. package/dist/governance-assessment/sanitize.js.map +1 -1
  554. package/dist/governance-assessment/types.d.ts +1 -173
  555. package/dist/governance-assessment/types.js +1 -12
  556. package/dist/governance-assessment/types.js.map +1 -1
  557. package/dist/governance-assessment/yaml.d.ts +1 -6
  558. package/dist/governance-assessment/yaml.js +1 -29
  559. package/dist/governance-assessment/yaml.js.map +1 -1
  560. package/dist/init-filesystem.d.ts +1 -1
  561. package/dist/init-filesystem.js +126 -174
  562. package/dist/init-filesystem.js.map +1 -1
  563. package/dist/interactive.d.ts +2 -2
  564. package/dist/interactive.js +42 -41
  565. package/dist/interactive.js.map +1 -1
  566. package/dist/migrate-plan.d.ts +1 -1
  567. package/dist/migrate-plan.js +14 -8
  568. package/dist/migrate-plan.js.map +1 -1
  569. package/dist/npm-template-assets.js +5 -4
  570. package/dist/npm-template-assets.js.map +1 -1
  571. package/dist/openspec-profile.d.ts +1 -1
  572. package/dist/opentofu-template-assets.js +3 -3
  573. package/dist/opentofu-template-assets.js.map +1 -1
  574. package/dist/package-identity.d.ts +3 -0
  575. package/dist/package-identity.js +13 -2
  576. package/dist/package-identity.js.map +1 -1
  577. package/dist/planner.d.ts +1 -19
  578. package/dist/planner.js +1 -565
  579. package/dist/planner.js.map +1 -1
  580. package/dist/process-runner.d.ts +1 -1
  581. package/dist/project-dependencies.d.ts +5 -3
  582. package/dist/project-dependencies.js +74 -63
  583. package/dist/project-dependencies.js.map +1 -1
  584. package/dist/published-verifier.js +61 -30
  585. package/dist/published-verifier.js.map +1 -1
  586. package/dist/python-template-assets.js +6 -9
  587. package/dist/python-template-assets.js.map +1 -1
  588. package/dist/reconcile.d.ts +1 -1
  589. package/dist/reconcile.js +2 -2
  590. package/dist/reconcile.js.map +1 -1
  591. package/dist/repository-governance.d.ts +5 -2
  592. package/dist/repository-governance.js +140 -113
  593. package/dist/repository-governance.js.map +1 -1
  594. package/dist/runtime.js +1 -1
  595. package/dist/runtime.js.map +1 -1
  596. package/dist/scan.d.ts +6 -2
  597. package/dist/scan.js +78 -30
  598. package/dist/scan.js.map +1 -1
  599. package/dist/self-upgrade.d.ts +1 -1
  600. package/dist/self-upgrade.js +20 -7
  601. package/dist/self-upgrade.js.map +1 -1
  602. package/dist/stable-release.js +7 -1
  603. package/dist/stable-release.js.map +1 -1
  604. package/dist/standard-templates.d.ts +2 -2
  605. package/dist/standard-templates.js +6 -841
  606. package/dist/standard-templates.js.map +1 -1
  607. package/dist/supported-stack.d.ts +3 -115
  608. package/dist/supported-stack.js +4 -438
  609. package/dist/supported-stack.js.map +1 -1
  610. package/dist/telemetry/index.d.ts +1 -1
  611. package/dist/templates.d.ts +10 -20
  612. package/dist/templates.js +52 -3261
  613. package/dist/templates.js.map +1 -1
  614. package/dist/types.d.ts +1 -263
  615. package/dist/types.js +1 -1
  616. package/dist/types.js.map +1 -1
  617. package/dist/version.js +2 -6
  618. package/dist/version.js.map +1 -1
  619. package/dist/workstation-catalog.d.ts +5 -2
  620. package/dist/workstation-catalog.js +33 -2
  621. package/dist/workstation-catalog.js.map +1 -1
  622. package/dist/workstation.d.ts +4 -3
  623. package/dist/workstation.js +86 -32
  624. package/dist/workstation.js.map +1 -1
  625. package/docs/assets/liftoff-terminal.svg +3 -3
  626. package/docs/azure-deployment.md +107 -10
  627. package/docs/cli-reference.md +144 -35
  628. package/docs/configuration-and-manifests.md +152 -35
  629. package/docs/existing-repositories.md +48 -12
  630. package/docs/getting-started.md +44 -31
  631. package/docs/prerequisites.md +34 -35
  632. package/docs/project-structure.md +39 -46
  633. package/docs/repository-governance.md +96 -26
  634. package/docs/safety-and-consent.md +90 -28
  635. package/docs/spec-workflows-and-agents.md +31 -28
  636. package/docs/supported-stack.md +11 -9
  637. package/docs/troubleshooting.md +114 -54
  638. package/docs/workloads.md +52 -67
  639. package/package.json +4 -7
  640. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/UPSTREAM_LICENSE.txt +0 -21
  641. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/catalog.json +0 -520
  642. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/packaged/gitignore +0 -27
  643. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/README.md +0 -25
  644. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/components.json +0 -22
  645. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/eslint.config.js +0 -23
  646. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/index.html +0 -13
  647. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/package-lock.json +0 -6156
  648. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/package.json +0 -60
  649. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/public/power-apps.svg +0 -55
  650. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/App.tsx +0 -17
  651. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/assets/react.svg +0 -1
  652. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/mode-toggle.tsx +0 -37
  653. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/badge.tsx +0 -46
  654. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/button.tsx +0 -60
  655. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/calendar.tsx +0 -211
  656. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/card.tsx +0 -92
  657. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/chart.tsx +0 -355
  658. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/checkbox.tsx +0 -32
  659. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/command.tsx +0 -184
  660. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/dialog.tsx +0 -141
  661. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/dropdown-menu.tsx +0 -257
  662. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/input.tsx +0 -21
  663. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/label.tsx +0 -22
  664. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/popover.tsx +0 -46
  665. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/progress.tsx +0 -29
  666. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/select.tsx +0 -185
  667. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/separator.tsx +0 -26
  668. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/skeleton.tsx +0 -13
  669. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/table.tsx +0 -114
  670. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/tabs.tsx +0 -66
  671. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/textarea.tsx +0 -18
  672. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/tooltip.tsx +0 -61
  673. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/hooks/use-theme.ts +0 -11
  674. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/index.css +0 -131
  675. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/lib/utils.ts +0 -6
  676. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/main.tsx +0 -10
  677. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/_layout.tsx +0 -31
  678. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/home.tsx +0 -59
  679. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/not-found.tsx +0 -14
  680. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/query-provider.tsx +0 -26
  681. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/sonner-provider.tsx +0 -23
  682. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/theme-provider.tsx +0 -64
  683. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/router.tsx +0 -24
  684. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.app.json +0 -34
  685. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.json +0 -13
  686. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.node.json +0 -26
  687. package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/vite.config.ts +0 -19
  688. package/assets/power-apps-code-app/README.md +0 -27
  689. package/dist/code-apps-plugin.d.ts +0 -13
  690. package/dist/code-apps-plugin.js +0 -69
  691. package/dist/code-apps-plugin.js.map +0 -1
  692. package/dist/power-apps-assets.d.ts +0 -30
  693. package/dist/power-apps-assets.js +0 -131
  694. package/dist/power-apps-assets.js.map +0 -1
  695. package/dist/power-apps-templates.d.ts +0 -3
  696. package/dist/power-apps-templates.js +0 -177
  697. package/dist/power-apps-templates.js.map +0 -1
  698. package/dist/power-apps-validation.d.ts +0 -1
  699. package/dist/power-apps-validation.js +0 -79
  700. package/dist/power-apps-validation.js.map +0 -1
@@ -0,0 +1,1347 @@
1
+ import { activationCompatibility, canonicalPhaseGraph, canonicalPhaseGraphHash, currentActivationIdentity } from './graph.js';
2
+ import { activationContractVersion, activationStateSchemaVersion, approvalEnvelopeSchemaVersion, credentialPolicySchemaVersion, evidenceHeaderSchemaVersion, governanceActivationPolicyVersion, liftoffActivationPackageVersion, liftoffManifestArtifactVersion, phaseGraphSchemaVersion, resolveActivationCompatibility, supersessionSchemaVersion, isHistoricalActivationIdentity } from '../policy/identity.js';
3
+ import { normalizeApprovalCostCeiling, normalizeApprovalDestinations, normalizeApprovalDestructiveScope, normalizeApprovalPermissions, normalizeApprovalPolicyExceptions, normalizeApprovalResources } from './approvals.js';
4
+ import { approvalGateKinds, invalidationInputKinds, mutationClasses, phaseIds, phaseStates, rollbackKinds, runnerPreflightDisplayNameTemplate, runnerPreflightOrganizationPermissions, runnerPreflightPatLifetimeDays, runnerPreflightRepositoryPermissions, runnerPreflightRotationLeadDays, runnerPreflightSecretName } from './types.js';
5
+ const phaseIdSet = new Set(phaseIds);
6
+ const terminalPhaseStateSet = new Set(['approved', 'verified', 'failed', 'inapplicable', 'retained', 'disposed']);
7
+ const resultStateSet = new Set(['verified', 'failed', 'inapplicable', 'retained', 'disposed']);
8
+ const hex64Pattern = /^[a-f0-9]{64}$/;
9
+ const isoLikePattern = /^\d{4}-\d{2}-\d{2}T/;
10
+ const liveReadbackProviderSet = new Set(['github', 'azure']);
11
+ const githubRemoteWriteMutations = new Set(['github-write', 'github-secret-write', 'github-ruleset-write']);
12
+ const azureRemoteWriteMutations = new Set([
13
+ 'azure-provider-register',
14
+ 'azure-network-provision',
15
+ 'azure-state-import',
16
+ 'azure-resource-provision'
17
+ ]);
18
+ const transitionAdapterIds = new Set([
19
+ 'local-evidence',
20
+ 'selected-spec-workflow',
21
+ 'git',
22
+ 'github',
23
+ 'azure-opentofu',
24
+ 'local-state'
25
+ ]);
26
+ function record(value, path) {
27
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
28
+ throw new Error(`${path} must be an object.`);
29
+ }
30
+ return value;
31
+ }
32
+ function exact(value, requiredKeys, path) {
33
+ const item = record(value, path);
34
+ for (const key of requiredKeys) {
35
+ if (!Object.hasOwn(item, key)) {
36
+ throw new Error(`${path}.${key} is required.`);
37
+ }
38
+ }
39
+ const allowed = new Set(requiredKeys);
40
+ for (const key of Object.keys(item)) {
41
+ if (!allowed.has(key)) {
42
+ throw new Error(`${path}.${key} is not allowed.`);
43
+ }
44
+ }
45
+ return item;
46
+ }
47
+ function exactWithOptional(value, requiredKeys, optionalKeys, path) {
48
+ const item = record(value, path);
49
+ for (const key of requiredKeys) {
50
+ if (!Object.hasOwn(item, key)) {
51
+ throw new Error(`${path}.${key} is required.`);
52
+ }
53
+ }
54
+ const allowed = new Set([...requiredKeys, ...optionalKeys]);
55
+ for (const key of Object.keys(item)) {
56
+ if (!allowed.has(key)) {
57
+ throw new Error(`${path}.${key} is not allowed.`);
58
+ }
59
+ }
60
+ return item;
61
+ }
62
+ function stringField(item, key, path) {
63
+ const value = item[key];
64
+ if (typeof value !== 'string' || value.length === 0) {
65
+ throw new Error(`${path}.${key} must be a non-empty string.`);
66
+ }
67
+ return value;
68
+ }
69
+ function booleanField(item, key, path) {
70
+ const value = item[key];
71
+ if (typeof value !== 'boolean') {
72
+ throw new Error(`${path}.${key} must be a boolean.`);
73
+ }
74
+ return value;
75
+ }
76
+ function numberField(item, key, path) {
77
+ const value = item[key];
78
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
79
+ throw new Error(`${path}.${key} must be a finite number.`);
80
+ }
81
+ return value;
82
+ }
83
+ function integerField(item, key, path) {
84
+ const value = numberField(item, key, path);
85
+ if (!Number.isSafeInteger(value)) {
86
+ throw new Error(`${path}.${key} must be a safe integer.`);
87
+ }
88
+ return value;
89
+ }
90
+ function stringArray(value, path) {
91
+ if (!Array.isArray(value)) {
92
+ throw new Error(`${path} must be an array.`);
93
+ }
94
+ return value.map((entry, index) => {
95
+ if (typeof entry !== 'string' || entry.length === 0) {
96
+ throw new Error(`${path}[${index}] must be a non-empty string.`);
97
+ }
98
+ return entry;
99
+ });
100
+ }
101
+ function optionalStringArray(value, path) {
102
+ return value === undefined ? undefined : stringArray(value, path);
103
+ }
104
+ function pathPartsArray(value, path) {
105
+ if (!Array.isArray(value)) {
106
+ throw new Error(`${path} must be an array.`);
107
+ }
108
+ return value.map((entry, index) => stringArray(entry, `${path}[${index}]`));
109
+ }
110
+ function enumValue(value, allowed, path) {
111
+ if (typeof value !== 'string' || !allowed.has(value)) {
112
+ throw new Error(`${path} contains unsupported value ${JSON.stringify(value)}.`);
113
+ }
114
+ return value;
115
+ }
116
+ function requireVersion(value, expected, path) {
117
+ if (value !== expected) {
118
+ throw new Error(`${path} must be ${JSON.stringify(expected)}.`);
119
+ }
120
+ }
121
+ function validateActivationIdentityShape(value, path) {
122
+ const identity = exact(value, [
123
+ 'liftoffVersion',
124
+ 'manifestArtifactVersion',
125
+ 'policyVersion',
126
+ 'activationContractVersion',
127
+ 'phaseGraphSchemaVersion',
128
+ 'phaseGraphHash',
129
+ 'activationStateSchemaVersion',
130
+ 'evidenceHeaderSchemaVersion',
131
+ 'approvalEnvelopeSchemaVersion',
132
+ 'supersessionSchemaVersion',
133
+ 'credentialPolicySchemaVersion'
134
+ ], path);
135
+ requireVersion(identity.liftoffVersion, liftoffActivationPackageVersion, `${path}.liftoffVersion`);
136
+ requireVersion(identity.manifestArtifactVersion, liftoffManifestArtifactVersion, `${path}.manifestArtifactVersion`);
137
+ requireVersion(identity.policyVersion, governanceActivationPolicyVersion, `${path}.policyVersion`);
138
+ requireVersion(identity.activationContractVersion, activationContractVersion, `${path}.activationContractVersion`);
139
+ requireVersion(identity.phaseGraphSchemaVersion, phaseGraphSchemaVersion, `${path}.phaseGraphSchemaVersion`);
140
+ requireVersion(identity.activationStateSchemaVersion, activationStateSchemaVersion, `${path}.activationStateSchemaVersion`);
141
+ requireVersion(identity.evidenceHeaderSchemaVersion, evidenceHeaderSchemaVersion, `${path}.evidenceHeaderSchemaVersion`);
142
+ requireVersion(identity.approvalEnvelopeSchemaVersion, approvalEnvelopeSchemaVersion, `${path}.approvalEnvelopeSchemaVersion`);
143
+ requireVersion(identity.supersessionSchemaVersion, supersessionSchemaVersion, `${path}.supersessionSchemaVersion`);
144
+ requireVersion(identity.credentialPolicySchemaVersion, credentialPolicySchemaVersion, `${path}.credentialPolicySchemaVersion`);
145
+ const phaseGraphHash = stringField(identity, 'phaseGraphHash', path);
146
+ if (!hex64Pattern.test(phaseGraphHash)) {
147
+ throw new Error(`${path}.phaseGraphHash must be a SHA-256 hex digest.`);
148
+ }
149
+ return {
150
+ liftoffVersion: identity.liftoffVersion,
151
+ manifestArtifactVersion: identity.manifestArtifactVersion,
152
+ policyVersion: identity.policyVersion,
153
+ activationContractVersion: identity.activationContractVersion,
154
+ phaseGraphSchemaVersion: identity.phaseGraphSchemaVersion,
155
+ phaseGraphHash,
156
+ activationStateSchemaVersion: identity.activationStateSchemaVersion,
157
+ evidenceHeaderSchemaVersion: identity.evidenceHeaderSchemaVersion,
158
+ approvalEnvelopeSchemaVersion: identity.approvalEnvelopeSchemaVersion,
159
+ supersessionSchemaVersion: identity.supersessionSchemaVersion,
160
+ credentialPolicySchemaVersion: identity.credentialPolicySchemaVersion
161
+ };
162
+ }
163
+ export function validateActivationIdentity(value) {
164
+ if (isHistoricalActivationIdentity(value)) {
165
+ const historical = resolveActivationCompatibility(value, activationCompatibility);
166
+ if (!historical.compatible)
167
+ throw new Error(historical.reason);
168
+ }
169
+ const typed = validateActivationIdentityShape(value, 'identity');
170
+ const compatibility = resolveActivationCompatibility(typed, activationCompatibility);
171
+ if (!compatibility.compatible) {
172
+ throw new Error(compatibility.reason);
173
+ }
174
+ return typed;
175
+ }
176
+ /** Manifest readability is not execution compatibility; historical vectors are never retagged. */
177
+ export function validateReadableActivationIdentity(value) {
178
+ if (isHistoricalActivationIdentity(value))
179
+ return { ...value };
180
+ return validateActivationIdentity(value);
181
+ }
182
+ export function validateManifestActivationForExecution(manifest) {
183
+ const governance = manifest.governance;
184
+ if (governance.profile !== 'none' && governance.profile !== 'unspecified' && governance.activationIdentity !== undefined) {
185
+ validateActivationIdentity(governance.activationIdentity);
186
+ }
187
+ }
188
+ function hexDigest(value, path) {
189
+ if (typeof value !== 'string' || !hex64Pattern.test(value)) {
190
+ throw new Error(`${path} must be a SHA-256 hex digest.`);
191
+ }
192
+ return value;
193
+ }
194
+ function isoTimestamp(value, path) {
195
+ if (typeof value !== 'string' || !isoLikePattern.test(value) || Number.isNaN(Date.parse(value))) {
196
+ throw new Error(`${path} must be a valid ISO timestamp.`);
197
+ }
198
+ return value;
199
+ }
200
+ function dateDaysBetween(start, end) {
201
+ return (Date.parse(end) - Date.parse(start)) / (24 * 60 * 60 * 1000);
202
+ }
203
+ function addDaysIso(start, days) {
204
+ return new Date(Date.parse(start) + days * 24 * 60 * 60 * 1000).toISOString();
205
+ }
206
+ function exactStringSet(value, expected, path) {
207
+ const sortedValue = [...value].sort();
208
+ const sortedExpected = [...expected].sort();
209
+ if (sortedValue.length !== sortedExpected.length ||
210
+ sortedValue.some((entry, index) => entry !== sortedExpected[index])) {
211
+ throw new Error(`${path} must exactly equal ${expected.join(', ')}.`);
212
+ }
213
+ return expected;
214
+ }
215
+ function assertNoDuplicateStrings(value, path) {
216
+ const seen = new Set();
217
+ for (const entry of value) {
218
+ if (seen.has(entry)) {
219
+ throw new Error(`${path} contains duplicate value ${entry}.`);
220
+ }
221
+ seen.add(entry);
222
+ }
223
+ }
224
+ function validateCredentialRepositoryIdentity(value, path) {
225
+ const repository = exact(value, ['id', 'owner', 'name', 'fullName'], path);
226
+ const owner = stringField(repository, 'owner', path);
227
+ const name = stringField(repository, 'name', path);
228
+ const fullName = stringField(repository, 'fullName', path);
229
+ if (fullName !== `${owner}/${name}`) {
230
+ throw new Error(`${path}.fullName must equal owner/name.`);
231
+ }
232
+ return {
233
+ id: stringField(repository, 'id', path),
234
+ owner,
235
+ name,
236
+ fullName
237
+ };
238
+ }
239
+ function assertTimestampNotExpired(value, path, now) {
240
+ if (Date.parse(value) <= now.getTime()) {
241
+ throw new Error(`${path} must be in the future.`);
242
+ }
243
+ }
244
+ function validateEvidenceTransitionIdentity(value, path) {
245
+ const transition = exact(value, ['phaseId', 'baselineSha', 'inputDigest', 'transitionDigest'], path);
246
+ return {
247
+ phaseId: enumValue(transition.phaseId, phaseIdSet, `${path}.phaseId`),
248
+ baselineSha: hexDigest(transition.baselineSha, `${path}.baselineSha`),
249
+ inputDigest: hexDigest(transition.inputDigest, `${path}.inputDigest`),
250
+ transitionDigest: hexDigest(transition.transitionDigest, `${path}.transitionDigest`)
251
+ };
252
+ }
253
+ function validateDependency(value, path) {
254
+ const dependency = exact(value, ['anyOf', 'accepts', 'description'], path);
255
+ const anyOf = stringArray(dependency.anyOf, `${path}.anyOf`).map((id) => enumValue(id, phaseIdSet, `${path}.anyOf`));
256
+ if (anyOf.length === 0) {
257
+ throw new Error(`${path}.anyOf must not be empty.`);
258
+ }
259
+ const accepts = stringArray(dependency.accepts, `${path}.accepts`).map((state) => enumValue(state, terminalPhaseStateSet, `${path}.accepts`));
260
+ if (accepts.length === 0) {
261
+ throw new Error(`${path}.accepts must not be empty.`);
262
+ }
263
+ return { anyOf, accepts, description: stringField(dependency, 'description', path) };
264
+ }
265
+ function validateApplicability(value, path) {
266
+ const base = record(value, path);
267
+ if (base.kind === 'always') {
268
+ exact(value, ['kind'], path);
269
+ return { kind: 'always' };
270
+ }
271
+ const applicability = exact(value, [
272
+ 'kind',
273
+ 'discriminator',
274
+ 'when',
275
+ 'inapplicableWhen',
276
+ 'exclusiveWith'
277
+ ], path);
278
+ enumValue(applicability.kind, new Set(['conditional']), `${path}.kind`);
279
+ const discriminator = enumValue(applicability.discriminator, new Set(['state-path', 'private-staging-dast', 'credential-required']), `${path}.discriminator`);
280
+ const exclusiveWith = stringArray(applicability.exclusiveWith, `${path}.exclusiveWith`).map((id) => enumValue(id, phaseIdSet, `${path}.exclusiveWith`));
281
+ return {
282
+ kind: 'conditional',
283
+ discriminator,
284
+ when: stringField(applicability, 'when', path),
285
+ inapplicableWhen: stringField(applicability, 'inapplicableWhen', path),
286
+ exclusiveWith
287
+ };
288
+ }
289
+ function validateMutations(value, path) {
290
+ const mutations = exact(value, ['local', 'remote'], path);
291
+ const mutationSet = new Set(mutationClasses);
292
+ const local = stringArray(mutations.local, `${path}.local`).map((entry) => enumValue(entry, mutationSet, `${path}.local`));
293
+ const remote = stringArray(mutations.remote, `${path}.remote`).map((entry) => enumValue(entry, mutationSet, `${path}.remote`));
294
+ for (const [label, entries] of [['local', local], ['remote', remote]]) {
295
+ if (entries.length === 0) {
296
+ throw new Error(`${path}.${label} must not be empty.`);
297
+ }
298
+ if (entries.includes('none') && entries.length > 1) {
299
+ throw new Error(`${path}.${label} cannot combine none with other mutations.`);
300
+ }
301
+ }
302
+ return { local, remote };
303
+ }
304
+ function validateNode(value, path) {
305
+ const node = exact(value, [
306
+ 'id',
307
+ 'label',
308
+ 'dependencies',
309
+ 'applicability',
310
+ 'allowedMutations',
311
+ 'evidence',
312
+ 'approvalGate',
313
+ 'invalidationInputs',
314
+ 'rollback',
315
+ 'terminalStates'
316
+ ], path);
317
+ const id = enumValue(node.id, phaseIdSet, `${path}.id`);
318
+ const label = stringField(node, 'label', path);
319
+ if (!Array.isArray(node.dependencies)) {
320
+ throw new Error(`${path}.dependencies must be an array.`);
321
+ }
322
+ const dependencies = node.dependencies.map((dependency, index) => validateDependency(dependency, `${path}.dependencies[${index}]`));
323
+ const applicability = validateApplicability(node.applicability, `${path}.applicability`);
324
+ const allowedMutations = validateMutations(node.allowedMutations, `${path}.allowedMutations`);
325
+ const evidence = exact(node.evidence, ['schema', 'required', 'headerSchemaVersion', 'liveReadbackProviders'], `${path}.evidence`);
326
+ requireVersion(evidence.headerSchemaVersion, evidenceHeaderSchemaVersion, `${path}.evidence.headerSchemaVersion`);
327
+ const liveReadbackProviders = stringArray(evidence.liveReadbackProviders, `${path}.evidence.liveReadbackProviders`).map((provider) => enumValue(provider, liveReadbackProviderSet, `${path}.evidence.liveReadbackProviders`));
328
+ if (new Set(liveReadbackProviders).size !== liveReadbackProviders.length) {
329
+ throw new Error(`${path}.evidence.liveReadbackProviders must not contain duplicates.`);
330
+ }
331
+ const approvalGate = exact(node.approvalGate, ['kind', 'required', 'envelopeSchemaVersion'], `${path}.approvalGate`);
332
+ const approvalKind = enumValue(approvalGate.kind, new Set(approvalGateKinds), `${path}.approvalGate.kind`);
333
+ requireVersion(approvalGate.envelopeSchemaVersion, approvalEnvelopeSchemaVersion, `${path}.approvalGate.envelopeSchemaVersion`);
334
+ const invalidationSet = new Set(invalidationInputKinds);
335
+ const invalidationInputs = stringArray(node.invalidationInputs, `${path}.invalidationInputs`).map((entry) => enumValue(entry, invalidationSet, `${path}.invalidationInputs`));
336
+ const rollback = exact(node.rollback, ['kind', 'target', 'description'], `${path}.rollback`);
337
+ const rollbackKind = enumValue(rollback.kind, new Set(rollbackKinds), `${path}.rollback.kind`);
338
+ const target = rollback.target === null
339
+ ? null
340
+ : enumValue(rollback.target, phaseIdSet, `${path}.rollback.target`);
341
+ const terminalStates = stringArray(node.terminalStates, `${path}.terminalStates`).map((state) => enumValue(state, terminalPhaseStateSet, `${path}.terminalStates`));
342
+ if (terminalStates.length === 0) {
343
+ throw new Error(`${path}.terminalStates must not be empty.`);
344
+ }
345
+ return {
346
+ id,
347
+ label,
348
+ dependencies,
349
+ applicability,
350
+ allowedMutations,
351
+ evidence: {
352
+ schema: stringField(evidence, 'schema', `${path}.evidence`),
353
+ required: booleanField(evidence, 'required', `${path}.evidence`),
354
+ headerSchemaVersion: evidenceHeaderSchemaVersion,
355
+ liveReadbackProviders
356
+ },
357
+ approvalGate: {
358
+ kind: approvalKind,
359
+ required: booleanField(approvalGate, 'required', `${path}.approvalGate`),
360
+ envelopeSchemaVersion: approvalEnvelopeSchemaVersion
361
+ },
362
+ invalidationInputs,
363
+ rollback: {
364
+ kind: rollbackKind,
365
+ target,
366
+ description: stringField(rollback, 'description', `${path}.rollback`)
367
+ },
368
+ terminalStates
369
+ };
370
+ }
371
+ function hasDependency(node, phaseId) {
372
+ return node.dependencies.some((dependency) => dependency.anyOf.includes(phaseId));
373
+ }
374
+ function assertReachableToFinal(nodes) {
375
+ const adjacency = new Map();
376
+ for (const id of phaseIds) {
377
+ adjacency.set(id, []);
378
+ }
379
+ for (const node of nodes) {
380
+ for (const dependency of node.dependencies) {
381
+ for (const parent of dependency.anyOf) {
382
+ adjacency.get(parent)?.push(node.id);
383
+ }
384
+ }
385
+ }
386
+ for (const start of phaseIds) {
387
+ if (start === 'bootstrap-state-disposed') {
388
+ continue;
389
+ }
390
+ let reachesFinal = false;
391
+ const seen = new Set();
392
+ const stack = [start];
393
+ while (stack.length > 0) {
394
+ const id = stack.pop();
395
+ if (id === 'bootstrap-state-disposed') {
396
+ reachesFinal = true;
397
+ break;
398
+ }
399
+ if (seen.has(id)) {
400
+ continue;
401
+ }
402
+ seen.add(id);
403
+ stack.push(...(adjacency.get(id) ?? []));
404
+ }
405
+ if (!reachesFinal) {
406
+ throw new Error(`${start} cannot reach terminal bootstrap-state-disposed.`);
407
+ }
408
+ }
409
+ }
410
+ export function validateManagedPhaseGraph(value) {
411
+ const graph = exact(value, ['schemaVersion', 'versions', 'phases'], 'phaseGraph');
412
+ requireVersion(graph.schemaVersion, phaseGraphSchemaVersion, 'phaseGraph.schemaVersion');
413
+ const versions = exact(graph.versions, [
414
+ 'liftoffVersion',
415
+ 'policyVersion',
416
+ 'activationContractVersion',
417
+ 'phaseGraphSchemaVersion'
418
+ ], 'phaseGraph.versions');
419
+ requireVersion(versions.liftoffVersion, liftoffActivationPackageVersion, 'phaseGraph.versions.liftoffVersion');
420
+ requireVersion(versions.policyVersion, governanceActivationPolicyVersion, 'phaseGraph.versions.policyVersion');
421
+ requireVersion(versions.activationContractVersion, activationContractVersion, 'phaseGraph.versions.activationContractVersion');
422
+ requireVersion(versions.phaseGraphSchemaVersion, phaseGraphSchemaVersion, 'phaseGraph.versions.phaseGraphSchemaVersion');
423
+ if (!Array.isArray(graph.phases)) {
424
+ throw new Error('phaseGraph.phases must be an array.');
425
+ }
426
+ const nodes = graph.phases.map((node, index) => validateNode(node, `phaseGraph.phases[${index}]`));
427
+ if (nodes.length !== phaseIds.length) {
428
+ throw new Error('phaseGraph must declare every canonical phase exactly once.');
429
+ }
430
+ const seen = new Set();
431
+ for (const [index, node] of nodes.entries()) {
432
+ if (seen.has(node.id)) {
433
+ throw new Error(`Duplicate phase id ${node.id}.`);
434
+ }
435
+ seen.add(node.id);
436
+ if (node.id !== phaseIds[index]) {
437
+ throw new Error(`Phase ${node.id} is not in canonical order at index ${index}.`);
438
+ }
439
+ for (const dependency of node.dependencies) {
440
+ for (const dependencyId of dependency.anyOf) {
441
+ const dependencyIndex = phaseIds.indexOf(dependencyId);
442
+ if (dependencyIndex >= index) {
443
+ throw new Error(`Reversed dependency order: ${node.id} depends on ${dependencyId}.`);
444
+ }
445
+ }
446
+ }
447
+ if (node.rollback.target !== null && phaseIds.indexOf(node.rollback.target) >= index) {
448
+ throw new Error(`Rollback target for ${node.id} must be an earlier phase.`);
449
+ }
450
+ if (node.approvalGate.required && node.approvalGate.kind === 'none') {
451
+ throw new Error(`${node.id} cannot require approval gate none.`);
452
+ }
453
+ if (!node.approvalGate.required && node.approvalGate.kind !== 'none') {
454
+ throw new Error(`${node.id} has a non-none optional approval gate.`);
455
+ }
456
+ const requiredLiveReadbackProviders = [
457
+ ...(node.allowedMutations.remote.some((mutation) => githubRemoteWriteMutations.has(mutation)) ? ['github'] : []),
458
+ ...(node.allowedMutations.remote.some((mutation) => azureRemoteWriteMutations.has(mutation)) ? ['azure'] : [])
459
+ ];
460
+ for (const provider of requiredLiveReadbackProviders) {
461
+ if (!node.evidence.liveReadbackProviders.includes(provider)) {
462
+ throw new Error(`${node.id} must declare ${provider} live readback proof for remote mutation evidence.`);
463
+ }
464
+ }
465
+ if (node.applicability.kind === 'conditional') {
466
+ for (const exclusiveId of node.applicability.exclusiveWith) {
467
+ const other = nodes.find((candidate) => candidate.id === exclusiveId);
468
+ if (!other || other.applicability.kind !== 'conditional') {
469
+ throw new Error(`${node.id} exclusive phase ${exclusiveId} must be conditional.`);
470
+ }
471
+ }
472
+ if (!node.terminalStates.includes('inapplicable')) {
473
+ throw new Error(`${node.id} conditional phase must permit inapplicable terminal state.`);
474
+ }
475
+ }
476
+ }
477
+ for (const id of phaseIds) {
478
+ if (!seen.has(id)) {
479
+ throw new Error(`Missing canonical phase ${id}.`);
480
+ }
481
+ }
482
+ const byId = Object.fromEntries(nodes.map((node) => [node.id, node]));
483
+ if (!hasDependency(byId['bootstrap-local'], 'provider-ready')) {
484
+ throw new Error('bootstrap-local must depend on provider-ready.');
485
+ }
486
+ if (!hasDependency(byId['private-backend-proof'], 'runner-ready')) {
487
+ throw new Error('private-backend-proof must depend on runner-ready.');
488
+ }
489
+ if (!hasDependency(byId['remote-import-verified'], 'private-backend-proof')) {
490
+ throw new Error('remote-import-verified must depend on private-backend-proof.');
491
+ }
492
+ if (!hasDependency(byId['remote-ready'], 'remote-import-verified')) {
493
+ throw new Error('remote-ready must depend on remote-import-verified.');
494
+ }
495
+ const visiting = new Set();
496
+ const visited = new Set();
497
+ const visit = (id) => {
498
+ if (visiting.has(id)) {
499
+ throw new Error(`Cycle detected at ${id}.`);
500
+ }
501
+ if (visited.has(id)) {
502
+ return;
503
+ }
504
+ visiting.add(id);
505
+ for (const dependency of byId[id].dependencies) {
506
+ for (const dependencyId of dependency.anyOf) {
507
+ visit(dependencyId);
508
+ }
509
+ }
510
+ visiting.delete(id);
511
+ visited.add(id);
512
+ };
513
+ for (const id of phaseIds) {
514
+ visit(id);
515
+ }
516
+ assertReachableToFinal(nodes);
517
+ return {
518
+ schemaVersion: phaseGraphSchemaVersion,
519
+ versions: {
520
+ liftoffVersion: liftoffActivationPackageVersion,
521
+ policyVersion: governanceActivationPolicyVersion,
522
+ activationContractVersion,
523
+ phaseGraphSchemaVersion
524
+ },
525
+ phases: nodes
526
+ };
527
+ }
528
+ export function assertCanonicalGraphValid() {
529
+ validateManagedPhaseGraph(canonicalPhaseGraph);
530
+ }
531
+ function validateEvidenceReference(value, path) {
532
+ const reference = exact(value, ['phaseId', 'evidenceId', 'headerDigest', 'result'], path);
533
+ const phaseId = enumValue(reference.phaseId, phaseIdSet, `${path}.phaseId`);
534
+ const result = enumValue(reference.result, resultStateSet, `${path}.result`);
535
+ const headerDigest = stringField(reference, 'headerDigest', path);
536
+ if (!hex64Pattern.test(headerDigest)) {
537
+ throw new Error(`${path}.headerDigest must be a SHA-256 hex digest.`);
538
+ }
539
+ return {
540
+ phaseId,
541
+ evidenceId: stringField(reference, 'evidenceId', path),
542
+ headerDigest,
543
+ result
544
+ };
545
+ }
546
+ export function validateUserActivationState(value) {
547
+ const state = exactWithOptional(value, [
548
+ 'schemaVersion',
549
+ 'identity',
550
+ 'repository',
551
+ 'activeChange',
552
+ 'applicability',
553
+ 'phases',
554
+ 'createdAt',
555
+ 'updatedAt'
556
+ ], ['bootstrapState', 'remoteBinding'], 'activationState');
557
+ requireVersion(state.schemaVersion, activationStateSchemaVersion, 'activationState.schemaVersion');
558
+ const identity = validateActivationIdentity(state.identity);
559
+ if (identity.phaseGraphHash !== canonicalPhaseGraphHash) {
560
+ throw new Error('activationState.identity.phaseGraphHash does not match canonical graph.');
561
+ }
562
+ const repository = exact(state.repository, ['id', 'name', 'defaultBranch'], 'activationState.repository');
563
+ if (repository.id === 'unbound')
564
+ throw new Error('Persisted activation state must have an explicitly established immutable local execution anchor.');
565
+ let remoteBinding;
566
+ if (state.remoteBinding !== undefined) {
567
+ const binding = exact(state.remoteBinding, ['id', 'name', 'defaultBranch', 'pushUrl', 'verifiedAt'], 'activationState.remoteBinding');
568
+ remoteBinding = {
569
+ id: stringField(binding, 'id', 'activationState.remoteBinding'),
570
+ name: stringField(binding, 'name', 'activationState.remoteBinding'),
571
+ defaultBranch: stringField(binding, 'defaultBranch', 'activationState.remoteBinding'),
572
+ pushUrl: stringField(binding, 'pushUrl', 'activationState.remoteBinding'),
573
+ verifiedAt: isoTimestamp(binding.verifiedAt, 'activationState.remoteBinding.verifiedAt')
574
+ };
575
+ const remote = /^(?:https:\/\/github\.com\/|git@github\.com:)([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?\/?$/.exec(remoteBinding.pushUrl);
576
+ if (!remote || remote[1].toLowerCase() !== remoteBinding.name.toLowerCase()) {
577
+ throw new Error('activationState.remoteBinding must match one credential-free GitHub push destination.');
578
+ }
579
+ }
580
+ let activeChange = null;
581
+ if (state.activeChange !== null) {
582
+ const change = exact(state.activeChange, ['id', 'kind'], 'activationState.activeChange');
583
+ activeChange = {
584
+ id: stringField(change, 'id', 'activationState.activeChange'),
585
+ kind: enumValue(change.kind, new Set(['openspec', 'spec-kit']), 'activationState.activeChange.kind')
586
+ };
587
+ }
588
+ const applicability = exact(state.applicability, [
589
+ 'statePath',
590
+ 'privateStagingDast',
591
+ 'credentialRequired'
592
+ ], 'activationState.applicability');
593
+ const phases = record(state.phases, 'activationState.phases');
594
+ const phaseStatesById = {};
595
+ for (const id of phaseIds) {
596
+ if (!Object.hasOwn(phases, id)) {
597
+ throw new Error(`activationState.phases.${id} is required.`);
598
+ }
599
+ const phase = exact(phases[id], ['state', 'updatedAt', 'evidence', 'approvals', 'blockers'], `activationState.phases.${id}`);
600
+ const phaseState = enumValue(phase.state, new Set(phaseStates), `activationState.phases.${id}.state`);
601
+ if (!Array.isArray(phase.evidence) || !Array.isArray(phase.approvals) || !Array.isArray(phase.blockers)) {
602
+ throw new Error(`activationState.phases.${id} evidence, approvals, and blockers must be arrays.`);
603
+ }
604
+ phaseStatesById[id] = {
605
+ state: phaseState,
606
+ updatedAt: stringField(phase, 'updatedAt', `activationState.phases.${id}`),
607
+ evidence: phase.evidence.map((entry, index) => validateEvidenceReference(entry, `activationState.phases.${id}.evidence[${index}]`)),
608
+ approvals: stringArray(phase.approvals, `activationState.phases.${id}.approvals`),
609
+ blockers: stringArray(phase.blockers, `activationState.phases.${id}.blockers`)
610
+ };
611
+ }
612
+ for (const key of Object.keys(phases)) {
613
+ if (!phaseIdSet.has(key)) {
614
+ throw new Error(`activationState.phases.${key} is not a canonical phase.`);
615
+ }
616
+ }
617
+ let bootstrapState;
618
+ if (state.bootstrapState !== undefined) {
619
+ const retention = exactWithOptional(state.bootstrapState, [
620
+ 'status',
621
+ 'remoteImportEvidenceId',
622
+ 'remoteImportEvidenceDigest',
623
+ 'retainedAt',
624
+ 'disposeAfter',
625
+ 'encryptedStatePathParts',
626
+ 'encryptionKeyPathParts'
627
+ ], ['disposedAt', 'deletionEvidenceId', 'incompleteCleanup'], 'activationState.bootstrapState');
628
+ const retainedAt = isoTimestamp(retention.retainedAt, 'activationState.bootstrapState.retainedAt');
629
+ const disposeAfter = isoTimestamp(retention.disposeAfter, 'activationState.bootstrapState.disposeAfter');
630
+ if (Date.parse(disposeAfter) - Date.parse(retainedAt) !== 30 * 24 * 60 * 60 * 1000) {
631
+ throw new Error('activationState.bootstrapState.disposeAfter must be exactly 30 days after retainedAt.');
632
+ }
633
+ const status = enumValue(retention.status, new Set(['retained', 'disposed']), 'activationState.bootstrapState.status');
634
+ if (status === 'disposed' && retention.disposedAt === undefined) {
635
+ throw new Error('activationState.bootstrapState.disposedAt is required when status is disposed.');
636
+ }
637
+ bootstrapState = {
638
+ status,
639
+ remoteImportEvidenceId: stringField(retention, 'remoteImportEvidenceId', 'activationState.bootstrapState'),
640
+ remoteImportEvidenceDigest: hexDigest(retention.remoteImportEvidenceDigest, 'activationState.bootstrapState.remoteImportEvidenceDigest'),
641
+ retainedAt,
642
+ disposeAfter,
643
+ encryptedStatePathParts: pathPartsArray(retention.encryptedStatePathParts, 'activationState.bootstrapState.encryptedStatePathParts'),
644
+ encryptionKeyPathParts: pathPartsArray(retention.encryptionKeyPathParts, 'activationState.bootstrapState.encryptionKeyPathParts'),
645
+ ...(retention.disposedAt !== undefined ? { disposedAt: isoTimestamp(retention.disposedAt, 'activationState.bootstrapState.disposedAt') } : {}),
646
+ ...(retention.deletionEvidenceId !== undefined ? { deletionEvidenceId: stringField(retention, 'deletionEvidenceId', 'activationState.bootstrapState') } : {}),
647
+ ...(retention.incompleteCleanup !== undefined ? { incompleteCleanup: stringArray(retention.incompleteCleanup, 'activationState.bootstrapState.incompleteCleanup') } : {})
648
+ };
649
+ }
650
+ return {
651
+ schemaVersion: activationStateSchemaVersion,
652
+ identity,
653
+ repository: {
654
+ id: stringField(repository, 'id', 'activationState.repository'),
655
+ name: stringField(repository, 'name', 'activationState.repository'),
656
+ defaultBranch: stringField(repository, 'defaultBranch', 'activationState.repository')
657
+ },
658
+ activeChange,
659
+ applicability: {
660
+ statePath: enumValue(applicability.statePath, new Set(['existing-private', 'bootstrap-local', 'none']), 'activationState.applicability.statePath'),
661
+ privateStagingDast: applicability.privateStagingDast === 'unknown' ? 'unknown' : booleanField(applicability, 'privateStagingDast', 'activationState.applicability'),
662
+ credentialRequired: applicability.credentialRequired === 'unknown' ? 'unknown' : booleanField(applicability, 'credentialRequired', 'activationState.applicability')
663
+ },
664
+ ...(remoteBinding ? { remoteBinding } : {}),
665
+ ...(bootstrapState ? { bootstrapState } : {}),
666
+ phases: phaseStatesById,
667
+ createdAt: stringField(state, 'createdAt', 'activationState'),
668
+ updatedAt: stringField(state, 'updatedAt', 'activationState')
669
+ };
670
+ }
671
+ export function validateEvidenceHeader(value) {
672
+ const header = exactWithOptional(value, [
673
+ 'schemaVersion',
674
+ 'repositoryId',
675
+ 'identity',
676
+ 'phaseGraphHash',
677
+ 'phaseId',
678
+ 'phaseContractDigest',
679
+ 'inputDigest',
680
+ 'baselineSha',
681
+ 'transition',
682
+ 'producedAt',
683
+ 'producer',
684
+ 'bodyDigest',
685
+ 'result'
686
+ ], ['remoteBindingDigest'], 'evidenceHeader');
687
+ requireVersion(header.schemaVersion, evidenceHeaderSchemaVersion, 'evidenceHeader.schemaVersion');
688
+ const identity = validateActivationIdentity(header.identity);
689
+ const phaseGraphHash = hexDigest(header.phaseGraphHash, 'evidenceHeader.phaseGraphHash');
690
+ if (phaseGraphHash !== identity.phaseGraphHash) {
691
+ throw new Error('evidenceHeader.phaseGraphHash must match evidenceHeader.identity.phaseGraphHash.');
692
+ }
693
+ const phaseId = enumValue(header.phaseId, phaseIdSet, 'evidenceHeader.phaseId');
694
+ const phaseContractDigest = hexDigest(header.phaseContractDigest, 'evidenceHeader.phaseContractDigest');
695
+ const inputDigest = hexDigest(header.inputDigest, 'evidenceHeader.inputDigest');
696
+ const baselineSha = hexDigest(header.baselineSha, 'evidenceHeader.baselineSha');
697
+ const transition = validateEvidenceTransitionIdentity(header.transition, 'evidenceHeader.transition');
698
+ if (transition.phaseId !== phaseId) {
699
+ throw new Error('evidenceHeader.transition.phaseId must match evidenceHeader.phaseId.');
700
+ }
701
+ if (transition.baselineSha !== baselineSha) {
702
+ throw new Error('evidenceHeader.transition.baselineSha must match evidenceHeader.baselineSha.');
703
+ }
704
+ if (transition.inputDigest !== inputDigest) {
705
+ throw new Error('evidenceHeader.transition.inputDigest must match evidenceHeader.inputDigest.');
706
+ }
707
+ return {
708
+ schemaVersion: evidenceHeaderSchemaVersion,
709
+ repositoryId: stringField(header, 'repositoryId', 'evidenceHeader'),
710
+ identity,
711
+ phaseGraphHash,
712
+ phaseId,
713
+ phaseContractDigest,
714
+ inputDigest,
715
+ baselineSha,
716
+ transition,
717
+ producedAt: isoTimestamp(header.producedAt, 'evidenceHeader.producedAt'),
718
+ producer: stringField(header, 'producer', 'evidenceHeader'),
719
+ bodyDigest: hexDigest(header.bodyDigest, 'evidenceHeader.bodyDigest'),
720
+ ...(header.remoteBindingDigest !== undefined ? {
721
+ remoteBindingDigest: hexDigest(header.remoteBindingDigest, 'evidenceHeader.remoteBindingDigest')
722
+ } : {}),
723
+ result: enumValue(header.result, resultStateSet, 'evidenceHeader.result')
724
+ };
725
+ }
726
+ export function validateLiveReadbackProof(value) {
727
+ const proof = exact(value, [
728
+ 'schemaVersion',
729
+ 'repositoryId',
730
+ 'identity',
731
+ 'phaseGraphHash',
732
+ 'phaseId',
733
+ 'baselineSha',
734
+ 'inputDigest',
735
+ 'transition',
736
+ 'observedAt',
737
+ 'provider',
738
+ 'resourceType',
739
+ 'resourceId',
740
+ 'sourceDigest',
741
+ 'readbackDigest',
742
+ 'matches'
743
+ ], 'liveReadbackProof');
744
+ requireVersion(proof.schemaVersion, evidenceHeaderSchemaVersion, 'liveReadbackProof.schemaVersion');
745
+ const identity = validateActivationIdentity(proof.identity);
746
+ const phaseGraphHash = hexDigest(proof.phaseGraphHash, 'liveReadbackProof.phaseGraphHash');
747
+ if (phaseGraphHash !== identity.phaseGraphHash) {
748
+ throw new Error('liveReadbackProof.phaseGraphHash must match liveReadbackProof.identity.phaseGraphHash.');
749
+ }
750
+ const phaseId = enumValue(proof.phaseId, phaseIdSet, 'liveReadbackProof.phaseId');
751
+ const baselineSha = hexDigest(proof.baselineSha, 'liveReadbackProof.baselineSha');
752
+ const inputDigest = hexDigest(proof.inputDigest, 'liveReadbackProof.inputDigest');
753
+ const transition = validateEvidenceTransitionIdentity(proof.transition, 'liveReadbackProof.transition');
754
+ if (transition.phaseId !== phaseId) {
755
+ throw new Error('liveReadbackProof.transition.phaseId must match liveReadbackProof.phaseId.');
756
+ }
757
+ if (transition.baselineSha !== baselineSha) {
758
+ throw new Error('liveReadbackProof.transition.baselineSha must match liveReadbackProof.baselineSha.');
759
+ }
760
+ if (transition.inputDigest !== inputDigest) {
761
+ throw new Error('liveReadbackProof.transition.inputDigest must match liveReadbackProof.inputDigest.');
762
+ }
763
+ return {
764
+ schemaVersion: evidenceHeaderSchemaVersion,
765
+ repositoryId: stringField(proof, 'repositoryId', 'liveReadbackProof'),
766
+ identity,
767
+ phaseGraphHash,
768
+ phaseId,
769
+ baselineSha,
770
+ inputDigest,
771
+ transition,
772
+ observedAt: isoTimestamp(proof.observedAt, 'liveReadbackProof.observedAt'),
773
+ provider: enumValue(proof.provider, new Set(['github', 'azure']), 'liveReadbackProof.provider'),
774
+ resourceType: stringField(proof, 'resourceType', 'liveReadbackProof'),
775
+ resourceId: stringField(proof, 'resourceId', 'liveReadbackProof'),
776
+ sourceDigest: hexDigest(proof.sourceDigest, 'liveReadbackProof.sourceDigest'),
777
+ readbackDigest: hexDigest(proof.readbackDigest, 'liveReadbackProof.readbackDigest'),
778
+ matches: booleanField(proof, 'matches', 'liveReadbackProof')
779
+ };
780
+ }
781
+ function validateApprovalResource(value, path) {
782
+ const resource = exact(value, ['type', 'identity'], path);
783
+ return {
784
+ type: stringField(resource, 'type', path),
785
+ identity: stringField(resource, 'identity', path)
786
+ };
787
+ }
788
+ function validateApprovalDestination(value, path) {
789
+ const destination = exact(value, ['type', 'identity', 'repository', 'subscriptionId'], path);
790
+ return {
791
+ type: enumValue(destination.type, new Set(['repository', 'subscription', 'environment', 'tenant', 'local', 'external']), `${path}.type`),
792
+ identity: stringField(destination, 'identity', path),
793
+ repository: destination.repository === null ? null : stringField(destination, 'repository', path),
794
+ subscriptionId: destination.subscriptionId === null ? null : stringField(destination, 'subscriptionId', path)
795
+ };
796
+ }
797
+ function identityMatches(left, right) {
798
+ return JSON.stringify(left) === JSON.stringify(right);
799
+ }
800
+ export function validateApprovalEnvelope(value, options = {}) {
801
+ const envelope = exact(value, [
802
+ 'schemaVersion',
803
+ 'id',
804
+ 'phaseId',
805
+ 'gateKind',
806
+ 'identity',
807
+ 'baselineSha',
808
+ 'planDigest',
809
+ 'resources',
810
+ 'destinations',
811
+ 'permissions',
812
+ 'costCeiling',
813
+ 'policyExceptions',
814
+ 'destructiveScope',
815
+ 'expiresAt',
816
+ 'approvedAt',
817
+ 'approver'
818
+ ], 'approvalEnvelope');
819
+ requireVersion(envelope.schemaVersion, approvalEnvelopeSchemaVersion, 'approvalEnvelope.schemaVersion');
820
+ const cost = exact(envelope.costCeiling, [
821
+ 'currency',
822
+ 'fixedMonthlyCents',
823
+ 'usageMonthlyCents'
824
+ ], 'approvalEnvelope.costCeiling');
825
+ const baselineSha = stringField(envelope, 'baselineSha', 'approvalEnvelope');
826
+ const planDigest = stringField(envelope, 'planDigest', 'approvalEnvelope');
827
+ if (!hex64Pattern.test(baselineSha) || !hex64Pattern.test(planDigest)) {
828
+ throw new Error('approvalEnvelope baselineSha and planDigest must be SHA-256 hex digests.');
829
+ }
830
+ const identity = validateActivationIdentity(envelope.identity);
831
+ if (options.expectedIdentity && !identityMatches(identity, options.expectedIdentity)) {
832
+ throw new Error('approvalEnvelope.identity does not match the active activation identity.');
833
+ }
834
+ const expiresAt = isoTimestamp(envelope.expiresAt, 'approvalEnvelope.expiresAt');
835
+ const approvedAt = isoTimestamp(envelope.approvedAt, 'approvalEnvelope.approvedAt');
836
+ if (Date.parse(approvedAt) >= Date.parse(expiresAt))
837
+ throw new Error('Approval requires approvedAt < expiresAt.');
838
+ if (options.requireUnexpired) {
839
+ assertTimestampNotExpired(expiresAt, 'approvalEnvelope.expiresAt', options.now ?? new Date());
840
+ if (Date.parse(approvedAt) > (options.now ?? new Date()).getTime())
841
+ throw new Error('Approval approvedAt is in the future.');
842
+ }
843
+ const resources = Array.isArray(envelope.resources)
844
+ ? normalizeApprovalResources(envelope.resources.map((entry, index) => validateApprovalResource(entry, `approvalEnvelope.resources[${index}]`)))
845
+ : (() => { throw new Error('approvalEnvelope.resources must be an array.'); })();
846
+ const destinations = Array.isArray(envelope.destinations)
847
+ ? normalizeApprovalDestinations(envelope.destinations.map((entry, index) => validateApprovalDestination(entry, `approvalEnvelope.destinations[${index}]`)))
848
+ : (() => { throw new Error('approvalEnvelope.destinations must be an array.'); })();
849
+ const permissions = normalizeApprovalPermissions(stringArray(envelope.permissions, 'approvalEnvelope.permissions'));
850
+ const policyExceptions = normalizeApprovalPolicyExceptions(stringArray(envelope.policyExceptions, 'approvalEnvelope.policyExceptions'));
851
+ const destructiveScope = normalizeApprovalDestructiveScope(stringArray(envelope.destructiveScope, 'approvalEnvelope.destructiveScope'));
852
+ const costCeiling = normalizeApprovalCostCeiling({
853
+ currency: stringField(cost, 'currency', 'approvalEnvelope.costCeiling'),
854
+ fixedMonthlyCents: integerField(cost, 'fixedMonthlyCents', 'approvalEnvelope.costCeiling'),
855
+ usageMonthlyCents: integerField(cost, 'usageMonthlyCents', 'approvalEnvelope.costCeiling')
856
+ });
857
+ const phaseId = enumValue(envelope.phaseId, phaseIdSet, 'approvalEnvelope.phaseId');
858
+ const gateKind = enumValue(envelope.gateKind, new Set(approvalGateKinds), 'approvalEnvelope.gateKind');
859
+ const expectedGateKind = canonicalPhaseGraph.phases.find((phase) => phase.id === phaseId)?.approvalGate.kind;
860
+ if (expectedGateKind !== gateKind) {
861
+ throw new Error(`approvalEnvelope.gateKind ${gateKind} does not match phase ${phaseId} gate ${expectedGateKind}.`);
862
+ }
863
+ return {
864
+ schemaVersion: approvalEnvelopeSchemaVersion,
865
+ id: stringField(envelope, 'id', 'approvalEnvelope'),
866
+ phaseId,
867
+ gateKind,
868
+ identity,
869
+ baselineSha,
870
+ planDigest,
871
+ resources,
872
+ destinations,
873
+ permissions,
874
+ costCeiling,
875
+ policyExceptions,
876
+ destructiveScope,
877
+ expiresAt,
878
+ approvedAt,
879
+ approver: stringField(envelope, 'approver', 'approvalEnvelope')
880
+ };
881
+ }
882
+ function validateOperationDestination(value, path) {
883
+ const destination = exactWithOptional(value, ['type', 'identity'], ['pathParts', 'repository', 'subscriptionId', 'ref'], path);
884
+ const normalized = {
885
+ type: enumValue(destination.type, new Set(['local', 'repository', 'subscription', 'environment', 'tenant', 'external']), `${path}.type`),
886
+ identity: stringField(destination, 'identity', path),
887
+ ...(destination.pathParts !== undefined ? { pathParts: stringArray(destination.pathParts, `${path}.pathParts`) } : {}),
888
+ ...(destination.repository !== undefined ? { repository: stringField(destination, 'repository', path) } : {}),
889
+ ...(destination.subscriptionId !== undefined ? { subscriptionId: stringField(destination, 'subscriptionId', path) } : {}),
890
+ ...(destination.ref !== undefined ? { ref: stringField(destination, 'ref', path) } : {})
891
+ };
892
+ return normalized;
893
+ }
894
+ function validateTransitionOperation(value, path) {
895
+ const operation = exact(value, [
896
+ 'adapter',
897
+ 'actionId',
898
+ 'mutationClass',
899
+ 'phaseId',
900
+ 'inputs',
901
+ 'destination',
902
+ 'remote',
903
+ 'destructive'
904
+ ], path);
905
+ return {
906
+ adapter: enumValue(operation.adapter, transitionAdapterIds, `${path}.adapter`),
907
+ actionId: stringField(operation, 'actionId', path),
908
+ mutationClass: enumValue(operation.mutationClass, new Set(mutationClasses), `${path}.mutationClass`),
909
+ phaseId: enumValue(operation.phaseId, phaseIdSet, `${path}.phaseId`),
910
+ inputs: record(operation.inputs, `${path}.inputs`),
911
+ destination: validateOperationDestination(operation.destination, `${path}.destination`),
912
+ remote: booleanField(operation, 'remote', path),
913
+ destructive: booleanField(operation, 'destructive', path)
914
+ };
915
+ }
916
+ function validateApprovalEvaluation(value, path) {
917
+ const evaluation = exact(value, [
918
+ 'phaseId',
919
+ 'gateKind',
920
+ 'questionKind',
921
+ 'approvalRequired',
922
+ 'status',
923
+ 'envelopeId',
924
+ 'envelopeHash',
925
+ 'reasons',
926
+ 'expansionReasons'
927
+ ], path);
928
+ const question = evaluation.questionKind === null
929
+ ? null
930
+ : enumValue(evaluation.questionKind, new Set([
931
+ 'repository-creation-initial-commit-push',
932
+ 'credential-enrollment',
933
+ 'billed-infrastructure-policy-exception-cost-ceiling',
934
+ 'final-enforcement',
935
+ 'destructive-operation',
936
+ 'external-blocker'
937
+ ]), `${path}.questionKind`);
938
+ const envelopeHash = evaluation.envelopeHash === null
939
+ ? null
940
+ : hexDigest(evaluation.envelopeHash, `${path}.envelopeHash`);
941
+ return {
942
+ phaseId: enumValue(evaluation.phaseId, phaseIdSet, `${path}.phaseId`),
943
+ gateKind: enumValue(evaluation.gateKind, new Set(approvalGateKinds), `${path}.gateKind`),
944
+ questionKind: question,
945
+ approvalRequired: booleanField(evaluation, 'approvalRequired', path),
946
+ status: enumValue(evaluation.status, new Set(['not-required', 'approval-required', 'reused', 'expired', 'invalidated']), `${path}.status`),
947
+ envelopeId: evaluation.envelopeId === null ? null : stringField(evaluation, 'envelopeId', path),
948
+ envelopeHash,
949
+ reasons: stringArray(evaluation.reasons, `${path}.reasons`),
950
+ expansionReasons: stringArray(evaluation.expansionReasons, `${path}.expansionReasons`)
951
+ };
952
+ }
953
+ function validateRollbackPlan(value, path) {
954
+ const rollbackPlan = exact(value, [
955
+ 'phaseId',
956
+ 'strategy',
957
+ 'target',
958
+ 'operations',
959
+ 'retained',
960
+ 'cleanupWarnings'
961
+ ], path);
962
+ return {
963
+ phaseId: enumValue(rollbackPlan.phaseId, phaseIdSet, `${path}.phaseId`),
964
+ strategy: enumValue(rollbackPlan.strategy, new Set(rollbackKinds), `${path}.strategy`),
965
+ target: rollbackPlan.target === null ? null : enumValue(rollbackPlan.target, phaseIdSet, `${path}.target`),
966
+ operations: Array.isArray(rollbackPlan.operations)
967
+ ? rollbackPlan.operations.map((operation, index) => {
968
+ const validated = validateTransitionOperation(operation, `${path}.operations[${index}]`);
969
+ return {
970
+ adapter: validated.adapter,
971
+ actionId: validated.actionId,
972
+ mutationClass: validated.mutationClass,
973
+ phaseId: validated.phaseId,
974
+ inputs: validated.inputs,
975
+ destination: validated.destination,
976
+ remote: validated.remote,
977
+ destructive: validated.destructive
978
+ };
979
+ })
980
+ : (() => { throw new Error(`${path}.operations must be an array.`); })(),
981
+ retained: stringArray(rollbackPlan.retained, `${path}.retained`),
982
+ cleanupWarnings: stringArray(rollbackPlan.cleanupWarnings, `${path}.cleanupWarnings`)
983
+ };
984
+ }
985
+ export function validateSavedTransitionPlan(value) {
986
+ const plan = exact(value, [
987
+ 'schemaVersion',
988
+ 'phaseId',
989
+ 'createdAt',
990
+ 'expiresAt',
991
+ 'identity',
992
+ 'graphHash',
993
+ 'stateHash',
994
+ 'baselineDigest',
995
+ 'inputDigest',
996
+ 'transitionDigest',
997
+ 'planDigest',
998
+ 'mutationClasses',
999
+ 'operations',
1000
+ 'approval',
1001
+ 'rollbackPlan',
1002
+ 'noSecrets'
1003
+ ], 'transitionPlan');
1004
+ requireVersion(plan.schemaVersion, 1, 'transitionPlan.schemaVersion');
1005
+ const identity = validateActivationIdentity(plan.identity);
1006
+ const graphHash = hexDigest(plan.graphHash, 'transitionPlan.graphHash');
1007
+ if (graphHash !== identity.phaseGraphHash) {
1008
+ throw new Error('transitionPlan.graphHash must match identity.phaseGraphHash.');
1009
+ }
1010
+ const phaseId = enumValue(plan.phaseId, phaseIdSet, 'transitionPlan.phaseId');
1011
+ const mutationClassesValue = exact(plan.mutationClasses, ['local', 'remote'], 'transitionPlan.mutationClasses');
1012
+ const approval = exact(plan.approval, [
1013
+ 'gateKind',
1014
+ 'required',
1015
+ 'evaluation',
1016
+ 'envelopeId',
1017
+ 'envelopeHash'
1018
+ ], 'transitionPlan.approval');
1019
+ const operations = Array.isArray(plan.operations)
1020
+ ? plan.operations.map((operation, index) => validateTransitionOperation(operation, `transitionPlan.operations[${index}]`))
1021
+ : (() => { throw new Error('transitionPlan.operations must be an array.'); })();
1022
+ for (const operation of operations) {
1023
+ if (operation.phaseId !== phaseId) {
1024
+ throw new Error(`transitionPlan operation ${operation.actionId} phaseId must match ${phaseId}.`);
1025
+ }
1026
+ }
1027
+ const evaluation = validateApprovalEvaluation(approval.evaluation, 'transitionPlan.approval.evaluation');
1028
+ const envelopeHash = approval.envelopeHash === null
1029
+ ? null
1030
+ : hexDigest(approval.envelopeHash, 'transitionPlan.approval.envelopeHash');
1031
+ return {
1032
+ schemaVersion: 1,
1033
+ phaseId,
1034
+ createdAt: isoTimestamp(plan.createdAt, 'transitionPlan.createdAt'),
1035
+ expiresAt: isoTimestamp(plan.expiresAt, 'transitionPlan.expiresAt'),
1036
+ identity,
1037
+ graphHash,
1038
+ stateHash: plan.stateHash === null ? null : hexDigest(plan.stateHash, 'transitionPlan.stateHash'),
1039
+ baselineDigest: hexDigest(plan.baselineDigest, 'transitionPlan.baselineDigest'),
1040
+ inputDigest: hexDigest(plan.inputDigest, 'transitionPlan.inputDigest'),
1041
+ transitionDigest: hexDigest(plan.transitionDigest, 'transitionPlan.transitionDigest'),
1042
+ planDigest: hexDigest(plan.planDigest, 'transitionPlan.planDigest'),
1043
+ mutationClasses: {
1044
+ local: stringArray(mutationClassesValue.local, 'transitionPlan.mutationClasses.local').map((entry) => enumValue(entry, new Set(mutationClasses), 'transitionPlan.mutationClasses.local')),
1045
+ remote: stringArray(mutationClassesValue.remote, 'transitionPlan.mutationClasses.remote').map((entry) => enumValue(entry, new Set(mutationClasses), 'transitionPlan.mutationClasses.remote'))
1046
+ },
1047
+ operations,
1048
+ approval: {
1049
+ gateKind: enumValue(approval.gateKind, new Set(approvalGateKinds), 'transitionPlan.approval.gateKind'),
1050
+ required: booleanField(approval, 'required', 'transitionPlan.approval'),
1051
+ evaluation,
1052
+ envelopeId: approval.envelopeId === null ? null : stringField(approval, 'envelopeId', 'transitionPlan.approval'),
1053
+ envelopeHash
1054
+ },
1055
+ rollbackPlan: validateRollbackPlan(plan.rollbackPlan, 'transitionPlan.rollbackPlan'),
1056
+ noSecrets: plan.noSecrets === true ? true : (() => { throw new Error('transitionPlan.noSecrets must be true.'); })()
1057
+ };
1058
+ }
1059
+ export function validateSupersessionRecord(value) {
1060
+ const supersession = exact(value, [
1061
+ 'schemaVersion',
1062
+ 'identity',
1063
+ 'supersededChangeId',
1064
+ 'supersedingChangeId',
1065
+ 'reason',
1066
+ 'approvedAt',
1067
+ 'approver'
1068
+ ], 'supersession');
1069
+ requireVersion(supersession.schemaVersion, supersessionSchemaVersion, 'supersession.schemaVersion');
1070
+ return {
1071
+ schemaVersion: supersessionSchemaVersion,
1072
+ identity: validateActivationIdentity(supersession.identity),
1073
+ supersededChangeId: stringField(supersession, 'supersededChangeId', 'supersession'),
1074
+ supersedingChangeId: stringField(supersession, 'supersedingChangeId', 'supersession'),
1075
+ reason: stringField(supersession, 'reason', 'supersession'),
1076
+ approvedAt: stringField(supersession, 'approvedAt', 'supersession'),
1077
+ approver: stringField(supersession, 'approver', 'supersession')
1078
+ };
1079
+ }
1080
+ export function validateGraphReconciliationRecord(value, recognizedGraphHashes = new Set([canonicalPhaseGraphHash])) {
1081
+ const reconciliation = exact(value, [
1082
+ 'schemaVersion',
1083
+ 'fromGraphHash',
1084
+ 'toGraphHash',
1085
+ 'fromIdentity',
1086
+ 'toIdentity',
1087
+ 'phaseMappings',
1088
+ 'reconciledAt',
1089
+ 'producer'
1090
+ ], 'graphReconciliation');
1091
+ requireVersion(reconciliation.schemaVersion, activationStateSchemaVersion, 'graphReconciliation.schemaVersion');
1092
+ const fromGraphHash = hexDigest(reconciliation.fromGraphHash, 'graphReconciliation.fromGraphHash');
1093
+ const toGraphHash = hexDigest(reconciliation.toGraphHash, 'graphReconciliation.toGraphHash');
1094
+ if (!recognizedGraphHashes.has(fromGraphHash)) {
1095
+ throw new Error(`graphReconciliation.fromGraphHash is not a recognized graph hash: ${fromGraphHash}.`);
1096
+ }
1097
+ if (!recognizedGraphHashes.has(toGraphHash)) {
1098
+ throw new Error(`graphReconciliation.toGraphHash is not a recognized graph hash: ${toGraphHash}.`);
1099
+ }
1100
+ const fromIdentity = validateActivationIdentityShape(reconciliation.fromIdentity, 'graphReconciliation.fromIdentity');
1101
+ const toIdentity = validateActivationIdentityShape(reconciliation.toIdentity, 'graphReconciliation.toIdentity');
1102
+ if (fromIdentity.phaseGraphHash !== fromGraphHash) {
1103
+ throw new Error('graphReconciliation.fromIdentity.phaseGraphHash must match fromGraphHash.');
1104
+ }
1105
+ if (toIdentity.phaseGraphHash !== toGraphHash) {
1106
+ throw new Error('graphReconciliation.toIdentity.phaseGraphHash must match toGraphHash.');
1107
+ }
1108
+ if (!Array.isArray(reconciliation.phaseMappings)) {
1109
+ throw new Error('graphReconciliation.phaseMappings must be an array.');
1110
+ }
1111
+ const seen = new Set();
1112
+ const phaseMappings = reconciliation.phaseMappings.map((entry, index) => {
1113
+ const mapping = exact(entry, [
1114
+ 'phaseId',
1115
+ 'fromContractDigest',
1116
+ 'toContractDigest',
1117
+ 'preserveEvidence'
1118
+ ], `graphReconciliation.phaseMappings[${index}]`);
1119
+ const phaseId = enumValue(mapping.phaseId, phaseIdSet, `graphReconciliation.phaseMappings[${index}].phaseId`);
1120
+ if (seen.has(phaseId)) {
1121
+ throw new Error(`graphReconciliation.phaseMappings contains duplicate phase ${phaseId}.`);
1122
+ }
1123
+ seen.add(phaseId);
1124
+ const fromContractDigest = hexDigest(mapping.fromContractDigest, `graphReconciliation.phaseMappings[${index}].fromContractDigest`);
1125
+ const toContractDigest = hexDigest(mapping.toContractDigest, `graphReconciliation.phaseMappings[${index}].toContractDigest`);
1126
+ const preserveEvidence = booleanField(mapping, 'preserveEvidence', `graphReconciliation.phaseMappings[${index}]`);
1127
+ if (preserveEvidence && fromContractDigest !== toContractDigest) {
1128
+ throw new Error(`graphReconciliation.phaseMappings[${index}] cannot preserve evidence for changed phase ${phaseId}.`);
1129
+ }
1130
+ return {
1131
+ phaseId,
1132
+ fromContractDigest,
1133
+ toContractDigest,
1134
+ preserveEvidence
1135
+ };
1136
+ });
1137
+ for (const phaseId of phaseIds) {
1138
+ if (!seen.has(phaseId)) {
1139
+ throw new Error(`graphReconciliation.phaseMappings.${phaseId} is required.`);
1140
+ }
1141
+ }
1142
+ return {
1143
+ schemaVersion: activationStateSchemaVersion,
1144
+ fromGraphHash,
1145
+ toGraphHash,
1146
+ fromIdentity,
1147
+ toIdentity,
1148
+ phaseMappings,
1149
+ reconciledAt: isoTimestamp(reconciliation.reconciledAt, 'graphReconciliation.reconciledAt'),
1150
+ producer: stringField(reconciliation, 'producer', 'graphReconciliation')
1151
+ };
1152
+ }
1153
+ export function validateCredentialPolicy(value) {
1154
+ const policy = exact(value, [
1155
+ 'schemaVersion',
1156
+ 'identity',
1157
+ 'repository',
1158
+ 'owner',
1159
+ 'authKind',
1160
+ 'displayNameTemplate',
1161
+ 'displayName',
1162
+ 'secretName',
1163
+ 'createdAt',
1164
+ 'expiresAt',
1165
+ 'rotationLeadDays',
1166
+ 'rotationDueAt',
1167
+ 'permissions',
1168
+ 'allowedWorkflows',
1169
+ 'nonForwarding',
1170
+ 'status',
1171
+ 'proof',
1172
+ 'app',
1173
+ 'pat'
1174
+ ], 'credentialPolicy');
1175
+ requireVersion(policy.schemaVersion, credentialPolicySchemaVersion, 'credentialPolicy.schemaVersion');
1176
+ const permissions = exact(policy.permissions, ['repository', 'organization'], 'credentialPolicy.permissions');
1177
+ if (policy.nonForwarding !== true) {
1178
+ throw new Error('credentialPolicy.nonForwarding must be true.');
1179
+ }
1180
+ if (policy.secretName !== runnerPreflightSecretName) {
1181
+ throw new Error(`credentialPolicy.secretName must be ${runnerPreflightSecretName}.`);
1182
+ }
1183
+ if (policy.displayNameTemplate !== runnerPreflightDisplayNameTemplate) {
1184
+ throw new Error(`credentialPolicy.displayNameTemplate must be ${runnerPreflightDisplayNameTemplate}.`);
1185
+ }
1186
+ if (!Array.isArray(policy.allowedWorkflows)) {
1187
+ throw new Error('credentialPolicy.allowedWorkflows must be an array.');
1188
+ }
1189
+ if (policy.allowedWorkflows.length === 0) {
1190
+ throw new Error('credentialPolicy.allowedWorkflows must contain at least one workflow.');
1191
+ }
1192
+ const repository = validateCredentialRepositoryIdentity(policy.repository, 'credentialPolicy.repository');
1193
+ if (policy.owner !== repository.owner) {
1194
+ throw new Error('credentialPolicy.owner must match credentialPolicy.repository.owner.');
1195
+ }
1196
+ const displayName = stringField(policy, 'displayName', 'credentialPolicy');
1197
+ if (displayName !== `${repository.name.toLowerCase()}-runner-preflight-read`) {
1198
+ throw new Error('credentialPolicy.displayName must be derived from the canonical repository name.');
1199
+ }
1200
+ const createdAt = isoTimestamp(policy.createdAt, 'credentialPolicy.createdAt');
1201
+ const expiresAt = isoTimestamp(policy.expiresAt, 'credentialPolicy.expiresAt');
1202
+ const rotationLeadDays = integerField(policy, 'rotationLeadDays', 'credentialPolicy');
1203
+ requireVersion(rotationLeadDays, runnerPreflightRotationLeadDays, 'credentialPolicy.rotationLeadDays');
1204
+ const rotationDueAt = isoTimestamp(policy.rotationDueAt, 'credentialPolicy.rotationDueAt');
1205
+ if (rotationDueAt !== addDaysIso(expiresAt, -runnerPreflightRotationLeadDays)) {
1206
+ throw new Error('credentialPolicy.rotationDueAt must equal expiresAt minus the rotation lead.');
1207
+ }
1208
+ const repositoryPermissions = stringArray(permissions.repository, 'credentialPolicy.permissions.repository');
1209
+ const organizationPermissions = stringArray(permissions.organization, 'credentialPolicy.permissions.organization');
1210
+ assertNoDuplicateStrings(repositoryPermissions, 'credentialPolicy.permissions.repository');
1211
+ assertNoDuplicateStrings(organizationPermissions, 'credentialPolicy.permissions.organization');
1212
+ exactStringSet(repositoryPermissions, runnerPreflightRepositoryPermissions, 'credentialPolicy.permissions.repository');
1213
+ exactStringSet(organizationPermissions, runnerPreflightOrganizationPermissions, 'credentialPolicy.permissions.organization');
1214
+ const authKind = enumValue(policy.authKind, new Set(['github-app', 'fine-grained-pat']), 'credentialPolicy.authKind');
1215
+ const proof = exact(policy.proof, ['verifiedAt', 'readbackDigest', 'readbackProvider', 'payloadFree'], 'credentialPolicy.proof');
1216
+ if (proof.payloadFree !== true) {
1217
+ throw new Error('credentialPolicy.proof.payloadFree must be true.');
1218
+ }
1219
+ const app = policy.app === null
1220
+ ? null
1221
+ : exact(policy.app, [
1222
+ 'installationId',
1223
+ 'appSlug',
1224
+ 'selection',
1225
+ 'repositoryFullName',
1226
+ 'permissionsVerifiedAt',
1227
+ 'token'
1228
+ ], 'credentialPolicy.app');
1229
+ const pat = policy.pat === null
1230
+ ? null
1231
+ : exact(policy.pat, [
1232
+ 'lifetimeDays',
1233
+ 'selectedRepositoryOnly',
1234
+ 'createdBy'
1235
+ ], 'credentialPolicy.pat');
1236
+ if (authKind === 'github-app') {
1237
+ if (app === null || pat !== null) {
1238
+ throw new Error('credentialPolicy.github-app requires app metadata and no PAT metadata.');
1239
+ }
1240
+ if (integerField(app, 'installationId', 'credentialPolicy.app') <= 0) {
1241
+ throw new Error('credentialPolicy.app.installationId must be positive.');
1242
+ }
1243
+ if (app.selection !== 'selected-repository') {
1244
+ throw new Error('credentialPolicy.app.selection must be selected-repository.');
1245
+ }
1246
+ if (stringField(app, 'repositoryFullName', 'credentialPolicy.app') !== repository.fullName) {
1247
+ throw new Error('credentialPolicy.app.repositoryFullName must match the policy repository.');
1248
+ }
1249
+ }
1250
+ else {
1251
+ if (pat === null || app !== null) {
1252
+ throw new Error('credentialPolicy.fine-grained-pat requires PAT metadata and no App metadata.');
1253
+ }
1254
+ requireVersion(pat.lifetimeDays, runnerPreflightPatLifetimeDays, 'credentialPolicy.pat.lifetimeDays');
1255
+ if (dateDaysBetween(createdAt, expiresAt) !== runnerPreflightPatLifetimeDays) {
1256
+ throw new Error('credentialPolicy fine-grained PAT expiry must be exactly 30 days after creation.');
1257
+ }
1258
+ if (pat.selectedRepositoryOnly !== true) {
1259
+ throw new Error('credentialPolicy.pat.selectedRepositoryOnly must be true.');
1260
+ }
1261
+ if (pat.createdBy !== 'manual-masked-entry') {
1262
+ throw new Error('credentialPolicy.pat.createdBy must be manual-masked-entry.');
1263
+ }
1264
+ }
1265
+ const typedApp = app === null
1266
+ ? null
1267
+ : {
1268
+ installationId: integerField(app, 'installationId', 'credentialPolicy.app'),
1269
+ appSlug: stringField(app, 'appSlug', 'credentialPolicy.app'),
1270
+ selection: enumValue(app.selection, new Set(['selected-repository']), 'credentialPolicy.app.selection'),
1271
+ repositoryFullName: stringField(app, 'repositoryFullName', 'credentialPolicy.app'),
1272
+ permissionsVerifiedAt: isoTimestamp(app.permissionsVerifiedAt, 'credentialPolicy.app.permissionsVerifiedAt'),
1273
+ token: (() => {
1274
+ const token = exact(app.token, ['strategy', 'ttlSeconds', 'generatedBy'], 'credentialPolicy.app.token');
1275
+ const ttlSeconds = integerField(token, 'ttlSeconds', 'credentialPolicy.app.token');
1276
+ if (ttlSeconds <= 0 || ttlSeconds > 3600) {
1277
+ throw new Error('credentialPolicy.app.token.ttlSeconds must be between 1 and 3600.');
1278
+ }
1279
+ return {
1280
+ strategy: enumValue(token.strategy, new Set(['installation-token']), 'credentialPolicy.app.token.strategy'),
1281
+ ttlSeconds,
1282
+ generatedBy: enumValue(token.generatedBy, new Set(['github-app']), 'credentialPolicy.app.token.generatedBy')
1283
+ };
1284
+ })()
1285
+ };
1286
+ return {
1287
+ schemaVersion: credentialPolicySchemaVersion,
1288
+ identity: validateActivationIdentity(policy.identity),
1289
+ repository,
1290
+ owner: stringField(policy, 'owner', 'credentialPolicy'),
1291
+ authKind,
1292
+ displayNameTemplate: runnerPreflightDisplayNameTemplate,
1293
+ displayName,
1294
+ secretName: runnerPreflightSecretName,
1295
+ createdAt,
1296
+ expiresAt,
1297
+ rotationLeadDays: runnerPreflightRotationLeadDays,
1298
+ rotationDueAt,
1299
+ permissions: {
1300
+ repository: [...runnerPreflightRepositoryPermissions],
1301
+ organization: [...runnerPreflightOrganizationPermissions]
1302
+ },
1303
+ allowedWorkflows: (() => {
1304
+ const workflowPaths = new Set();
1305
+ return policy.allowedWorkflows.map((entry, index) => {
1306
+ const workflow = exact(entry, ['path', 'jobs'], `credentialPolicy.allowedWorkflows[${index}]`);
1307
+ const jobs = stringArray(workflow.jobs, `credentialPolicy.allowedWorkflows[${index}].jobs`);
1308
+ if (jobs.length === 0) {
1309
+ throw new Error(`credentialPolicy.allowedWorkflows[${index}].jobs must contain at least one job.`);
1310
+ }
1311
+ assertNoDuplicateStrings(jobs, `credentialPolicy.allowedWorkflows[${index}].jobs`);
1312
+ const workflowPath = stringField(workflow, 'path', `credentialPolicy.allowedWorkflows[${index}]`);
1313
+ if (!workflowPath.startsWith('.github/workflows/')) {
1314
+ throw new Error(`credentialPolicy.allowedWorkflows[${index}].path must be a GitHub Actions workflow path.`);
1315
+ }
1316
+ if (workflowPaths.has(workflowPath)) {
1317
+ throw new Error(`credentialPolicy.allowedWorkflows contains duplicate workflow ${workflowPath}.`);
1318
+ }
1319
+ workflowPaths.add(workflowPath);
1320
+ return {
1321
+ path: workflowPath,
1322
+ jobs
1323
+ };
1324
+ });
1325
+ })(),
1326
+ nonForwarding: true,
1327
+ status: enumValue(policy.status, new Set(['active', 'expiring', 'expired', 'compromised']), 'credentialPolicy.status'),
1328
+ proof: {
1329
+ verifiedAt: isoTimestamp(proof.verifiedAt, 'credentialPolicy.proof.verifiedAt'),
1330
+ readbackDigest: hexDigest(proof.readbackDigest, 'credentialPolicy.proof.readbackDigest'),
1331
+ readbackProvider: enumValue(proof.readbackProvider, new Set(['github-api', 'adapter-fixture']), 'credentialPolicy.proof.readbackProvider'),
1332
+ payloadFree: true
1333
+ },
1334
+ app: typedApp,
1335
+ pat: pat === null
1336
+ ? null
1337
+ : {
1338
+ lifetimeDays: runnerPreflightPatLifetimeDays,
1339
+ selectedRepositoryOnly: true,
1340
+ createdBy: 'manual-masked-entry'
1341
+ }
1342
+ };
1343
+ }
1344
+ export function validFixtureIdentity() {
1345
+ return currentActivationIdentity;
1346
+ }
1347
+ //# sourceMappingURL=validators.js.map