@msn-control/liftoff 0.11.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/DEVELOPER.md +26 -24
  2. package/README.md +18 -18
  3. package/assets/governance/single-maintainer-gitflow/activation-v2-graph.json +1583 -0
  4. package/dist/adapters/credentials/github-enrollment.d.ts +51 -0
  5. package/dist/adapters/credentials/github-enrollment.js +226 -0
  6. package/dist/adapters/credentials/github-enrollment.js.map +1 -0
  7. package/dist/adapters/credentials/protected-input.d.ts +7 -0
  8. package/dist/adapters/credentials/protected-input.js +68 -0
  9. package/dist/adapters/credentials/protected-input.js.map +1 -0
  10. package/dist/adapters/filesystem/executables.d.ts +2 -0
  11. package/dist/adapters/filesystem/executables.js +70 -0
  12. package/dist/adapters/filesystem/executables.js.map +1 -0
  13. package/dist/adapters/filesystem/update-previews.d.ts +9 -0
  14. package/dist/adapters/filesystem/update-previews.js +45 -2
  15. package/dist/adapters/filesystem/update-previews.js.map +1 -1
  16. package/dist/adapters/filesystem/workstation-attempts.d.ts +13 -0
  17. package/dist/adapters/filesystem/workstation-attempts.js +78 -0
  18. package/dist/adapters/filesystem/workstation-attempts.js.map +1 -0
  19. package/dist/adapters/github/activation-rest.d.ts +40 -0
  20. package/dist/adapters/github/activation-rest.js +272 -0
  21. package/dist/adapters/github/activation-rest.js.map +1 -0
  22. package/dist/adapters/process/shell-command.d.ts +1 -0
  23. package/dist/adapters/process/shell-command.js +5 -2
  24. package/dist/adapters/process/shell-command.js.map +1 -1
  25. package/dist/adapters/state/azure-blob.d.ts +43 -0
  26. package/dist/adapters/state/azure-blob.js +335 -0
  27. package/dist/adapters/state/azure-blob.js.map +1 -0
  28. package/dist/adapters/state/darwin-capabilities.d.ts +33 -0
  29. package/dist/adapters/state/darwin-capabilities.js +146 -0
  30. package/dist/adapters/state/darwin-capabilities.js.map +1 -0
  31. package/dist/adapters/state/darwin-native-host.d.ts +32 -0
  32. package/dist/adapters/state/darwin-native-host.js +294 -0
  33. package/dist/adapters/state/darwin-native-host.js.map +1 -0
  34. package/dist/adapters/state/darwin-profile.d.ts +6 -0
  35. package/dist/adapters/state/darwin-profile.js +56 -0
  36. package/dist/adapters/state/darwin-profile.js.map +1 -0
  37. package/dist/adapters/state/darwin-system-program.d.ts +1 -0
  38. package/dist/adapters/state/darwin-system-program.js +94 -0
  39. package/dist/adapters/state/darwin-system-program.js.map +1 -0
  40. package/dist/adapters/state/local-qualification.d.ts +16 -0
  41. package/dist/adapters/state/local-qualification.js +299 -0
  42. package/dist/adapters/state/local-qualification.js.map +1 -0
  43. package/dist/adapters/state/local.d.ts +25 -0
  44. package/dist/adapters/state/local.js +145 -0
  45. package/dist/adapters/state/local.js.map +1 -0
  46. package/dist/adapters/state/native-command.d.ts +21 -0
  47. package/dist/adapters/state/native-command.js +82 -0
  48. package/dist/adapters/state/native-command.js.map +1 -0
  49. package/dist/adapters/state/native-files.d.ts +2 -0
  50. package/dist/adapters/state/native-files.js +47 -0
  51. package/dist/adapters/state/native-files.js.map +1 -0
  52. package/dist/adapters/state/native-system.d.ts +38 -0
  53. package/dist/adapters/state/native-system.js +86 -0
  54. package/dist/adapters/state/native-system.js.map +1 -0
  55. package/dist/adapters/state/opentofu.d.ts +35 -0
  56. package/dist/adapters/state/opentofu.js +350 -0
  57. package/dist/adapters/state/opentofu.js.map +1 -0
  58. package/dist/adapters/state/owned-process.d.ts +43 -0
  59. package/dist/adapters/state/owned-process.js +252 -0
  60. package/dist/adapters/state/owned-process.js.map +1 -0
  61. package/dist/adapters/state/posix-lock-program.d.ts +1 -0
  62. package/dist/adapters/state/posix-lock-program.js +185 -0
  63. package/dist/adapters/state/posix-lock-program.js.map +1 -0
  64. package/dist/adapters/state/posix-native-lock.d.ts +15 -0
  65. package/dist/adapters/state/posix-native-lock.js +145 -0
  66. package/dist/adapters/state/posix-native-lock.js.map +1 -0
  67. package/dist/adapters/state/protected-workspace.d.ts +57 -0
  68. package/dist/adapters/state/protected-workspace.js +412 -0
  69. package/dist/adapters/state/protected-workspace.js.map +1 -0
  70. package/dist/application/context.d.ts +3 -0
  71. package/dist/application/diagnose/doctor.d.ts +5 -0
  72. package/dist/application/diagnose/doctor.js +21 -5
  73. package/dist/application/diagnose/doctor.js.map +1 -1
  74. package/dist/application/diagnose/generated-project.js +2 -7
  75. package/dist/application/diagnose/generated-project.js.map +1 -1
  76. package/dist/application/initialize/fixture.js +8 -1
  77. package/dist/application/initialize/fixture.js.map +1 -1
  78. package/dist/application/initialize/use-case.js +70 -36
  79. package/dist/application/initialize/use-case.js.map +1 -1
  80. package/dist/application/project/manifest.js +5 -4
  81. package/dist/application/project/manifest.js.map +1 -1
  82. package/dist/application/state-migration/execution.d.ts +32 -0
  83. package/dist/application/state-migration/execution.js +440 -0
  84. package/dist/application/state-migration/execution.js.map +1 -0
  85. package/dist/application/state-migration/index.d.ts +22 -0
  86. package/dist/application/state-migration/index.js +17 -0
  87. package/dist/application/state-migration/index.js.map +1 -0
  88. package/dist/application/state-migration/lifecycle.d.ts +3 -0
  89. package/dist/application/state-migration/lifecycle.js +149 -0
  90. package/dist/application/state-migration/lifecycle.js.map +1 -0
  91. package/dist/application/state-migration/planning.d.ts +7 -0
  92. package/dist/application/state-migration/planning.js +150 -0
  93. package/dist/application/state-migration/planning.js.map +1 -0
  94. package/dist/application/state-migration/recovery.d.ts +5 -0
  95. package/dist/application/state-migration/recovery.js +145 -0
  96. package/dist/application/state-migration/recovery.js.map +1 -0
  97. package/dist/application/state-migration/runtime.d.ts +32 -0
  98. package/dist/application/state-migration/runtime.js +188 -0
  99. package/dist/application/state-migration/runtime.js.map +1 -0
  100. package/dist/application/state-migration/service.d.ts +2 -0
  101. package/dist/application/state-migration/service.js +20 -0
  102. package/dist/application/state-migration/service.js.map +1 -0
  103. package/dist/application/update/command-guidance.d.ts +19 -2
  104. package/dist/application/update/command-guidance.js +20 -6
  105. package/dist/application/update/command-guidance.js.map +1 -1
  106. package/dist/application/update/guidance-context.d.ts +2 -0
  107. package/dist/application/update/guidance-context.js +35 -0
  108. package/dist/application/update/guidance-context.js.map +1 -0
  109. package/dist/application/update/inspection.d.ts +21 -4
  110. package/dist/application/update/inspection.js +88 -29
  111. package/dist/application/update/inspection.js.map +1 -1
  112. package/dist/application/update/migration-runtime.js +25 -13
  113. package/dist/application/update/migration-runtime.js.map +1 -1
  114. package/dist/application/update/output.d.ts +4 -1
  115. package/dist/application/update/output.js +14 -4
  116. package/dist/application/update/output.js.map +1 -1
  117. package/dist/application/update/preview.d.ts +10 -1
  118. package/dist/application/update/preview.js +26 -4
  119. package/dist/application/update/preview.js.map +1 -1
  120. package/dist/application/update/revalidation-plan.d.ts +1 -0
  121. package/dist/application/update/revalidation-plan.js +27 -15
  122. package/dist/application/update/revalidation-plan.js.map +1 -1
  123. package/dist/application/update/revalidation.d.ts +4 -1
  124. package/dist/application/update/revalidation.js +64 -23
  125. package/dist/application/update/revalidation.js.map +1 -1
  126. package/dist/application/update/use-case.js +50 -29
  127. package/dist/application/update/use-case.js.map +1 -1
  128. package/dist/cli/args/definitions.js +11 -3
  129. package/dist/cli/args/definitions.js.map +1 -1
  130. package/dist/cli/args/parser.js +29 -3
  131. package/dist/cli/args/parser.js.map +1 -1
  132. package/dist/domain/governance/activation/approvals.d.ts +264 -7
  133. package/dist/domain/governance/activation/approvals.js +166 -23
  134. package/dist/domain/governance/activation/approvals.js.map +1 -1
  135. package/dist/domain/governance/activation/capabilities.js +5 -2
  136. package/dist/domain/governance/activation/capabilities.js.map +1 -1
  137. package/dist/domain/governance/activation/evidence.d.ts +2 -1
  138. package/dist/domain/governance/activation/evidence.js +64 -11
  139. package/dist/domain/governance/activation/evidence.js.map +1 -1
  140. package/dist/domain/governance/activation/graph.d.ts +11 -384
  141. package/dist/domain/governance/activation/graph.js +424 -379
  142. package/dist/domain/governance/activation/graph.js.map +1 -1
  143. package/dist/domain/governance/activation/inputs.d.ts +3 -1
  144. package/dist/domain/governance/activation/inputs.js +47 -6
  145. package/dist/domain/governance/activation/inputs.js.map +1 -1
  146. package/dist/domain/governance/activation/operations.d.ts +4 -1
  147. package/dist/domain/governance/activation/operations.js +110 -22
  148. package/dist/domain/governance/activation/operations.js.map +1 -1
  149. package/dist/domain/governance/activation/readiness.d.ts +10 -0
  150. package/dist/domain/governance/activation/readiness.js +77 -38
  151. package/dist/domain/governance/activation/readiness.js.map +1 -1
  152. package/dist/domain/governance/activation/types.d.ts +151 -9
  153. package/dist/domain/governance/activation/types.js +23 -1
  154. package/dist/domain/governance/activation/types.js.map +1 -1
  155. package/dist/domain/governance/activation/validators.d.ts +4 -1
  156. package/dist/domain/governance/activation/validators.js +419 -26
  157. package/dist/domain/governance/activation/validators.js.map +1 -1
  158. package/dist/domain/governance/policy/identity.d.ts +55 -13
  159. package/dist/domain/governance/policy/identity.js +28 -8
  160. package/dist/domain/governance/policy/identity.js.map +1 -1
  161. package/dist/domain/project/artifact-lifecycle.d.ts +2 -1
  162. package/dist/domain/project/artifact-lifecycle.js +7 -1
  163. package/dist/domain/project/artifact-lifecycle.js.map +1 -1
  164. package/dist/domain/project/catalog.d.ts +50 -1
  165. package/dist/domain/project/catalog.js +104 -4
  166. package/dist/domain/project/catalog.js.map +1 -1
  167. package/dist/domain/project/contracts.d.ts +9 -1
  168. package/dist/domain/project/infrastructure-layout.d.ts +1 -1
  169. package/dist/domain/project/infrastructure-layout.js +3 -1
  170. package/dist/domain/project/infrastructure-layout.js.map +1 -1
  171. package/dist/domain/project/manifest/governance.d.ts +1 -1
  172. package/dist/domain/project/manifest/governance.js +9 -10
  173. package/dist/domain/project/manifest/governance.js.map +1 -1
  174. package/dist/domain/project/planning.js +4 -5
  175. package/dist/domain/project/planning.js.map +1 -1
  176. package/dist/domain/repair/stateful-bounded.d.ts +1 -0
  177. package/dist/domain/repair/stateful-bounded.js +37 -0
  178. package/dist/domain/repair/stateful-bounded.js.map +1 -0
  179. package/dist/domain/repair/stateful-invariants.d.ts +28 -0
  180. package/dist/domain/repair/stateful-invariants.js +278 -0
  181. package/dist/domain/repair/stateful-invariants.js.map +1 -0
  182. package/dist/domain/repair/stateful.d.ts +690 -0
  183. package/dist/domain/repair/stateful.js +26 -0
  184. package/dist/domain/repair/stateful.js.map +1 -0
  185. package/dist/domain/workstation/constraints.d.ts +1 -0
  186. package/dist/domain/workstation/constraints.js.map +1 -1
  187. package/dist/domain/workstation/contracts.d.ts +42 -0
  188. package/dist/domain/workstation/contracts.js +2 -0
  189. package/dist/domain/workstation/contracts.js.map +1 -0
  190. package/dist/domain/workstation/executables.d.ts +19 -0
  191. package/dist/domain/workstation/executables.js +68 -0
  192. package/dist/domain/workstation/executables.js.map +1 -0
  193. package/dist/domain/workstation/versions.d.ts +8 -0
  194. package/dist/domain/workstation/versions.js +145 -0
  195. package/dist/domain/workstation/versions.js.map +1 -0
  196. package/dist/framework-adapters.d.ts +2 -0
  197. package/dist/framework-adapters.js +148 -22
  198. package/dist/framework-adapters.js.map +1 -1
  199. package/dist/framework-validation.d.ts +6 -0
  200. package/dist/framework-validation.js +89 -24
  201. package/dist/framework-validation.js.map +1 -1
  202. package/dist/generators/common/base.js +57 -17
  203. package/dist/generators/common/base.js.map +1 -1
  204. package/dist/governance-activation/activation-state.js +39 -7
  205. package/dist/governance-activation/activation-state.js.map +1 -1
  206. package/dist/governance-activation/authority-records.d.ts +4 -0
  207. package/dist/governance-activation/authority-records.js +24 -0
  208. package/dist/governance-activation/authority-records.js.map +1 -0
  209. package/dist/governance-activation/commands.d.ts +9 -1
  210. package/dist/governance-activation/commands.js +392 -97
  211. package/dist/governance-activation/commands.js.map +1 -1
  212. package/dist/governance-activation/compatibility.d.ts +11 -8
  213. package/dist/governance-activation/compatibility.js +37 -23
  214. package/dist/governance-activation/compatibility.js.map +1 -1
  215. package/dist/governance-activation/doctor.js +40 -16
  216. package/dist/governance-activation/doctor.js.map +1 -1
  217. package/dist/governance-activation/github-config.d.ts +17 -0
  218. package/dist/governance-activation/github-config.js +88 -0
  219. package/dist/governance-activation/github-config.js.map +1 -0
  220. package/dist/governance-activation/github-discovery.d.ts +18 -0
  221. package/dist/governance-activation/github-discovery.js +229 -0
  222. package/dist/governance-activation/github-discovery.js.map +1 -0
  223. package/dist/governance-activation/github-ports.d.ts +12 -0
  224. package/dist/governance-activation/github-ports.js +4 -0
  225. package/dist/governance-activation/github-ports.js.map +1 -0
  226. package/dist/governance-activation/github-publication.d.ts +3 -0
  227. package/dist/governance-activation/github-publication.js +190 -0
  228. package/dist/governance-activation/github-publication.js.map +1 -0
  229. package/dist/governance-activation/historical-common.d.ts +98 -0
  230. package/dist/governance-activation/historical-common.js +269 -0
  231. package/dist/governance-activation/historical-common.js.map +1 -0
  232. package/dist/governance-activation/historical-credential-policy.d.ts +3 -0
  233. package/dist/governance-activation/historical-credential-policy.js +91 -0
  234. package/dist/governance-activation/historical-credential-policy.js.map +1 -0
  235. package/dist/governance-activation/historical-inputs.d.ts +6 -0
  236. package/dist/governance-activation/historical-inputs.js +57 -0
  237. package/dist/governance-activation/historical-inputs.js.map +1 -0
  238. package/dist/governance-activation/historical-safety.d.ts +9 -0
  239. package/dist/governance-activation/historical-safety.js +102 -0
  240. package/dist/governance-activation/historical-safety.js.map +1 -0
  241. package/dist/governance-activation/historical-source-metadata.d.ts +31 -0
  242. package/dist/governance-activation/historical-source-metadata.js +55 -0
  243. package/dist/governance-activation/historical-source-metadata.js.map +1 -0
  244. package/dist/governance-activation/historical-state.d.ts +12 -50
  245. package/dist/governance-activation/historical-state.js +195 -308
  246. package/dist/governance-activation/historical-state.js.map +1 -1
  247. package/dist/governance-activation/historical-v1-auxiliary.d.ts +1 -0
  248. package/dist/governance-activation/historical-v1-auxiliary.js +43 -0
  249. package/dist/governance-activation/historical-v1-auxiliary.js.map +1 -0
  250. package/dist/governance-activation/historical-v1-phase-contracts.d.ts +31 -0
  251. package/dist/governance-activation/historical-v1-phase-contracts.js +46 -0
  252. package/dist/governance-activation/historical-v1-phase-contracts.js.map +1 -0
  253. package/dist/governance-activation/historical-v2.d.ts +53 -0
  254. package/dist/governance-activation/historical-v2.js +313 -0
  255. package/dist/governance-activation/historical-v2.js.map +1 -0
  256. package/dist/governance-activation/history-contracts.d.ts +21 -12
  257. package/dist/governance-activation/history-contracts.js +99 -27
  258. package/dist/governance-activation/history-contracts.js.map +1 -1
  259. package/dist/governance-activation/inputs.d.ts +8 -2
  260. package/dist/governance-activation/inputs.js +41 -6
  261. package/dist/governance-activation/inputs.js.map +1 -1
  262. package/dist/governance-activation/migration-history.d.ts +43 -5
  263. package/dist/governance-activation/migration-history.js +231 -50
  264. package/dist/governance-activation/migration-history.js.map +1 -1
  265. package/dist/governance-activation/migration.d.ts +7 -4
  266. package/dist/governance-activation/migration.js +53 -252
  267. package/dist/governance-activation/migration.js.map +1 -1
  268. package/dist/governance-activation/phase-azure.d.ts +3 -0
  269. package/dist/governance-activation/phase-azure.js +205 -0
  270. package/dist/governance-activation/phase-azure.js.map +1 -0
  271. package/dist/governance-activation/phase-bootstrap-state.js +3 -0
  272. package/dist/governance-activation/phase-bootstrap-state.js.map +1 -1
  273. package/dist/governance-activation/phase-github.d.ts +3 -0
  274. package/dist/governance-activation/phase-github.js +192 -0
  275. package/dist/governance-activation/phase-github.js.map +1 -0
  276. package/dist/governance-activation/phase-governance.js +8 -2
  277. package/dist/governance-activation/phase-governance.js.map +1 -1
  278. package/dist/governance-activation/public-plans.d.ts +36 -0
  279. package/dist/governance-activation/public-plans.js +100 -0
  280. package/dist/governance-activation/public-plans.js.map +1 -0
  281. package/dist/governance-activation/read-only.d.ts +3 -1
  282. package/dist/governance-activation/read-only.js +7 -3
  283. package/dist/governance-activation/read-only.js.map +1 -1
  284. package/dist/governance-activation/reconciliation.js +10 -0
  285. package/dist/governance-activation/reconciliation.js.map +1 -1
  286. package/dist/governance-activation/seed-lifecycle.js +14 -25
  287. package/dist/governance-activation/seed-lifecycle.js.map +1 -1
  288. package/dist/governance-activation/source-of-truth.d.ts +21 -5
  289. package/dist/governance-activation/source-of-truth.js +102 -13
  290. package/dist/governance-activation/source-of-truth.js.map +1 -1
  291. package/dist/governance-activation/task-projection.d.ts +4 -1
  292. package/dist/governance-activation/task-projection.js +32 -3
  293. package/dist/governance-activation/task-projection.js.map +1 -1
  294. package/dist/governance-activation/task-writes.d.ts +42 -0
  295. package/dist/governance-activation/task-writes.js +250 -0
  296. package/dist/governance-activation/task-writes.js.map +1 -0
  297. package/dist/governance-activation/transition-files.d.ts +12 -0
  298. package/dist/governance-activation/transition-files.js +109 -0
  299. package/dist/governance-activation/transition-files.js.map +1 -0
  300. package/dist/governance-activation/transition-planning.d.ts +3 -1
  301. package/dist/governance-activation/transition-planning.js +158 -20
  302. package/dist/governance-activation/transition-planning.js.map +1 -1
  303. package/dist/governance-activation/transition-ports.d.ts +31 -3
  304. package/dist/governance-activation/transition-records.d.ts +11 -1
  305. package/dist/governance-activation/transition-records.js +52 -6
  306. package/dist/governance-activation/transition-records.js.map +1 -1
  307. package/dist/governance-activation/transitions.d.ts +5 -0
  308. package/dist/governance-activation/transitions.js +271 -37
  309. package/dist/governance-activation/transitions.js.map +1 -1
  310. package/dist/governance-assessment/engine.js +22 -15
  311. package/dist/governance-assessment/engine.js.map +1 -1
  312. package/dist/governance-assessment/project.d.ts +2 -0
  313. package/dist/governance-assessment/project.js +2 -1
  314. package/dist/governance-assessment/project.js.map +1 -1
  315. package/dist/interactive.d.ts +0 -1
  316. package/dist/interactive.js +3 -22
  317. package/dist/interactive.js.map +1 -1
  318. package/dist/openspec-profile.d.ts +2 -1
  319. package/dist/openspec-profile.js +11 -41
  320. package/dist/openspec-profile.js.map +1 -1
  321. package/dist/repository-governance.d.ts +10 -5
  322. package/dist/repository-governance.js +178 -92
  323. package/dist/repository-governance.js.map +1 -1
  324. package/dist/telemetry/contract.d.ts +1 -1
  325. package/dist/telemetry/contract.js +3 -0
  326. package/dist/telemetry/contract.js.map +1 -1
  327. package/dist/workstation-catalog.d.ts +13 -1
  328. package/dist/workstation-catalog.js +122 -0
  329. package/dist/workstation-catalog.js.map +1 -1
  330. package/dist/workstation.d.ts +69 -14
  331. package/dist/workstation.js +600 -215
  332. package/dist/workstation.js.map +1 -1
  333. package/docs/cli-reference.md +94 -23
  334. package/docs/configuration-and-manifests.md +11 -10
  335. package/docs/prerequisites.md +93 -18
  336. package/docs/repository-governance.md +68 -40
  337. package/docs/spec-workflows-and-agents.md +132 -13
  338. package/docs/troubleshooting.md +28 -0
  339. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-command.js","sourceRoot":"","sources":["../../../src/adapters/state/native-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function writePrivateNativeFile(filename: string, bytes: string | Uint8Array, exclusive?: boolean): Promise<void>;
2
+ export declare function readPrivateNativeFile(filename: string, maximumBytes: number): Promise<Uint8Array>;
@@ -0,0 +1,47 @@
1
+ import { constants } from 'node:fs';
2
+ import { lstat, open, realpath } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { stateAssert } from '../../domain/repair/stateful-invariants.js';
5
+ async function inspectNativeFile(filename) {
6
+ stateAssert(path.isAbsolute(filename) && await realpath(path.dirname(filename)) === path.dirname(filename), 'unsafe-path');
7
+ const existing = await lstat(filename).catch((error) => {
8
+ if (error.code === 'ENOENT')
9
+ return null;
10
+ throw error;
11
+ });
12
+ stateAssert(!existing || (existing.isFile() && !existing.isSymbolicLink() && existing.nlink === 1), 'unsafe-path');
13
+ return existing;
14
+ }
15
+ export async function writePrivateNativeFile(filename, bytes, exclusive = false) {
16
+ const before = await inspectNativeFile(filename);
17
+ stateAssert(!exclusive || !before, 'unsafe-path');
18
+ const file = await open(filename, constants.O_WRONLY | constants.O_CREAT | (constants.O_NOFOLLOW ?? 0)
19
+ | (exclusive ? constants.O_EXCL : 0), 0o600);
20
+ try {
21
+ const current = await file.stat();
22
+ stateAssert(current.isFile() && current.nlink === 1
23
+ && (!before || (current.ino === before.ino && current.dev === before.dev)), 'unsafe-path');
24
+ await file.chmod(0o600);
25
+ await file.truncate(0);
26
+ await file.writeFile(bytes);
27
+ await file.sync();
28
+ }
29
+ finally {
30
+ await file.close();
31
+ }
32
+ }
33
+ export async function readPrivateNativeFile(filename, maximumBytes) {
34
+ const before = await inspectNativeFile(filename);
35
+ stateAssert(before && before.size <= maximumBytes, 'storage-limit');
36
+ const file = await open(filename, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
37
+ try {
38
+ const current = await file.stat();
39
+ stateAssert(current.isFile() && current.nlink === 1 && current.ino === before.ino && current.dev === before.dev
40
+ && current.size === before.size, 'unsafe-path');
41
+ return await file.readFile();
42
+ }
43
+ finally {
44
+ await file.close();
45
+ }
46
+ }
47
+ //# sourceMappingURL=native-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-files.js","sourceRoot":"","sources":["../../../src/adapters/state/native-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { ChildProcessWithoutNullStreams } from 'node:child_process';
2
+ import { type NativeLocalStateTools, type StateRegisteredExecutable } from '../../domain/repair/stateful.js';
3
+ export declare const nativeLocalStateProtocol: Readonly<{
4
+ version: 'opentofu-1.12.6-posix-fcntl';
5
+ tofuVersion: '1.12.6';
6
+ sourceCommit: "b4305e5a5dd2fb79a27897ae30784a181d3a26cb";
7
+ lockSource: "internal/flock/filesystem_lock_unix.go";
8
+ lockBlob: "c396e445a0eede26b32b97068216fe3691070d9f";
9
+ stateSource: "internal/states/statemgr/filesystem.go";
10
+ stateBlob: "3f01209ea1635c9cad5f499f4f08ce356aef9a4c";
11
+ lockOperation: "F_SETLK/F_WRLCK/start=0/length=0";
12
+ writeOperation: "seek/truncate/write/sync on the same open inode";
13
+ }>;
14
+ export declare function nativeStateHostId(): string;
15
+ export declare function captureStateExecutable(filename: string): Promise<StateRegisteredExecutable>;
16
+ export declare function verifyStateExecutable(executable: StateRegisteredExecutable): Promise<void>;
17
+ export declare function isolatedStateEnvironment(cwd: string): NodeJS.ProcessEnv;
18
+ export declare function startPrivateStateProcess(executable: StateRegisteredExecutable, args: readonly string[], cwd: string, environment?: NodeJS.ProcessEnv, role?: 'command' | 'lease'): Promise<ChildProcessWithoutNullStreams>;
19
+ export declare function runPrivateStateProcess(request: {
20
+ executable: StateRegisteredExecutable;
21
+ args: readonly string[];
22
+ cwd: string;
23
+ stdin?: Uint8Array;
24
+ timeoutMs?: number;
25
+ maximumBytes?: number;
26
+ environment?: NodeJS.ProcessEnv;
27
+ signal?: AbortSignal;
28
+ }): Promise<{
29
+ exitCode: number;
30
+ stdout: Uint8Array;
31
+ stderr: Uint8Array;
32
+ }>;
33
+ export declare function inspectNativeLocalStateTools(request: {
34
+ pythonPath: string;
35
+ tofuPath: string;
36
+ workingDirectory: string;
37
+ signal?: AbortSignal;
38
+ }): Promise<NativeLocalStateTools>;
@@ -0,0 +1,86 @@
1
+ import { lstat, readFile, realpath } from 'node:fs/promises';
2
+ import { hostname } from 'node:os';
3
+ import path from 'node:path';
4
+ import { stateAssert, stateDigest, stateObjectDigest } from '../../domain/repair/stateful-invariants.js';
5
+ import { OwnedPrivateStateProcessRunner, spawnOwnedStateProcess } from './owned-process.js';
6
+ export const nativeLocalStateProtocol = Object.freeze({
7
+ version: 'opentofu-1.12.6-posix-fcntl',
8
+ tofuVersion: '1.12.6',
9
+ sourceCommit: 'b4305e5a5dd2fb79a27897ae30784a181d3a26cb',
10
+ lockSource: 'internal/flock/filesystem_lock_unix.go',
11
+ lockBlob: 'c396e445a0eede26b32b97068216fe3691070d9f',
12
+ stateSource: 'internal/states/statemgr/filesystem.go',
13
+ stateBlob: '3f01209ea1635c9cad5f499f4f08ce356aef9a4c',
14
+ lockOperation: 'F_SETLK/F_WRLCK/start=0/length=0',
15
+ writeOperation: 'seek/truncate/write/sync on the same open inode'
16
+ });
17
+ export function nativeStateHostId() {
18
+ return `native-host:${stateObjectDigest({ platform: process.platform, host: hostname(), uid: process.getuid?.() })}`;
19
+ }
20
+ export async function captureStateExecutable(filename) {
21
+ stateAssert(path.isAbsolute(filename), 'tool-unavailable');
22
+ const resolved = await realpath(filename);
23
+ const info = await lstat(resolved);
24
+ stateAssert(info.isFile() && (info.mode & 0o022) === 0 && (info.mode & 0o111) !== 0, 'tool-unavailable');
25
+ return { path: resolved, sha256: stateDigest(await readFile(resolved)) };
26
+ }
27
+ export async function verifyStateExecutable(executable) {
28
+ stateAssert((await captureStateExecutable(executable.path)).sha256 === executable.sha256, 'tool-unavailable');
29
+ }
30
+ export function isolatedStateEnvironment(cwd) {
31
+ return {
32
+ PATH: '/usr/bin:/bin:/usr/sbin:/sbin', HOME: cwd, USERPROFILE: cwd,
33
+ XDG_CONFIG_HOME: cwd, TMPDIR: cwd, TMP: cwd, TEMP: cwd,
34
+ CHECKPOINT_DISABLE: '1', TF_IN_AUTOMATION: '1', TF_LOG: 'OFF',
35
+ TF_CLI_CONFIG_FILE: path.join(cwd, 'liftoff.private.tfrc'),
36
+ TF_DATA_DIR: path.join(cwd, '.terraform'), LC_ALL: 'C'
37
+ };
38
+ }
39
+ export async function startPrivateStateProcess(executable, args, cwd, environment = isolatedStateEnvironment(cwd), role = 'command') {
40
+ await verifyStateExecutable(executable);
41
+ stateAssert(path.isAbsolute(cwd) && args.every((arg) => !arg.includes('\0')), 'unsafe-path');
42
+ return spawnOwnedStateProcess({ executable: executable.path, args, cwd, environment, role });
43
+ }
44
+ export async function runPrivateStateProcess(request) {
45
+ const timeout = request.timeoutMs ?? 20_000;
46
+ stateAssert(timeout > 0 && timeout <= 300_000, 'invalid-binding');
47
+ await verifyStateExecutable(request.executable);
48
+ return new OwnedPrivateStateProcessRunner().run({
49
+ executable: request.executable.path, args: request.args, cwd: request.cwd,
50
+ environment: request.environment ?? isolatedStateEnvironment(request.cwd), stdin: request.stdin,
51
+ signal: request.signal, timeoutMs: timeout, maximumBytes: request.maximumBytes ?? 2 * 1024 * 1024
52
+ });
53
+ }
54
+ export async function inspectNativeLocalStateTools(request) {
55
+ stateAssert(process.platform === 'darwin', 'unsupported-native-platform');
56
+ const python = await captureStateExecutable(request.pythonPath);
57
+ const tofu = await captureStateExecutable(request.tofuPath);
58
+ const py = await runPrivateStateProcess({
59
+ executable: python, args: ['-I', '-S', '-B', '-c', 'import json,platform,sys; print(json.dumps({"implementation":platform.python_implementation(),"version":".".join(map(str,sys.version_info[:3]))}))'],
60
+ cwd: request.workingDirectory, signal: request.signal
61
+ });
62
+ let pythonVersion;
63
+ try {
64
+ const info = JSON.parse(Buffer.from(py.stdout).toString('utf8'));
65
+ stateAssert(py.exitCode === 0 && info.implementation === 'CPython' && /^3\.14\.\d+$/.test(info.version), 'native-lock-provider-required');
66
+ pythonVersion = info.version;
67
+ }
68
+ finally {
69
+ py.stdout.fill(0);
70
+ py.stderr.fill(0);
71
+ }
72
+ const tf = await runPrivateStateProcess({
73
+ executable: tofu, args: ['version', '-json'], cwd: request.workingDirectory, signal: request.signal
74
+ });
75
+ try {
76
+ const info = JSON.parse(Buffer.from(tf.stdout).toString('utf8'));
77
+ stateAssert(tf.exitCode === 0 && info.terraform_version === nativeLocalStateProtocol.tofuVersion
78
+ && info.platform === `darwin_${process.arch === 'arm64' ? 'arm64' : 'amd64'}`, 'unqualified-combination');
79
+ }
80
+ finally {
81
+ tf.stdout.fill(0);
82
+ tf.stderr.fill(0);
83
+ }
84
+ return { python, tofu, pythonVersion, tofuVersion: '1.12.6', hostId: nativeStateHostId() };
85
+ }
86
+ //# sourceMappingURL=native-system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-system.js","sourceRoot":"","sources":["../../../src/adapters/state/native-system.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type InspectedState, type PreparedStateMigration, type PrivateStateCommandRunner, type ProtectedStateWorkspace, type StateBackendKind, type StateConfigurationProvider, type StateMigrationPlan, type StateNativeDriver, type StateNativeReview, type StateRecipe, type StateRecipeQualification } from '../../domain/repair/stateful.js';
2
+ export declare const implementedStateRecipeCombinations: readonly {
3
+ recipe: StateRecipe;
4
+ source: StateBackendKind;
5
+ destinations: readonly StateBackendKind[];
6
+ liveQualificationRequired: true;
7
+ }[];
8
+ export type { StateConfigurationAttestation, StateConfigurationProvider, StateRecipeQualification } from '../../domain/repair/stateful.js';
9
+ export declare class OpenTofuStateDriver implements StateNativeDriver {
10
+ private readonly options;
11
+ constructor(options: {
12
+ workspace: ProtectedStateWorkspace;
13
+ runner: PrivateStateCommandRunner;
14
+ configurations: StateConfigurationProvider;
15
+ qualification: StateRecipeQualification;
16
+ now?: () => number;
17
+ });
18
+ quiesce(): Promise<void>;
19
+ private withScratch;
20
+ private qualify;
21
+ private run;
22
+ private runQuiet;
23
+ private backendConfiguration;
24
+ private minimalRoot;
25
+ private materialize;
26
+ private copyState;
27
+ private verifyPlannedIdentities;
28
+ private rootPlan;
29
+ review(request: Parameters<StateNativeDriver['review']>[0]): Promise<StateNativeReview>;
30
+ private privateState;
31
+ prepare(plan: StateMigrationPlan, signal?: AbortSignal): Promise<PreparedStateMigration>;
32
+ verify(plan: StateMigrationPlan, current: Readonly<Record<string, InspectedState>>, signal?: AbortSignal): Promise<string>;
33
+ verifyDestinations(plan: StateMigrationPlan, current: Readonly<Record<string, InspectedState>>, signal?: AbortSignal): Promise<string>;
34
+ private verifyRoots;
35
+ }
@@ -0,0 +1,350 @@
1
+ import { lstat, mkdir } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { statefulRecipeVersion } from '../../domain/repair/stateful.js';
4
+ import { assertNoResourceChanges, inspectStateBytes, isStateDigest, stateAssert, stateDigest, stateObjectDigest, validateStateMappings, validateStatePlanBindings, verifyStateAccounting } from '../../domain/repair/stateful-invariants.js';
5
+ import { protectedStateScope } from './protected-workspace.js';
6
+ import { readPrivateNativeFile, writePrivateNativeFile } from './native-files.js';
7
+ export const implementedStateRecipeCombinations = ['local', 'azurerm'].flatMap((source) => [
8
+ { recipe: 'address-refactor', source, destinations: [source], liveQualificationRequired: true },
9
+ ...['local', 'azurerm'].map((destination) => ({
10
+ recipe: 'backend-relocation', source, destinations: [destination], liveQualificationRequired: true
11
+ })),
12
+ { recipe: 'state-partition', source, destinations: ['local', 'azurerm'], liveQualificationRequired: true }
13
+ ]);
14
+ export class OpenTofuStateDriver {
15
+ options;
16
+ constructor(options) {
17
+ this.options = options;
18
+ }
19
+ async quiesce() {
20
+ stateAssert(this.options.runner.quiesce, 'process-tree-termination-unproven');
21
+ await this.options.runner.quiesce();
22
+ }
23
+ async withScratch(context, action) {
24
+ return this.options.workspace.withScratch(context, async (directory) => {
25
+ try {
26
+ return await action(directory);
27
+ }
28
+ finally {
29
+ await this.quiesce();
30
+ }
31
+ });
32
+ }
33
+ async qualify(plan) {
34
+ stateAssert(plan.inspection.live, 'live-scope-required');
35
+ validateStateMappings(plan.intent, plan.inspection.states);
36
+ validateStatePlanBindings(plan.intent, plan.inspection.bindings);
37
+ const source = plan.inspection.bindings.find((binding) => binding.id === plan.intent.sourceBackendId);
38
+ stateAssert(source, 'mapping-incomplete');
39
+ stateAssert(this.options.qualification, 'unqualified-combination');
40
+ await this.options.qualification.assertQualified({
41
+ recipeVersion: statefulRecipeVersion, recipe: plan.intent.recipe, source: source.kind,
42
+ destinations: plan.intent.destinationBackendIds.map((id) => {
43
+ const target = plan.inspection.bindings.find((binding) => binding.id === id);
44
+ stateAssert(target, 'mapping-incomplete');
45
+ return target.kind;
46
+ }),
47
+ executableDigest: this.options.runner.identityDigest, hostId: plan.context.hostId
48
+ });
49
+ }
50
+ async run(cwd, args, operation, signal, stdin, allowed = [0]) {
51
+ const result = await this.options.runner.run({ cwd, args, operation, signal, ...(stdin ? { stdin } : {}) });
52
+ if (!allowed.includes(result.exitCode)) {
53
+ result.stdout.fill(0);
54
+ stateAssert(false, 'native-command-failed');
55
+ }
56
+ return result;
57
+ }
58
+ async runQuiet(cwd, args, operation, signal, stdin) {
59
+ const result = await this.run(cwd, args, operation, signal, stdin);
60
+ result.stdout.fill(0);
61
+ }
62
+ async backendConfiguration(directory, statePath) {
63
+ await writePrivateNativeFile(path.join(directory, 'liftoff-state-backend.tf.json'), JSON.stringify({
64
+ terraform: { backend: { local: { path: statePath } } }
65
+ }));
66
+ }
67
+ async minimalRoot(directory, statePath, signal) {
68
+ await mkdir(directory, { mode: 0o700 });
69
+ const mirror = path.join(directory, 'provider-mirror');
70
+ await mkdir(mirror, { mode: 0o700 });
71
+ await writePrivateNativeFile(path.join(directory, 'liftoff.private.tfrc'), `disable_checkpoint = true\nprovider_installation {\n filesystem_mirror {\n path = ${JSON.stringify(mirror)}\n }\n}\n`);
72
+ await this.backendConfiguration(directory, statePath);
73
+ await this.runQuiet(directory, ['init', '-input=false', '-no-color', '-get=false'], 'inspect', signal);
74
+ }
75
+ async materialize(reference, directory, context, signal) {
76
+ await mkdir(directory, { mode: 0o700 });
77
+ const proof = await this.options.configurations.materialize(reference, directory, context, signal);
78
+ stateAssert(proof?.stateFormat === 'opentofu-v4-json', 'unsupported-encryption');
79
+ stateAssert(proof.configurationRef === reference && isStateDigest(proof.configurationDigest)
80
+ && proof.artifactDigest === context.artifactDigest && proof.backendNeutral
81
+ && proof.providerRegistration === 'disabled' && proof.provisioners.length === 0
82
+ && proof.externalPrograms.length === 0 && proof.uninspectedDataSources.length === 0
83
+ && proof.unresolvedModules.length === 0 && proof.moduleDigests.every(isStateDigest)
84
+ && typeof proof.providerMirrorDirectory === 'string' && path.isAbsolute(proof.providerMirrorDirectory)
85
+ && !/[\x00-\x1f]/.test(proof.providerMirrorDirectory)
86
+ && proof.providers.length > 0 && proof.providers.every((provider) => /^registry\.(?:opentofu|terraform)\.org\/hashicorp\/azurerm$/.test(provider.source)
87
+ && /^\d+\.\d+\.\d+$/.test(provider.version) && isStateDigest(provider.binaryDigest)), 'unsafe-planning-contract');
88
+ stateAssert(new Set(proof.providers.map((provider) => provider.source)).size === proof.providers.length, 'unsafe-planning-contract');
89
+ await this.options.configurations.verifyMaterialized(reference, directory, proof, signal);
90
+ await writePrivateNativeFile(path.join(directory, 'liftoff.private.tfrc'), `disable_checkpoint = true\nprovider_installation {\n filesystem_mirror {\n path = ${JSON.stringify(proof.providerMirrorDirectory)}\n include = ${JSON.stringify(proof.providers.map((provider) => provider.source))}\n }\n}\n`);
91
+ return proof;
92
+ }
93
+ async copyState(state, destination, context) {
94
+ stateAssert(state.stateRef && state.snapshot.digest, 'artifact-integrity');
95
+ const bytes = await this.options.workspace.get(state.stateRef, 'state', protectedStateScope(context));
96
+ try {
97
+ stateAssert(stateDigest(bytes) === state.snapshot.digest, 'artifact-integrity');
98
+ await writePrivateNativeFile(destination, bytes, true);
99
+ }
100
+ finally {
101
+ bytes.fill(0);
102
+ }
103
+ }
104
+ verifyPlannedIdentities(plan, expected) {
105
+ const plannedValues = plan.planned_values;
106
+ stateAssert(plannedValues && typeof plannedValues === 'object', 'verification-incomplete');
107
+ const found = new Map();
108
+ const visit = (value) => {
109
+ stateAssert(value && typeof value === 'object', 'verification-incomplete');
110
+ const module = value;
111
+ stateAssert(module.resources === undefined || Array.isArray(module.resources), 'verification-incomplete');
112
+ for (const resource of module.resources ?? []) {
113
+ stateAssert(typeof resource.address === 'string' && typeof resource.values?.id === 'string' && !found.has(resource.address), 'verification-incomplete');
114
+ found.set(resource.address, stateDigest(resource.values.id));
115
+ }
116
+ stateAssert(module.child_modules === undefined || Array.isArray(module.child_modules), 'verification-incomplete');
117
+ for (const child of module.child_modules ?? [])
118
+ visit(child);
119
+ };
120
+ visit(plannedValues.root_module ?? {});
121
+ stateAssert(found.size === expected.length && expected.every((instance) => found.get(instance.address) === instance.identityDigest), 'resource-identity-changed');
122
+ }
123
+ async rootPlan(request) {
124
+ const attestation = await this.materialize(request.reference, request.directory, request.context, request.signal);
125
+ stateAssert(request.expectedConfigurationDigest === undefined || request.expectedConfigurationDigest === attestation.configurationDigest, 'configuration-changed');
126
+ await this.backendConfiguration(request.directory, request.statePath);
127
+ await this.runQuiet(request.directory, ['init', '-input=false', '-no-color', '-get=false', '-lockfile=readonly'], 'inspect', request.signal);
128
+ const saved = path.join(request.directory, 'reviewed.tfplan');
129
+ const result = await this.run(request.directory, [
130
+ 'plan', '-input=false', '-no-color', '-refresh=true', '-lock=true', '-lock-timeout=10s',
131
+ '-detailed-exitcode', `-out=${saved}`
132
+ ], request.operation, request.signal, undefined, [0, 2]);
133
+ result.stdout.fill(0);
134
+ const shown = await this.run(request.directory, ['show', '-json', saved], 'inspect', request.signal);
135
+ let parsed;
136
+ try {
137
+ parsed = JSON.parse(Buffer.from(shown.stdout).toString('utf8'));
138
+ }
139
+ catch {
140
+ stateAssert(false, 'verification-incomplete');
141
+ }
142
+ finally {
143
+ shown.stdout.fill(0);
144
+ }
145
+ stateAssert(typeof parsed.format_version === 'string' && /^1\.\d+$/.test(parsed.format_version), 'verification-incomplete');
146
+ assertNoResourceChanges(parsed, request.strict);
147
+ this.verifyPlannedIdentities(parsed, request.instances);
148
+ if (request.strict)
149
+ stateAssert(result.exitCode === 0, 'verification-incomplete');
150
+ await this.options.configurations.verifyMaterialized(request.reference, request.directory, attestation, request.signal);
151
+ const bytes = await readPrivateNativeFile(saved, 64 * 1024 * 1024);
152
+ let savedRef;
153
+ let savedDigest;
154
+ try {
155
+ const artifact = await this.options.workspace.put('plan', protectedStateScope(request.context), bytes);
156
+ savedRef = artifact.ref;
157
+ savedDigest = artifact.digest;
158
+ }
159
+ finally {
160
+ bytes.fill(0);
161
+ }
162
+ if (request.applyPrivateStateOnly) {
163
+ stateAssert(request.operation === 'transform', 'unsafe-planning-contract');
164
+ await this.runQuiet(request.directory, ['apply', '-input=false', '-no-color', saved], 'transform', request.signal);
165
+ }
166
+ return {
167
+ proofDigest: stateObjectDigest({
168
+ config: attestation.configurationDigest, plan: stateObjectDigest(parsed),
169
+ binary: this.options.runner.identityDigest, refresh: true
170
+ }),
171
+ savedRef, savedDigest, exitCode: result.exitCode, configurationDigest: attestation.configurationDigest
172
+ };
173
+ }
174
+ async review(request) {
175
+ await this.qualify(request);
176
+ return this.withScratch(request.context, async (directory) => {
177
+ const source = request.inspection.states.find((state) => state.snapshot.backendId === request.intent.sourceBackendId);
178
+ const sourcePath = path.join(directory, 'source.tfstate');
179
+ await this.copyState(source, sourcePath, request.context);
180
+ const contracts = [];
181
+ let index = 0;
182
+ for (const reference of Object.values(request.intent.targetConfigurationRefs)) {
183
+ contracts.push(await this.materialize(reference, path.join(directory, `inspect-target-${index++}`), request.context, request.signal));
184
+ }
185
+ stateAssert(stateObjectDigest(contracts.map((entry) => [entry.configurationRef, entry.configurationDigest]).sort()) === request.intent.targetConfigurationDigest, 'configuration-changed');
186
+ const sourceRoot = path.join(directory, 'source-plan');
187
+ const proof = await this.rootPlan({
188
+ reference: request.intent.sourceConfigurationRef, directory: sourceRoot, statePath: sourcePath,
189
+ context: request.context, instances: source.instances, strict: true, operation: 'inspect', signal: request.signal
190
+ });
191
+ // Preview validates native address syntax without moving even private state.
192
+ for (const mapping of request.intent.mappings) {
193
+ if (mapping.sourceAddress === mapping.destinationAddress || mapping.disposition === 'preserve')
194
+ continue;
195
+ await this.runQuiet(sourceRoot, [
196
+ 'state', 'mv', '-dry-run', '-lock=true', '-lock-timeout=10s', `-state=${sourcePath}`,
197
+ mapping.sourceAddress, mapping.destinationAddress
198
+ ], 'inspect', request.signal);
199
+ }
200
+ return {
201
+ configurationDigest: request.context.configurationDigest,
202
+ configurationDigests: Object.fromEntries([
203
+ ...contracts.map((contract) => [contract.configurationRef, contract.configurationDigest]),
204
+ [request.intent.sourceConfigurationRef, proof.configurationDigest]
205
+ ]),
206
+ contractDigest: stateObjectDigest({ contracts, binary: this.options.runner.identityDigest }),
207
+ savedPlanRefs: [proof.savedRef], savedPlanDigests: [proof.savedDigest]
208
+ };
209
+ });
210
+ }
211
+ async privateState(backendId, filename, original, context, purpose) {
212
+ const info = await lstat(filename).catch((error) => {
213
+ stateAssert(error.code === 'ENOENT', 'unsafe-path');
214
+ return null;
215
+ });
216
+ if (!info) {
217
+ const empty = inspectStateBytes({
218
+ ...original.snapshot, backendId, exists: false, version: null, etag: null, size: 0
219
+ }, null);
220
+ return { ...empty, stateRef: null };
221
+ }
222
+ stateAssert(info.isFile() && !info.isSymbolicLink() && info.nlink === 1, 'unsafe-path');
223
+ stateAssert(info.size > 0 && info.size <= 32 * 1024 * 1024, 'invalid-state');
224
+ const bytes = await readPrivateNativeFile(filename, 32 * 1024 * 1024);
225
+ try {
226
+ const inspected = inspectStateBytes({
227
+ ...original.snapshot, backendId, exists: true, size: bytes.byteLength,
228
+ observedAt: this.options.now?.() ?? Date.now()
229
+ }, bytes);
230
+ const saved = await this.options.workspace.put(purpose, protectedStateScope(context), bytes);
231
+ return { ...inspected, stateRef: saved.ref };
232
+ }
233
+ finally {
234
+ bytes.fill(0);
235
+ }
236
+ }
237
+ async prepare(plan, signal) {
238
+ await this.qualify({ context: plan.context, inspection: plan.inspection, intent: plan.intent, signal });
239
+ return this.withScratch(plan.context, async (directory) => {
240
+ const contracts = [];
241
+ let contractIndex = 0;
242
+ for (const reference of Object.values(plan.intent.targetConfigurationRefs)) {
243
+ contracts.push(await this.materialize(reference, path.join(directory, `recheck-target-${contractIndex++}`), plan.context, signal));
244
+ }
245
+ stateAssert(stateObjectDigest(contracts.map((entry) => [entry.configurationRef, entry.configurationDigest]).sort()) === plan.intent.targetConfigurationDigest
246
+ && stateObjectDigest({ contracts, binary: this.options.runner.identityDigest }) === plan.review.contractDigest, 'configuration-changed');
247
+ for (let index = 0; index < plan.review.savedPlanRefs.length; index++) {
248
+ const bytes = await this.options.workspace.get(plan.review.savedPlanRefs[index], 'plan', protectedStateScope(plan.context));
249
+ try {
250
+ stateAssert(stateDigest(bytes) === plan.review.savedPlanDigests[index], 'artifact-integrity');
251
+ }
252
+ finally {
253
+ bytes.fill(0);
254
+ }
255
+ }
256
+ const source = plan.inspection.states.find((state) => state.snapshot.backendId === plan.intent.sourceBackendId);
257
+ const filenames = Object.fromEntries(plan.inspection.states.map((state, index) => [state.snapshot.backendId, path.join(directory, `state-${index}.tfstate`)]));
258
+ const sourcePath = filenames[plan.intent.sourceBackendId];
259
+ await this.copyState(source, sourcePath, plan.context);
260
+ const nativeRoot = path.join(directory, 'native');
261
+ await this.minimalRoot(nativeRoot, sourcePath, signal);
262
+ if (plan.intent.recipe === 'backend-relocation') {
263
+ const destinationPath = filenames[plan.intent.destinationBackendIds[0]];
264
+ await this.backendConfiguration(nativeRoot, destinationPath);
265
+ await this.runQuiet(nativeRoot, [
266
+ 'init', '-migrate-state', '-input=true', '-no-color', '-get=false', '-lock-timeout=10s'
267
+ ], 'transform', signal, Buffer.from('yes\n'));
268
+ }
269
+ else {
270
+ for (const mapping of plan.intent.mappings) {
271
+ if (mapping.disposition === 'preserve'
272
+ || (mapping.destinationBackendId === plan.intent.sourceBackendId && mapping.sourceAddress === mapping.destinationAddress))
273
+ continue;
274
+ await this.runQuiet(nativeRoot, [
275
+ 'state', 'mv', '-lock=true', '-lock-timeout=10s', `-state=${sourcePath}`,
276
+ ...(mapping.destinationBackendId === plan.intent.sourceBackendId ? [] : [`-state-out=${filenames[mapping.destinationBackendId]}`]),
277
+ mapping.sourceAddress, mapping.destinationAddress
278
+ ], 'transform', signal);
279
+ }
280
+ }
281
+ const preliminary = {};
282
+ for (const state of plan.inspection.states) {
283
+ const id = state.snapshot.backendId;
284
+ if (plan.intent.recipe === 'backend-relocation' && id === plan.intent.sourceBackendId)
285
+ continue;
286
+ preliminary[id] = await this.privateState(id, filenames[id], state, plan.context, 'candidate');
287
+ }
288
+ verifyStateAccounting(plan.intent, source, preliminary, true);
289
+ const candidates = {};
290
+ const proofs = [];
291
+ let index = 0;
292
+ for (const [id, candidate] of Object.entries(preliminary)) {
293
+ if (candidate.instances.length === 0)
294
+ continue;
295
+ const reference = plan.intent.targetConfigurationRefs[id];
296
+ stateAssert(reference, 'mapping-incomplete');
297
+ await this.rootPlan({
298
+ reference, directory: path.join(directory, `target-prepare-${index}`), statePath: filenames[id],
299
+ context: plan.context, instances: candidate.instances, strict: false, operation: 'transform',
300
+ applyPrivateStateOnly: true, signal, expectedConfigurationDigest: plan.review.configurationDigests[reference]
301
+ });
302
+ const prepared = await this.privateState(id, filenames[id], candidate, plan.context, 'candidate');
303
+ const verified = await this.rootPlan({
304
+ reference, directory: path.join(directory, `target-verify-${index++}`), statePath: filenames[id],
305
+ context: plan.context, instances: prepared.instances, strict: true, operation: 'inspect', signal,
306
+ expectedConfigurationDigest: plan.review.configurationDigests[reference]
307
+ });
308
+ candidates[id] = prepared;
309
+ proofs.push(verified.proofDigest);
310
+ }
311
+ verifyStateAccounting(plan.intent, source, candidates, false);
312
+ return { candidates, verificationDigest: stateObjectDigest(proofs) };
313
+ });
314
+ }
315
+ async verify(plan, current, signal) {
316
+ await this.qualify({ context: plan.context, inspection: plan.inspection, intent: plan.intent, signal });
317
+ const source = plan.inspection.states.find((state) => state.snapshot.backendId === plan.intent.sourceBackendId);
318
+ verifyStateAccounting(plan.intent, source, current, false);
319
+ return this.verifyRoots(plan, current, signal);
320
+ }
321
+ async verifyDestinations(plan, current, signal) {
322
+ await this.qualify({ context: plan.context, inspection: plan.inspection, intent: plan.intent, signal });
323
+ const ids = new Set(plan.intent.destinationBackendIds);
324
+ stateAssert(Object.keys(current).length === ids.size && Object.keys(current).every((id) => ids.has(id)), 'mapping-incomplete');
325
+ const source = plan.inspection.states.find((state) => state.snapshot.backendId === plan.intent.sourceBackendId);
326
+ const mappings = plan.intent.mappings.filter((mapping) => ids.has(mapping.destinationBackendId));
327
+ verifyStateAccounting({ ...plan.intent, mappings }, source, current, false);
328
+ return this.verifyRoots(plan, current, signal);
329
+ }
330
+ async verifyRoots(plan, current, signal) {
331
+ return this.withScratch(plan.context, async (directory) => {
332
+ const proofs = [];
333
+ let index = 0;
334
+ for (const [id, state] of Object.entries(current)) {
335
+ if (!state.snapshot.exists || state.instances.length === 0)
336
+ continue;
337
+ const filename = path.join(directory, `verify-${index}.tfstate`);
338
+ await this.copyState(state, filename, plan.context);
339
+ const proof = await this.rootPlan({
340
+ reference: plan.intent.targetConfigurationRefs[id], directory: path.join(directory, `verify-root-${index++}`),
341
+ statePath: filename, context: plan.context, instances: state.instances, strict: true, operation: 'inspect', signal,
342
+ expectedConfigurationDigest: plan.review.configurationDigests[plan.intent.targetConfigurationRefs[id]]
343
+ });
344
+ proofs.push(proof.proofDigest);
345
+ }
346
+ return stateObjectDigest(proofs);
347
+ });
348
+ }
349
+ }
350
+ //# sourceMappingURL=opentofu.js.map