@mannyc1/ts-release 0.0.7 → 0.3.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 (695) hide show
  1. package/ARCHITECTURE.md +184 -92
  2. package/CHANGELOG.md +197 -0
  3. package/LICENSE +21 -0
  4. package/README.md +404 -327
  5. package/SPEC.md +257 -310
  6. package/apps/release-ts/README.md +39 -0
  7. package/apps/release-ts/src/cli/command.ts +164 -0
  8. package/apps/release-ts/src/cli/commands.ts +351 -0
  9. package/apps/release-ts/src/cli/main.ts +43 -0
  10. package/apps/release-ts/src/cli/node-main.ts +49 -0
  11. package/apps/ts-release-agents/LICENSE +21 -0
  12. package/apps/ts-release-agents/README.md +21 -0
  13. package/apps/ts-release-agents/evals/cases.json +11 -0
  14. package/apps/ts-release-agents/manifests/claude.json +5 -0
  15. package/apps/ts-release-agents/manifests/codex.json +5 -0
  16. package/apps/ts-release-agents/package.json +11 -0
  17. package/apps/ts-release-agents/skills/release/SKILL.md +48 -0
  18. package/apps/ts-release-agents/skills/release/references/configuration.md +18 -0
  19. package/apps/ts-release-agents/skills/release/references/recovery.md +10 -0
  20. package/apps/ts-release-agents/skills/release/references/staged-workflow.md +12 -0
  21. package/apps/ts-release-agents/skills/release/references/target-selection.md +13 -0
  22. package/apps/ts-release-agents/skills/release/references/verification.md +14 -0
  23. package/apps/ts-release-agents/src/build.ts +105 -0
  24. package/apps/ts-release-agents/src/check.ts +122 -0
  25. package/apps/ts-release-agents/src/install.ts +121 -0
  26. package/apps/ts-release-agents/test/contract.test.ts +56 -0
  27. package/apps/ts-release-agents/tsconfig.json +5 -0
  28. package/dist/api/api.d.ts +15 -0
  29. package/dist/api/api.d.ts.map +1 -0
  30. package/dist/api/api.js +244 -0
  31. package/dist/api/api.js.map +1 -0
  32. package/dist/api/errors.d.ts +39 -0
  33. package/dist/api/errors.d.ts.map +1 -0
  34. package/dist/api/errors.js +32 -0
  35. package/dist/api/errors.js.map +1 -0
  36. package/dist/api/input.d.ts +10 -0
  37. package/dist/api/input.d.ts.map +1 -0
  38. package/dist/api/input.js +73 -0
  39. package/dist/api/input.js.map +1 -0
  40. package/dist/api/runtime.d.ts +18 -0
  41. package/dist/api/runtime.d.ts.map +1 -0
  42. package/dist/api/runtime.js +7 -0
  43. package/dist/api/runtime.js.map +1 -0
  44. package/dist/api/types.d.ts +76 -0
  45. package/dist/api/types.d.ts.map +1 -0
  46. package/dist/api/types.js +17 -0
  47. package/dist/api/types.js.map +1 -0
  48. package/dist/bin/ts-release.js +39346 -0
  49. package/dist/capabilities/bun-targets.d.ts +3 -0
  50. package/dist/capabilities/bun-targets.d.ts.map +1 -0
  51. package/dist/capabilities/bun-targets.js +3 -0
  52. package/dist/capabilities/bun-targets.js.map +1 -0
  53. package/dist/capabilities/field-ownership.d.ts +17 -0
  54. package/dist/capabilities/field-ownership.d.ts.map +1 -0
  55. package/dist/capabilities/field-ownership.js +40 -0
  56. package/dist/capabilities/field-ownership.js.map +1 -0
  57. package/dist/capabilities/module.d.ts +91 -0
  58. package/dist/capabilities/module.d.ts.map +1 -0
  59. package/dist/capabilities/module.js +2 -0
  60. package/dist/capabilities/module.js.map +1 -0
  61. package/dist/capabilities/registry.d.ts +829 -0
  62. package/dist/capabilities/registry.d.ts.map +1 -0
  63. package/dist/capabilities/registry.js +291 -0
  64. package/dist/capabilities/registry.js.map +1 -0
  65. package/dist/config/config.d.ts +6 -0
  66. package/dist/config/config.d.ts.map +1 -0
  67. package/dist/config/config.js +42 -0
  68. package/dist/config/config.js.map +1 -0
  69. package/dist/correction/coordinator.d.ts +248 -0
  70. package/dist/correction/coordinator.d.ts.map +1 -0
  71. package/dist/correction/coordinator.js +274 -0
  72. package/dist/correction/coordinator.js.map +1 -0
  73. package/dist/correction/index.d.ts +3 -0
  74. package/dist/correction/index.d.ts.map +1 -0
  75. package/dist/correction/index.js +3 -0
  76. package/dist/correction/index.js.map +1 -0
  77. package/dist/correction/intent.d.ts +111 -0
  78. package/dist/correction/intent.d.ts.map +1 -0
  79. package/dist/correction/intent.js +146 -0
  80. package/dist/correction/intent.js.map +1 -0
  81. package/dist/drivers/archive.d.ts +9 -0
  82. package/dist/drivers/archive.d.ts.map +1 -0
  83. package/dist/drivers/archive.js +105 -0
  84. package/dist/drivers/archive.js.map +1 -0
  85. package/dist/drivers/contain.d.ts +6 -0
  86. package/dist/drivers/contain.d.ts.map +1 -0
  87. package/dist/drivers/contain.js +17 -0
  88. package/dist/drivers/contain.js.map +1 -0
  89. package/dist/drivers/environment.d.ts +4 -0
  90. package/dist/drivers/environment.d.ts.map +1 -0
  91. package/dist/drivers/environment.js +18 -0
  92. package/dist/drivers/environment.js.map +1 -0
  93. package/dist/drivers/errors.d.ts +9 -0
  94. package/dist/drivers/errors.d.ts.map +1 -0
  95. package/dist/drivers/errors.js +6 -0
  96. package/dist/drivers/errors.js.map +1 -0
  97. package/dist/drivers/glob.d.ts +2 -0
  98. package/dist/drivers/glob.d.ts.map +1 -0
  99. package/dist/drivers/glob.js +162 -0
  100. package/dist/drivers/glob.js.map +1 -0
  101. package/dist/drivers/process.d.ts +48 -0
  102. package/dist/drivers/process.d.ts.map +1 -0
  103. package/dist/drivers/process.js +257 -0
  104. package/dist/drivers/process.js.map +1 -0
  105. package/dist/drivers/python-wheel.d.ts +21 -0
  106. package/dist/drivers/python-wheel.d.ts.map +1 -0
  107. package/dist/drivers/python-wheel.js +109 -0
  108. package/dist/drivers/python-wheel.js.map +1 -0
  109. package/dist/drivers/redact.d.ts +4 -0
  110. package/dist/drivers/redact.d.ts.map +1 -0
  111. package/dist/drivers/redact.js +24 -0
  112. package/dist/drivers/redact.js.map +1 -0
  113. package/dist/drivers/seccomp-helper-source.d.ts +7 -0
  114. package/dist/drivers/seccomp-helper-source.d.ts.map +1 -0
  115. package/dist/drivers/seccomp-helper-source.js +121 -0
  116. package/dist/drivers/seccomp-helper-source.js.map +1 -0
  117. package/dist/drivers/utils.d.ts +4 -0
  118. package/dist/drivers/utils.d.ts.map +1 -0
  119. package/dist/drivers/utils.js +5 -0
  120. package/dist/drivers/utils.js.map +1 -0
  121. package/dist/drivers/workspace.d.ts +9 -0
  122. package/dist/drivers/workspace.d.ts.map +1 -0
  123. package/dist/drivers/workspace.js +53 -0
  124. package/dist/drivers/workspace.js.map +1 -0
  125. package/dist/extensions/provider-adapter.d.ts +48 -0
  126. package/dist/extensions/provider-adapter.d.ts.map +1 -0
  127. package/dist/extensions/provider-adapter.js +64 -0
  128. package/dist/extensions/provider-adapter.js.map +1 -0
  129. package/dist/host.d.ts +33 -0
  130. package/dist/host.d.ts.map +1 -0
  131. package/dist/host.js +20 -0
  132. package/dist/host.js.map +1 -0
  133. package/dist/index.d.ts +19 -1
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +12 -1
  136. package/dist/index.js.map +1 -1
  137. package/dist/model/artifact-collection.d.ts +84 -0
  138. package/dist/model/artifact-collection.d.ts.map +1 -0
  139. package/dist/model/artifact-collection.js +185 -0
  140. package/dist/model/artifact-collection.js.map +1 -0
  141. package/dist/model/authority.d.ts +89 -0
  142. package/dist/model/authority.d.ts.map +1 -0
  143. package/dist/model/authority.js +80 -0
  144. package/dist/model/authority.js.map +1 -0
  145. package/dist/model/bun-targets.d.ts +34 -0
  146. package/dist/model/bun-targets.d.ts.map +1 -0
  147. package/dist/model/bun-targets.js +17 -0
  148. package/dist/model/bun-targets.js.map +1 -0
  149. package/dist/model/canonical.d.ts +8 -0
  150. package/dist/model/canonical.d.ts.map +1 -0
  151. package/dist/model/canonical.js +205 -0
  152. package/dist/model/canonical.js.map +1 -0
  153. package/dist/model/catalog.d.ts +76 -0
  154. package/dist/model/catalog.d.ts.map +1 -0
  155. package/dist/model/catalog.js +174 -0
  156. package/dist/model/catalog.js.map +1 -0
  157. package/dist/model/digest.d.ts +53 -0
  158. package/dist/model/digest.d.ts.map +1 -0
  159. package/dist/model/digest.js +127 -0
  160. package/dist/model/digest.js.map +1 -0
  161. package/dist/model/errors.d.ts +14 -0
  162. package/dist/model/errors.d.ts.map +1 -0
  163. package/dist/model/errors.js +8 -0
  164. package/dist/model/errors.js.map +1 -0
  165. package/dist/model/primitives.d.ts +19 -0
  166. package/dist/model/primitives.d.ts.map +1 -0
  167. package/dist/model/primitives.js +18 -0
  168. package/dist/model/primitives.js.map +1 -0
  169. package/dist/model/pypi.d.ts +12 -0
  170. package/dist/model/pypi.d.ts.map +1 -0
  171. package/dist/model/pypi.js +20 -0
  172. package/dist/model/pypi.js.map +1 -0
  173. package/dist/model/python-distribution.d.ts +33 -0
  174. package/dist/model/python-distribution.d.ts.map +1 -0
  175. package/dist/model/python-distribution.js +367 -0
  176. package/dist/model/python-distribution.js.map +1 -0
  177. package/dist/model/secret-patterns.d.ts +2 -0
  178. package/dist/model/secret-patterns.d.ts.map +1 -0
  179. package/dist/model/secret-patterns.js +12 -0
  180. package/dist/model/secret-patterns.js.map +1 -0
  181. package/dist/operation-journal/authority.d.ts +3 -0
  182. package/dist/operation-journal/authority.d.ts.map +1 -0
  183. package/dist/operation-journal/authority.js +147 -0
  184. package/dist/operation-journal/authority.js.map +1 -0
  185. package/dist/operation-journal/aws/deadline.d.ts +12 -0
  186. package/dist/operation-journal/aws/deadline.d.ts.map +1 -0
  187. package/dist/operation-journal/aws/deadline.js +38 -0
  188. package/dist/operation-journal/aws/deadline.js.map +1 -0
  189. package/dist/operation-journal/aws/oidc.d.ts +27 -0
  190. package/dist/operation-journal/aws/oidc.d.ts.map +1 -0
  191. package/dist/operation-journal/aws/oidc.js +361 -0
  192. package/dist/operation-journal/aws/oidc.js.map +1 -0
  193. package/dist/operation-journal/aws/policy.d.ts +42 -0
  194. package/dist/operation-journal/aws/policy.d.ts.map +1 -0
  195. package/dist/operation-journal/aws/policy.js +404 -0
  196. package/dist/operation-journal/aws/policy.js.map +1 -0
  197. package/dist/operation-journal/aws/s3-boundary.d.ts +17 -0
  198. package/dist/operation-journal/aws/s3-boundary.d.ts.map +1 -0
  199. package/dist/operation-journal/aws/s3-boundary.js +417 -0
  200. package/dist/operation-journal/aws/s3-boundary.js.map +1 -0
  201. package/dist/operation-journal/aws.d.ts +11 -0
  202. package/dist/operation-journal/aws.d.ts.map +1 -0
  203. package/dist/operation-journal/aws.js +50 -0
  204. package/dist/operation-journal/aws.js.map +1 -0
  205. package/dist/operation-journal/canonical.d.ts +52 -0
  206. package/dist/operation-journal/canonical.d.ts.map +1 -0
  207. package/dist/operation-journal/canonical.js +282 -0
  208. package/dist/operation-journal/canonical.js.map +1 -0
  209. package/dist/operation-journal/model.d.ts +251 -0
  210. package/dist/operation-journal/model.d.ts.map +1 -0
  211. package/dist/operation-journal/model.js +56 -0
  212. package/dist/operation-journal/model.js.map +1 -0
  213. package/dist/operation-journal/reducer.d.ts +28 -0
  214. package/dist/operation-journal/reducer.d.ts.map +1 -0
  215. package/dist/operation-journal/reducer.js +73 -0
  216. package/dist/operation-journal/reducer.js.map +1 -0
  217. package/dist/operation-journal/s3.d.ts +7 -0
  218. package/dist/operation-journal/s3.d.ts.map +1 -0
  219. package/dist/operation-journal/s3.js +667 -0
  220. package/dist/operation-journal/s3.js.map +1 -0
  221. package/dist/operation-journal.d.ts +14 -0
  222. package/dist/operation-journal.d.ts.map +1 -0
  223. package/dist/operation-journal.js +12 -0
  224. package/dist/operation-journal.js.map +1 -0
  225. package/dist/platform/bun.d.ts +7 -0
  226. package/dist/platform/bun.d.ts.map +1 -0
  227. package/dist/platform/bun.js +15 -0
  228. package/dist/platform/bun.js.map +1 -0
  229. package/dist/platform/credentials.d.ts +32 -0
  230. package/dist/platform/credentials.d.ts.map +1 -0
  231. package/dist/platform/credentials.js +834 -0
  232. package/dist/platform/credentials.js.map +1 -0
  233. package/dist/platform/host-support.d.ts +2 -0
  234. package/dist/platform/host-support.d.ts.map +1 -0
  235. package/dist/platform/host-support.js +4 -0
  236. package/dist/platform/host-support.js.map +1 -0
  237. package/dist/platform/node.d.ts +7 -0
  238. package/dist/platform/node.d.ts.map +1 -0
  239. package/dist/platform/node.js +15 -0
  240. package/dist/platform/node.js.map +1 -0
  241. package/dist/platform/release-runtime.d.ts +11 -0
  242. package/dist/platform/release-runtime.d.ts.map +1 -0
  243. package/dist/platform/release-runtime.js +34 -0
  244. package/dist/platform/release-runtime.js.map +1 -0
  245. package/dist/platform/services.d.ts +15 -0
  246. package/dist/platform/services.d.ts.map +1 -0
  247. package/dist/platform/services.js +30 -0
  248. package/dist/platform/services.js.map +1 -0
  249. package/dist/platform/source-observer.d.ts +5 -0
  250. package/dist/platform/source-observer.d.ts.map +1 -0
  251. package/dist/platform/source-observer.js +159 -0
  252. package/dist/platform/source-observer.js.map +1 -0
  253. package/dist/provider-sdk.d.ts +14 -0
  254. package/dist/provider-sdk.d.ts.map +1 -0
  255. package/dist/provider-sdk.js +10 -0
  256. package/dist/provider-sdk.js.map +1 -0
  257. package/dist/publication/adapter.d.ts +212 -0
  258. package/dist/publication/adapter.d.ts.map +1 -0
  259. package/dist/publication/adapter.js +83 -0
  260. package/dist/publication/adapter.js.map +1 -0
  261. package/dist/publication/authority.d.ts +137 -0
  262. package/dist/publication/authority.d.ts.map +1 -0
  263. package/dist/publication/authority.js +233 -0
  264. package/dist/publication/authority.js.map +1 -0
  265. package/dist/publication/catalog-git.d.ts +37 -0
  266. package/dist/publication/catalog-git.d.ts.map +1 -0
  267. package/dist/publication/catalog-git.js +451 -0
  268. package/dist/publication/catalog-git.js.map +1 -0
  269. package/dist/publication/claim.d.ts +39 -0
  270. package/dist/publication/claim.d.ts.map +1 -0
  271. package/dist/publication/claim.js +31 -0
  272. package/dist/publication/claim.js.map +1 -0
  273. package/dist/publication/coordinator.d.ts +246 -0
  274. package/dist/publication/coordinator.d.ts.map +1 -0
  275. package/dist/publication/coordinator.js +370 -0
  276. package/dist/publication/coordinator.js.map +1 -0
  277. package/dist/publication/github.d.ts +36 -0
  278. package/dist/publication/github.d.ts.map +1 -0
  279. package/dist/publication/github.js +695 -0
  280. package/dist/publication/github.js.map +1 -0
  281. package/dist/publication/http.d.ts +69 -0
  282. package/dist/publication/http.d.ts.map +1 -0
  283. package/dist/publication/http.js +29 -0
  284. package/dist/publication/http.js.map +1 -0
  285. package/dist/publication/index.d.ts +5 -0
  286. package/dist/publication/index.d.ts.map +1 -0
  287. package/dist/publication/index.js +5 -0
  288. package/dist/publication/index.js.map +1 -0
  289. package/dist/publication/npm.d.ts +40 -0
  290. package/dist/publication/npm.d.ts.map +1 -0
  291. package/dist/publication/npm.js +359 -0
  292. package/dist/publication/npm.js.map +1 -0
  293. package/dist/publication/profiles.d.ts +136 -0
  294. package/dist/publication/profiles.d.ts.map +1 -0
  295. package/dist/publication/profiles.js +90 -0
  296. package/dist/publication/profiles.js.map +1 -0
  297. package/dist/publication/publisher.d.ts +82 -0
  298. package/dist/publication/publisher.d.ts.map +1 -0
  299. package/dist/publication/publisher.js +53 -0
  300. package/dist/publication/publisher.js.map +1 -0
  301. package/dist/publication/pypi.d.ts +45 -0
  302. package/dist/publication/pypi.d.ts.map +1 -0
  303. package/dist/publication/pypi.js +369 -0
  304. package/dist/publication/pypi.js.map +1 -0
  305. package/dist/publication/recovery.d.ts +663 -0
  306. package/dist/publication/recovery.d.ts.map +1 -0
  307. package/dist/publication/recovery.js +252 -0
  308. package/dist/publication/recovery.js.map +1 -0
  309. package/dist/publication/report.d.ts +1061 -0
  310. package/dist/publication/report.d.ts.map +1 -0
  311. package/dist/publication/report.js +441 -0
  312. package/dist/publication/report.js.map +1 -0
  313. package/dist/recipes/config.d.ts +296 -0
  314. package/dist/recipes/config.d.ts.map +1 -0
  315. package/dist/recipes/config.js +325 -0
  316. package/dist/recipes/config.js.map +1 -0
  317. package/dist/release/capabilities.d.ts +12 -0
  318. package/dist/release/capabilities.d.ts.map +1 -0
  319. package/dist/release/capabilities.js +395 -0
  320. package/dist/release/capabilities.js.map +1 -0
  321. package/dist/release/compiler.d.ts +5 -0
  322. package/dist/release/compiler.d.ts.map +1 -0
  323. package/dist/release/compiler.js +19 -0
  324. package/dist/release/compiler.js.map +1 -0
  325. package/dist/release/config.d.ts +5 -0
  326. package/dist/release/config.d.ts.map +1 -0
  327. package/dist/release/config.js +10 -0
  328. package/dist/release/config.js.map +1 -0
  329. package/dist/release/context.d.ts +96 -0
  330. package/dist/release/context.d.ts.map +1 -0
  331. package/dist/release/context.js +168 -0
  332. package/dist/release/context.js.map +1 -0
  333. package/dist/release/graph.d.ts +271 -0
  334. package/dist/release/graph.d.ts.map +1 -0
  335. package/dist/release/graph.js +766 -0
  336. package/dist/release/graph.js.map +1 -0
  337. package/dist/release/inspect.d.ts +88 -0
  338. package/dist/release/inspect.d.ts.map +1 -0
  339. package/dist/release/inspect.js +75 -0
  340. package/dist/release/inspect.js.map +1 -0
  341. package/dist/release/prepare.d.ts +24 -0
  342. package/dist/release/prepare.d.ts.map +1 -0
  343. package/dist/release/prepare.js +1115 -0
  344. package/dist/release/prepare.js.map +1 -0
  345. package/dist/release/prepared-ref.d.ts +60 -0
  346. package/dist/release/prepared-ref.d.ts.map +1 -0
  347. package/dist/release/prepared-ref.js +131 -0
  348. package/dist/release/prepared-ref.js.map +1 -0
  349. package/dist/release/prepared-store.d.ts +90 -0
  350. package/dist/release/prepared-store.d.ts.map +1 -0
  351. package/dist/release/prepared-store.js +339 -0
  352. package/dist/release/prepared-store.js.map +1 -0
  353. package/dist/release/prepared.d.ts +172 -0
  354. package/dist/release/prepared.d.ts.map +1 -0
  355. package/dist/release/prepared.js +268 -0
  356. package/dist/release/prepared.js.map +1 -0
  357. package/dist/release/staging.d.ts +31 -0
  358. package/dist/release/staging.d.ts.map +1 -0
  359. package/dist/release/staging.js +218 -0
  360. package/dist/release/staging.js.map +1 -0
  361. package/dist/resolve/authored.d.ts +53 -0
  362. package/dist/resolve/authored.d.ts.map +1 -0
  363. package/dist/resolve/authored.js +55 -0
  364. package/dist/resolve/authored.js.map +1 -0
  365. package/dist/resolve/encode.d.ts +3 -0
  366. package/dist/resolve/encode.d.ts.map +1 -0
  367. package/dist/resolve/encode.js +21 -0
  368. package/dist/resolve/encode.js.map +1 -0
  369. package/dist/resolve/errors.d.ts +7 -0
  370. package/dist/resolve/errors.d.ts.map +1 -0
  371. package/dist/resolve/errors.js +17 -0
  372. package/dist/resolve/errors.js.map +1 -0
  373. package/dist/resolve/facts.d.ts +12 -0
  374. package/dist/resolve/facts.d.ts.map +1 -0
  375. package/dist/resolve/facts.js +18 -0
  376. package/dist/resolve/facts.js.map +1 -0
  377. package/dist/resolve/resolve.d.ts +10 -0
  378. package/dist/resolve/resolve.d.ts.map +1 -0
  379. package/dist/resolve/resolve.js +242 -0
  380. package/dist/resolve/resolve.js.map +1 -0
  381. package/dist/store.d.ts +11 -0
  382. package/dist/store.d.ts.map +1 -0
  383. package/dist/store.js +9 -0
  384. package/dist/store.js.map +1 -0
  385. package/examples/README.md +20 -30
  386. package/examples/github-release/release.config.json +11 -18
  387. package/examples/homebrew-tap/README.md +11 -0
  388. package/examples/homebrew-tap/release.config.json +40 -28
  389. package/examples/multi-target/release.config.json +28 -53
  390. package/examples/npm-first-publish/release.config.json +23 -25
  391. package/examples/npm-only/release.config.json +22 -30
  392. package/examples/portable-cli/README.md +17 -0
  393. package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-arm64 +1 -0
  394. package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-x64 +1 -0
  395. package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-arm64 +1 -0
  396. package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-x64 +1 -0
  397. package/examples/portable-cli/artifacts/portable-example-0.1.0-windows-x64.exe +1 -0
  398. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_10_15_x86_64.whl +1 -0
  399. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_11_0_arm64.whl +1 -0
  400. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_aarch64.whl +1 -0
  401. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_x86_64.whl +1 -0
  402. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-win_amd64.whl +1 -0
  403. package/examples/portable-cli/package.json +9 -0
  404. package/examples/portable-cli/release.config.json +53 -0
  405. package/examples/portable-cli/src/cli.ts +3 -0
  406. package/examples/pypi-registry/README.md +8 -0
  407. package/examples/scoop-bucket/README.md +10 -0
  408. package/examples/scoop-bucket/release.config.json +40 -30
  409. package/package.json +73 -154
  410. package/src/api/api.ts +365 -0
  411. package/src/api/errors.ts +36 -0
  412. package/src/api/input.ts +92 -0
  413. package/src/api/runtime.ts +14 -0
  414. package/src/api/types.ts +103 -0
  415. package/src/capabilities/bun-targets.ts +2 -0
  416. package/src/capabilities/field-ownership.ts +60 -0
  417. package/src/capabilities/module.ts +158 -0
  418. package/src/capabilities/registry.ts +333 -0
  419. package/src/config/config.ts +48 -0
  420. package/src/correction/coordinator.ts +336 -0
  421. package/src/correction/index.ts +2 -0
  422. package/src/correction/intent.ts +172 -0
  423. package/src/drivers/archive.ts +111 -0
  424. package/src/drivers/contain.ts +20 -0
  425. package/src/drivers/environment.ts +28 -0
  426. package/src/drivers/errors.ts +6 -0
  427. package/src/drivers/glob.ts +137 -0
  428. package/src/drivers/process.ts +339 -0
  429. package/src/drivers/python-wheel.ts +145 -0
  430. package/src/drivers/redact.ts +31 -0
  431. package/src/drivers/seccomp-helper-source.ts +121 -0
  432. package/src/drivers/utils.ts +10 -0
  433. package/src/drivers/workspace.ts +46 -0
  434. package/src/extensions/provider-adapter.ts +99 -0
  435. package/src/host.ts +140 -0
  436. package/src/index.ts +64 -0
  437. package/src/model/artifact-collection.ts +237 -0
  438. package/src/model/authority.ts +116 -0
  439. package/src/model/bun-targets.ts +34 -0
  440. package/src/model/canonical.ts +205 -0
  441. package/src/model/catalog.ts +220 -0
  442. package/src/model/digest.ts +172 -0
  443. package/src/model/errors.ts +6 -0
  444. package/src/model/primitives.ts +37 -0
  445. package/src/model/pypi.ts +30 -0
  446. package/src/model/python-distribution.ts +360 -0
  447. package/src/model/secret-patterns.ts +11 -0
  448. package/src/operation-journal/authority.ts +162 -0
  449. package/src/operation-journal/aws/deadline.ts +41 -0
  450. package/src/operation-journal/aws/oidc.ts +439 -0
  451. package/src/operation-journal/aws/policy.ts +491 -0
  452. package/src/operation-journal/aws/s3-boundary.ts +562 -0
  453. package/src/operation-journal/aws.ts +60 -0
  454. package/src/operation-journal/canonical.ts +373 -0
  455. package/src/operation-journal/model.ts +301 -0
  456. package/src/operation-journal/reducer.ts +112 -0
  457. package/src/operation-journal/s3.ts +884 -0
  458. package/src/operation-journal.ts +51 -0
  459. package/src/platform/bun.ts +38 -0
  460. package/src/platform/credentials.ts +1151 -0
  461. package/src/platform/host-support.ts +4 -0
  462. package/src/platform/node.ts +38 -0
  463. package/src/platform/release-runtime.ts +47 -0
  464. package/src/platform/services.ts +57 -0
  465. package/src/platform/source-observer.ts +193 -0
  466. package/src/provider-sdk.ts +48 -0
  467. package/src/publication/adapter.ts +132 -0
  468. package/src/publication/authority.ts +397 -0
  469. package/src/publication/catalog-git.ts +603 -0
  470. package/src/publication/claim.ts +51 -0
  471. package/src/publication/coordinator.ts +578 -0
  472. package/src/publication/github.ts +1022 -0
  473. package/src/publication/http.ts +101 -0
  474. package/src/publication/index.ts +4 -0
  475. package/src/publication/npm.ts +525 -0
  476. package/src/publication/profiles.ts +94 -0
  477. package/src/publication/publisher.ts +130 -0
  478. package/src/publication/pypi.ts +463 -0
  479. package/src/publication/recovery.ts +349 -0
  480. package/src/publication/report.ts +628 -0
  481. package/src/recipes/config.ts +395 -0
  482. package/src/release/capabilities.ts +460 -0
  483. package/src/release/compiler.ts +28 -0
  484. package/src/release/config.ts +12 -0
  485. package/src/release/context.ts +223 -0
  486. package/src/release/graph.ts +866 -0
  487. package/src/release/inspect.ts +83 -0
  488. package/src/release/prepare.ts +1329 -0
  489. package/src/release/prepared-ref.ts +193 -0
  490. package/src/release/prepared-store.ts +378 -0
  491. package/src/release/prepared.ts +299 -0
  492. package/src/release/staging.ts +257 -0
  493. package/src/resolve/authored.ts +64 -0
  494. package/src/resolve/encode.ts +22 -0
  495. package/src/resolve/errors.ts +15 -0
  496. package/src/resolve/facts.ts +18 -0
  497. package/src/resolve/resolve.ts +328 -0
  498. package/src/store.ts +28 -0
  499. package/templates/README.md +55 -72
  500. package/templates/bun-cli-github/README.md +7 -9
  501. package/templates/bun-cli-github/release.config.json +35 -73
  502. package/templates/github-actions/release.yml +74 -0
  503. package/templates/github-actions/reviewed-release.yml +115 -0
  504. package/templates/multi-target-homebrew/README.md +10 -0
  505. package/templates/multi-target-homebrew/release.config.json +43 -60
  506. package/templates/multi-target-scoop/README.md +10 -0
  507. package/templates/multi-target-scoop/release.config.json +43 -62
  508. package/templates/npm-github/release.config.json +25 -38
  509. package/templates/npm-github/reviewed-release.config.json +37 -0
  510. package/templates/npm-only/README.md +10 -0
  511. package/templates/npm-only/release.config.json +15 -30
  512. package/templates/portable-cli/README.md +13 -0
  513. package/templates/portable-cli/release.config.json +53 -0
  514. package/dist/artifacts/adapter.d.ts +0 -39
  515. package/dist/artifacts/adapter.d.ts.map +0 -1
  516. package/dist/artifacts/adapter.js +0 -23
  517. package/dist/artifacts/adapter.js.map +0 -1
  518. package/dist/artifacts/registry.d.ts +0 -21
  519. package/dist/artifacts/registry.d.ts.map +0 -1
  520. package/dist/artifacts/registry.js +0 -21
  521. package/dist/artifacts/registry.js.map +0 -1
  522. package/dist/config/errors.d.ts +0 -24
  523. package/dist/config/errors.d.ts.map +0 -1
  524. package/dist/config/errors.js +0 -19
  525. package/dist/config/errors.js.map +0 -1
  526. package/dist/config/load.d.ts +0 -9
  527. package/dist/config/load.d.ts.map +0 -1
  528. package/dist/config/load.js +0 -29
  529. package/dist/config/load.js.map +0 -1
  530. package/dist/config/schema.d.ts +0 -12
  531. package/dist/config/schema.d.ts.map +0 -1
  532. package/dist/config/schema.js +0 -19
  533. package/dist/config/schema.js.map +0 -1
  534. package/dist/domain/artifact.d.ts +0 -118
  535. package/dist/domain/artifact.d.ts.map +0 -1
  536. package/dist/domain/artifact.js +0 -197
  537. package/dist/domain/artifact.js.map +0 -1
  538. package/dist/domain/evidence.d.ts +0 -59
  539. package/dist/domain/evidence.d.ts.map +0 -1
  540. package/dist/domain/evidence.js +0 -51
  541. package/dist/domain/evidence.js.map +0 -1
  542. package/dist/domain/operation.d.ts +0 -143
  543. package/dist/domain/operation.d.ts.map +0 -1
  544. package/dist/domain/operation.js +0 -198
  545. package/dist/domain/operation.js.map +0 -1
  546. package/dist/domain/release.d.ts +0 -93
  547. package/dist/domain/release.d.ts.map +0 -1
  548. package/dist/domain/release.js +0 -82
  549. package/dist/domain/release.js.map +0 -1
  550. package/dist/domain/remote-state.d.ts +0 -58
  551. package/dist/domain/remote-state.d.ts.map +0 -1
  552. package/dist/domain/remote-state.js +0 -55
  553. package/dist/domain/remote-state.js.map +0 -1
  554. package/dist/domain/target.d.ts +0 -148
  555. package/dist/domain/target.d.ts.map +0 -1
  556. package/dist/domain/target.js +0 -151
  557. package/dist/domain/target.js.map +0 -1
  558. package/dist/host/host.d.ts +0 -32
  559. package/dist/host/host.d.ts.map +0 -1
  560. package/dist/host/host.js +0 -24
  561. package/dist/host/host.js.map +0 -1
  562. package/dist/host/http-live.d.ts +0 -6
  563. package/dist/host/http-live.d.ts.map +0 -1
  564. package/dist/host/http-live.js +0 -86
  565. package/dist/host/http-live.js.map +0 -1
  566. package/dist/host/http.d.ts +0 -43
  567. package/dist/host/http.d.ts.map +0 -1
  568. package/dist/host/http.js +0 -59
  569. package/dist/host/http.js.map +0 -1
  570. package/dist/host/platform.d.ts +0 -10
  571. package/dist/host/platform.d.ts.map +0 -1
  572. package/dist/host/platform.js +0 -114
  573. package/dist/host/platform.js.map +0 -1
  574. package/dist/host/test.d.ts +0 -23
  575. package/dist/host/test.d.ts.map +0 -1
  576. package/dist/host/test.js +0 -222
  577. package/dist/host/test.js.map +0 -1
  578. package/dist/internal/workspace-path.d.ts +0 -15
  579. package/dist/internal/workspace-path.d.ts.map +0 -1
  580. package/dist/internal/workspace-path.js +0 -36
  581. package/dist/internal/workspace-path.js.map +0 -1
  582. package/dist/planner/artifact-inventory.d.ts +0 -9
  583. package/dist/planner/artifact-inventory.d.ts.map +0 -1
  584. package/dist/planner/artifact-inventory.js +0 -86
  585. package/dist/planner/artifact-inventory.js.map +0 -1
  586. package/dist/planner/create-release-plan.d.ts +0 -5
  587. package/dist/planner/create-release-plan.d.ts.map +0 -1
  588. package/dist/planner/create-release-plan.js +0 -25
  589. package/dist/planner/create-release-plan.js.map +0 -1
  590. package/dist/planner/errors.d.ts +0 -67
  591. package/dist/planner/errors.d.ts.map +0 -1
  592. package/dist/planner/errors.js +0 -58
  593. package/dist/planner/errors.js.map +0 -1
  594. package/dist/planner/evidence-recorder.d.ts +0 -28
  595. package/dist/planner/evidence-recorder.d.ts.map +0 -1
  596. package/dist/planner/evidence-recorder.js +0 -362
  597. package/dist/planner/evidence-recorder.js.map +0 -1
  598. package/dist/planner/executor.d.ts +0 -58
  599. package/dist/planner/executor.d.ts.map +0 -1
  600. package/dist/planner/executor.js +0 -147
  601. package/dist/planner/executor.js.map +0 -1
  602. package/dist/planner/normalize-release.d.ts +0 -19
  603. package/dist/planner/normalize-release.d.ts.map +0 -1
  604. package/dist/planner/normalize-release.js +0 -342
  605. package/dist/planner/normalize-release.js.map +0 -1
  606. package/dist/planner/reconcile.d.ts +0 -17
  607. package/dist/planner/reconcile.d.ts.map +0 -1
  608. package/dist/planner/reconcile.js +0 -259
  609. package/dist/planner/reconcile.js.map +0 -1
  610. package/dist/planner/render-plan.d.ts +0 -15
  611. package/dist/planner/render-plan.d.ts.map +0 -1
  612. package/dist/planner/render-plan.js +0 -231
  613. package/dist/planner/render-plan.js.map +0 -1
  614. package/dist/targets/adapter-helpers.d.ts +0 -79
  615. package/dist/targets/adapter-helpers.d.ts.map +0 -1
  616. package/dist/targets/adapter-helpers.js +0 -194
  617. package/dist/targets/adapter-helpers.js.map +0 -1
  618. package/dist/targets/adapter.d.ts +0 -17
  619. package/dist/targets/adapter.d.ts.map +0 -1
  620. package/dist/targets/adapter.js +0 -2
  621. package/dist/targets/adapter.js.map +0 -1
  622. package/dist/targets/github-release.d.ts +0 -25
  623. package/dist/targets/github-release.d.ts.map +0 -1
  624. package/dist/targets/github-release.js +0 -82
  625. package/dist/targets/github-release.js.map +0 -1
  626. package/dist/targets/github.d.ts +0 -11
  627. package/dist/targets/github.d.ts.map +0 -1
  628. package/dist/targets/github.js +0 -117
  629. package/dist/targets/github.js.map +0 -1
  630. package/dist/targets/homebrew.d.ts +0 -11
  631. package/dist/targets/homebrew.d.ts.map +0 -1
  632. package/dist/targets/homebrew.js +0 -210
  633. package/dist/targets/homebrew.js.map +0 -1
  634. package/dist/targets/live.d.ts +0 -5
  635. package/dist/targets/live.d.ts.map +0 -1
  636. package/dist/targets/live.js +0 -50
  637. package/dist/targets/live.js.map +0 -1
  638. package/dist/targets/npm.d.ts +0 -10
  639. package/dist/targets/npm.d.ts.map +0 -1
  640. package/dist/targets/npm.js +0 -112
  641. package/dist/targets/npm.js.map +0 -1
  642. package/dist/targets/pypi.d.ts +0 -11
  643. package/dist/targets/pypi.d.ts.map +0 -1
  644. package/dist/targets/pypi.js +0 -141
  645. package/dist/targets/pypi.js.map +0 -1
  646. package/dist/targets/registry.d.ts +0 -25
  647. package/dist/targets/registry.d.ts.map +0 -1
  648. package/dist/targets/registry.js +0 -34
  649. package/dist/targets/registry.js.map +0 -1
  650. package/dist/targets/scoop.d.ts +0 -11
  651. package/dist/targets/scoop.d.ts.map +0 -1
  652. package/dist/targets/scoop.js +0 -88
  653. package/dist/targets/scoop.js.map +0 -1
  654. package/dist/types/effect-internal.d.ts +0 -5
  655. package/dist/types/effect-internal.d.ts.map +0 -1
  656. package/dist/types/effect-internal.js +0 -2
  657. package/dist/types/effect-internal.js.map +0 -1
  658. package/dist/workflows/config.d.ts +0 -202
  659. package/dist/workflows/config.d.ts.map +0 -1
  660. package/dist/workflows/config.js +0 -420
  661. package/dist/workflows/config.js.map +0 -1
  662. package/dist/workflows/diagnostics.d.ts +0 -62
  663. package/dist/workflows/diagnostics.d.ts.map +0 -1
  664. package/dist/workflows/diagnostics.js +0 -530
  665. package/dist/workflows/diagnostics.js.map +0 -1
  666. package/dist/workflows/distribution.d.ts +0 -25
  667. package/dist/workflows/distribution.d.ts.map +0 -1
  668. package/dist/workflows/distribution.js +0 -24
  669. package/dist/workflows/distribution.js.map +0 -1
  670. package/dist/workflows/evidence.d.ts +0 -17
  671. package/dist/workflows/evidence.d.ts.map +0 -1
  672. package/dist/workflows/evidence.js +0 -32
  673. package/dist/workflows/evidence.js.map +0 -1
  674. package/dist/workflows/index.d.ts +0 -8
  675. package/dist/workflows/index.d.ts.map +0 -1
  676. package/dist/workflows/index.js +0 -7
  677. package/dist/workflows/index.js.map +0 -1
  678. package/dist/workflows/init.d.ts +0 -84
  679. package/dist/workflows/init.d.ts.map +0 -1
  680. package/dist/workflows/init.js +0 -487
  681. package/dist/workflows/init.js.map +0 -1
  682. package/dist/workflows/live.d.ts +0 -9
  683. package/dist/workflows/live.d.ts.map +0 -1
  684. package/dist/workflows/live.js +0 -7
  685. package/dist/workflows/live.js.map +0 -1
  686. package/dist/workflows/options.d.ts +0 -30
  687. package/dist/workflows/options.d.ts.map +0 -1
  688. package/dist/workflows/options.js +0 -16
  689. package/dist/workflows/options.js.map +0 -1
  690. package/examples/non-strict-skips/artifacts/release-example-skips-0.1.0.tgz +0 -1
  691. package/examples/non-strict-skips/release.config.json +0 -31
  692. package/examples/pypi-registry/release.config.json +0 -31
  693. package/templates/github-actions/plan-and-approved-execute.yml +0 -58
  694. package/templates/github-actions/plan-only.yml +0 -33
  695. package/templates/github-actions/trusted-publishing.yml +0 -61
@@ -0,0 +1,667 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import * as Effect from "effect/Effect";
3
+ import { encodeCanonicalJson } from "../model/canonical.js";
4
+ import { decodeJournalEvent, decodeJournalHead, encodeJournalEvent, encodeJournalHead, eventDigest, isCanonicalS3VersionId, journalEventKey, journalHeadKey, journalNamespace, journalRecordFromEvent, makeCanonicalJournalRecord, objectChecksum, validateJournalOperation, validateJournalWorkflow, validateTransactionId } from "./canonical.js";
5
+ import { validateS3JournalAuthority } from "./authority.js";
6
+ import { JournalAuthorityMismatch, JournalConflict, JournalInputError, JournalIntegrityError, JournalStorageOutcomeUnknown, JournalStorageUnavailable, JournalTransitionError } from "./model.js";
7
+ import { admitJournalTransition, makeJournalEvent, makeJournalHead, reduceJournalEvents } from "./reducer.js";
8
+ const pureInput = (evaluate) => Effect.try({
9
+ try: evaluate,
10
+ catch: (cause) => cause instanceof JournalInputError
11
+ ? cause
12
+ : JournalInputError.make({ reason: "Journal input validation failed." })
13
+ });
14
+ const pureIntegrity = (evaluate) => Effect.try({
15
+ try: evaluate,
16
+ catch: (cause) => cause instanceof JournalIntegrityError
17
+ ? cause
18
+ : JournalIntegrityError.make({
19
+ reason: cause instanceof JournalInputError || cause instanceof JournalTransitionError
20
+ ? cause.reason
21
+ : "Journal canonical validation failed."
22
+ })
23
+ });
24
+ const pureTransition = (evaluate) => Effect.try({
25
+ try: evaluate,
26
+ catch: (cause) => cause instanceof JournalTransitionError
27
+ ? cause
28
+ : JournalTransitionError.make({ reason: "Journal transition validation failed." })
29
+ });
30
+ const safeReason = (error) => `S3 journal ${error.operation} boundary failed with ${error.commitment} commitment.`;
31
+ const readBoundary = (effect) => effect.pipe(Effect.mapError((error) => JournalStorageUnavailable.make({ reason: safeReason(error) })));
32
+ const postMutationRead = (effect) => effect.pipe(Effect.mapError((error) => JournalStorageOutcomeUnknown.make({ reason: safeReason(error) })));
33
+ const sameBytes = (left, right) => left.length === right.length && left.every((byte, index) => byte === right[index]);
34
+ const objectIdentity = (key, versionId) => `${key}\u0000${versionId}`;
35
+ const canonicalAuthority = (authority) => encodeCanonicalJson(authority);
36
+ const observeAuthority = (expected, client) => Effect.gen(function* () {
37
+ yield* Effect.try({
38
+ try: () => validateS3JournalAuthority(expected),
39
+ catch: (cause) => cause instanceof JournalAuthorityMismatch
40
+ ? cause
41
+ : JournalAuthorityMismatch.make({ reason: "Expected journal authority is malformed." })
42
+ });
43
+ const observed = yield* readBoundary(client.observeAuthority());
44
+ yield* Effect.try({
45
+ try: () => validateS3JournalAuthority(observed),
46
+ catch: (cause) => cause instanceof JournalAuthorityMismatch
47
+ ? cause
48
+ : JournalAuthorityMismatch.make({ reason: "Observed journal authority is malformed." })
49
+ });
50
+ if (canonicalAuthority(observed) !== canonicalAuthority(expected)) {
51
+ return yield* JournalAuthorityMismatch.make({ reason: "Observed journal authority drifted from the exact expected identity and policy." });
52
+ }
53
+ return observed;
54
+ });
55
+ const minimumTenYearRetentionMilliseconds = 10 * 365 * 24 * 60 * 60 * 1_000;
56
+ const validateRetainedObject = (object, expectedKey, expectedVersionId, expectedEtag) => {
57
+ if (object.key !== expectedKey || (expectedVersionId !== undefined && object.versionId !== expectedVersionId) ||
58
+ (expectedEtag !== undefined && object.etag !== expectedEtag)) {
59
+ throw JournalIntegrityError.make({ reason: "Journal object identity disagrees with its exact version listing." });
60
+ }
61
+ if (!isCanonicalS3VersionId(object.versionId) || !/^"[!#-~]{1,1024}"$/u.test(object.etag)) {
62
+ throw JournalIntegrityError.make({ reason: "Journal object version or ETag is not canonical." });
63
+ }
64
+ if (!/^sha256:[a-f0-9]{64}$/u.test(object.checksumSha256) ||
65
+ object.checksumSha256 !== objectChecksum(object.bytes)) {
66
+ throw JournalIntegrityError.make({ reason: "Journal object checksum does not match its exact bytes." });
67
+ }
68
+ const modified = new Date(object.lastModified);
69
+ const retained = new Date(object.retainUntil);
70
+ if (Number.isNaN(modified.getTime()) || modified.toISOString() !== object.lastModified ||
71
+ Number.isNaN(retained.getTime()) || retained.toISOString() !== object.retainUntil ||
72
+ object.retentionMode !== "COMPLIANCE" ||
73
+ retained.getTime() - modified.getTime() < minimumTenYearRetentionMilliseconds) {
74
+ throw JournalIntegrityError.make({ reason: "Journal object is not retained in COMPLIANCE mode for the required ten years." });
75
+ }
76
+ };
77
+ function listOperation(authority, operation, maximum, client, afterMutation) {
78
+ const request = {
79
+ bucketName: authority.bucketName,
80
+ expectedBucketOwner: authority.expectedBucketOwner,
81
+ region: authority.region,
82
+ prefix: journalNamespace(operation),
83
+ maximum
84
+ };
85
+ return afterMutation
86
+ ? postMutationRead(client.listNamespace(request))
87
+ : readBoundary(client.listNamespace(request));
88
+ }
89
+ function getObject(authority, key, versionId, client, afterMutation) {
90
+ const request = {
91
+ bucketName: authority.bucketName,
92
+ expectedBucketOwner: authority.expectedBucketOwner,
93
+ region: authority.region,
94
+ key,
95
+ versionId
96
+ };
97
+ return afterMutation
98
+ ? postMutationRead(client.getObjectVersion(request))
99
+ : readBoundary(client.getObjectVersion(request));
100
+ }
101
+ const loadJournal = (input) => Effect.gen(function* () {
102
+ const operation = yield* pureInput(() => validateJournalOperation(input.operation));
103
+ const authority = input.afterMutation === true
104
+ ? yield* observeAuthority(input.expectedAuthority, input.client).pipe(Effect.mapError((error) => error instanceof JournalStorageUnavailable
105
+ ? JournalStorageOutcomeUnknown.make({ reason: error.reason })
106
+ : error))
107
+ : yield* observeAuthority(input.expectedAuthority, input.client);
108
+ if (operation.releasePoint !== authority.oidc.sha) {
109
+ return yield* JournalAuthorityMismatch.make({
110
+ reason: "Journal release point does not equal the exact caller SHA."
111
+ });
112
+ }
113
+ const listing = input.afterMutation === true
114
+ ? yield* listOperation(authority, operation, input.maximum, input.client, true)
115
+ : yield* listOperation(authority, operation, input.maximum, input.client, false);
116
+ if (listing.truncated || listing.versions.length > input.maximum) {
117
+ if (input.afterMutation === true) {
118
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Journal namespace exceeded the bounded authoritative re-read." });
119
+ }
120
+ return yield* JournalIntegrityError.make({ reason: "Journal namespace exceeded the bounded authoritative read." });
121
+ }
122
+ if (listing.deleteMarkers.length > 0) {
123
+ return yield* JournalIntegrityError.make({ reason: "Journal namespace contains a forbidden delete marker." });
124
+ }
125
+ const namespace = journalNamespace(operation);
126
+ const headKey = journalHeadKey(operation);
127
+ const eventPattern = new RegExp(`^${namespace.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}events/[0-9]{8}/[a-f0-9-]{36}\\.bin$`, "u");
128
+ const metadataIds = new Set();
129
+ const latestByKey = new Map();
130
+ for (const metadata of listing.versions) {
131
+ if (metadata.key !== headKey && !eventPattern.test(metadata.key)) {
132
+ return yield* JournalIntegrityError.make({ reason: "Journal namespace contains an unadmitted object key." });
133
+ }
134
+ const identity = objectIdentity(metadata.key, metadata.versionId);
135
+ if (metadataIds.has(identity)) {
136
+ return yield* JournalIntegrityError.make({ reason: "Journal version listing repeats an object version." });
137
+ }
138
+ metadataIds.add(identity);
139
+ if (metadata.isLatest)
140
+ latestByKey.set(metadata.key, (latestByKey.get(metadata.key) ?? 0) + 1);
141
+ }
142
+ for (const key of new Set(listing.versions.map((version) => version.key))) {
143
+ if (latestByKey.get(key) !== 1) {
144
+ return yield* JournalIntegrityError.make({ reason: "Journal object key does not have exactly one latest version." });
145
+ }
146
+ }
147
+ const objects = new Map();
148
+ for (const metadata of listing.versions) {
149
+ const object = input.afterMutation === true
150
+ ? yield* getObject(authority, metadata.key, metadata.versionId, input.client, true)
151
+ : yield* getObject(authority, metadata.key, metadata.versionId, input.client, false);
152
+ yield* pureIntegrity(() => validateRetainedObject(object, metadata.key, metadata.versionId, metadata.etag));
153
+ objects.set(objectIdentity(metadata.key, metadata.versionId), object);
154
+ }
155
+ const headMetadata = listing.versions.filter((version) => version.key === headKey);
156
+ const eventMetadata = listing.versions.filter((version) => version.key !== headKey);
157
+ const eventKeys = new Set();
158
+ for (const metadata of eventMetadata) {
159
+ if (eventKeys.has(metadata.key)) {
160
+ return yield* JournalIntegrityError.make({ reason: "Immutable journal event key has more than one version." });
161
+ }
162
+ eventKeys.add(metadata.key);
163
+ }
164
+ const headByVersion = new Map(headMetadata.map((metadata) => [metadata.versionId, metadata]));
165
+ const latestHead = headMetadata.find((metadata) => metadata.isLatest);
166
+ const visitedHeads = new Set();
167
+ const reverseEntries = [];
168
+ let cursor = latestHead;
169
+ while (cursor !== undefined) {
170
+ if (reverseEntries.length >= input.maximum || visitedHeads.has(cursor.versionId)) {
171
+ return yield* JournalIntegrityError.make({ reason: "Journal head chain is cyclic or exceeds its bound." });
172
+ }
173
+ visitedHeads.add(cursor.versionId);
174
+ const headObject = objects.get(objectIdentity(cursor.key, cursor.versionId));
175
+ const head = yield* pureIntegrity(() => decodeJournalHead(headObject.bytes));
176
+ if (head.releasePoint !== operation.releasePoint || head.operationKey !== operation.operationKey) {
177
+ return yield* JournalIntegrityError.make({ reason: "Journal head belongs to a different operation." });
178
+ }
179
+ const eventObject = objects.get(objectIdentity(head.eventKey, head.eventVersionId));
180
+ if (eventObject === undefined) {
181
+ return yield* JournalIntegrityError.make({ reason: "Journal head references a missing exact event version." });
182
+ }
183
+ const event = yield* pureIntegrity(() => decodeJournalEvent(eventObject.bytes));
184
+ if (event.releasePoint !== operation.releasePoint || event.operationKey !== operation.operationKey ||
185
+ event.sequence !== head.sequence || event.transactionId !== head.transactionId ||
186
+ journalEventKey(operation, event.sequence, event.transactionId) !== head.eventKey ||
187
+ eventObject.checksumSha256 !== head.eventChecksumSha256 || eventDigest(eventObject.bytes) !== head.eventDigest) {
188
+ return yield* JournalIntegrityError.make({ reason: "Journal head and event do not form one exact canonical record." });
189
+ }
190
+ if (event.workflow.repositoryId !== authority.oidc.repositoryId) {
191
+ return yield* JournalIntegrityError.make({
192
+ reason: "Journal event workflow repository does not equal the re-observed authority."
193
+ });
194
+ }
195
+ reverseEntries.push({ headObject, head, eventObject, event });
196
+ if (head.previousHeadVersionId === null || head.previousHeadEtag === null) {
197
+ if (head.previousHeadVersionId !== null || head.previousHeadEtag !== null || event.previous !== null) {
198
+ return yield* JournalIntegrityError.make({ reason: "Journal root predecessor is only partially empty." });
199
+ }
200
+ cursor = undefined;
201
+ }
202
+ else {
203
+ const previous = headByVersion.get(head.previousHeadVersionId);
204
+ if (previous === undefined || previous.etag !== head.previousHeadEtag || event.previous === null ||
205
+ event.previous.headVersionId !== head.previousHeadVersionId || event.previous.headEtag !== head.previousHeadEtag) {
206
+ return yield* JournalIntegrityError.make({ reason: "Journal predecessor does not identify one retained head version." });
207
+ }
208
+ cursor = previous;
209
+ }
210
+ }
211
+ if (visitedHeads.size !== headMetadata.length) {
212
+ return yield* JournalIntegrityError.make({ reason: "Journal contains an unreachable head version." });
213
+ }
214
+ const entries = reverseEntries.reverse();
215
+ for (let index = 0; index < entries.length; index += 1) {
216
+ const entry = entries[index];
217
+ const previous = entries[index - 1];
218
+ if (previous === undefined) {
219
+ if (entry.event.sequence !== 1 || entry.event.previous !== null) {
220
+ return yield* JournalIntegrityError.make({ reason: "Journal first event is not a canonical root." });
221
+ }
222
+ }
223
+ else if (entry.event.previous === null ||
224
+ entry.event.previous.eventDigest !== previous.head.eventDigest ||
225
+ entry.event.previous.headVersionId !== previous.headObject.versionId ||
226
+ entry.event.previous.headEtag !== previous.headObject.etag) {
227
+ return yield* JournalIntegrityError.make({ reason: "Journal event chain does not bind the preceding exact head." });
228
+ }
229
+ }
230
+ const state = yield* pureIntegrity(() => reduceJournalEvents(entries.map((entry) => entry.event)));
231
+ const reachableEvents = new Set(entries.map((entry) => objectIdentity(entry.eventObject.key, entry.eventObject.versionId)));
232
+ const reachableTransactions = new Set(entries.map((entry) => entry.event.transactionId));
233
+ const entryByHeadVersion = new Map(entries.map((entry) => [entry.headObject.versionId, entry]));
234
+ const orphans = [];
235
+ for (const metadata of eventMetadata) {
236
+ if (reachableEvents.has(objectIdentity(metadata.key, metadata.versionId)))
237
+ continue;
238
+ const eventObject = objects.get(objectIdentity(metadata.key, metadata.versionId));
239
+ const event = yield* pureIntegrity(() => decodeJournalEvent(eventObject.bytes));
240
+ if (event.releasePoint !== operation.releasePoint || event.operationKey !== operation.operationKey ||
241
+ journalEventKey(operation, event.sequence, event.transactionId) !== eventObject.key) {
242
+ return yield* JournalIntegrityError.make({ reason: "Unreachable journal event is not a canonical attempt for this operation." });
243
+ }
244
+ if (event.workflow.repositoryId !== authority.oidc.repositoryId) {
245
+ return yield* JournalIntegrityError.make({
246
+ reason: "Journal orphan workflow repository does not equal the re-observed authority."
247
+ });
248
+ }
249
+ let predecessorState = "Empty";
250
+ if (event.previous === null) {
251
+ if (event.sequence !== 1)
252
+ return yield* JournalIntegrityError.make({ reason: "Orphan root event has a non-root sequence." });
253
+ }
254
+ else {
255
+ const predecessor = entryByHeadVersion.get(event.previous.headVersionId);
256
+ if (predecessor === undefined || predecessor.headObject.etag !== event.previous.headEtag ||
257
+ predecessor.head.eventDigest !== event.previous.eventDigest || event.sequence !== predecessor.event.sequence + 1) {
258
+ return yield* JournalIntegrityError.make({ reason: "Orphan event does not bind one reachable predecessor." });
259
+ }
260
+ predecessorState = predecessor.event.record.tag;
261
+ }
262
+ yield* pureIntegrity(() => admitJournalTransition(predecessorState, event.record.tag));
263
+ orphans.push({ eventObject, event });
264
+ }
265
+ const logicalAttemptByTransaction = new Map();
266
+ for (const event of [
267
+ ...entries.map((entry) => entry.event),
268
+ ...orphans.map((orphan) => orphan.event)
269
+ ]) {
270
+ const existing = logicalAttemptByTransaction.get(event.transactionId);
271
+ if (existing !== undefined && !logicalRecordEquals(existing, event)) {
272
+ return yield* JournalIntegrityError.make({
273
+ reason: "One journal transaction ID carries divergent retained logical records."
274
+ });
275
+ }
276
+ logicalAttemptByTransaction.set(event.transactionId, event);
277
+ }
278
+ if (!input.allowStandaloneOrphans && orphans.some((orphan) => !reachableTransactions.has(orphan.event.transactionId))) {
279
+ return yield* JournalIntegrityError.make({ reason: "Journal contains an unacknowledged event transaction; explicit reconciliation is required." });
280
+ }
281
+ return { authority, operation, entries, orphans, state };
282
+ });
283
+ const acknowledgement = (loaded, entry) => ({
284
+ bucketArn: loaded.authority.bucketArn,
285
+ prefix: journalNamespace(loaded.operation),
286
+ releasePoint: loaded.operation.releasePoint,
287
+ operationKey: loaded.operation.operationKey,
288
+ eventKey: entry.eventObject.key,
289
+ eventVersionId: entry.eventObject.versionId,
290
+ eventChecksumSha256: entry.eventObject.checksumSha256,
291
+ headKey: entry.headObject.key,
292
+ headVersionId: entry.headObject.versionId,
293
+ headEtag: entry.headObject.etag,
294
+ headChecksumSha256: entry.headObject.checksumSha256,
295
+ recordDigest: entry.head.eventDigest,
296
+ sequence: entry.event.sequence,
297
+ transactionId: entry.event.transactionId,
298
+ previousHeadVersionId: entry.head.previousHeadVersionId,
299
+ previousHeadEtag: entry.head.previousHeadEtag
300
+ });
301
+ const snapshot = (loaded) => {
302
+ const current = loaded.entries.at(-1);
303
+ return {
304
+ ...loaded.operation,
305
+ state: loaded.state,
306
+ records: loaded.entries.map((entry) => journalRecordFromEvent(entry.event)),
307
+ acknowledgement: current === undefined ? null : acknowledgement(loaded, current)
308
+ };
309
+ };
310
+ const recoverExactEvent = (input) => Effect.gen(function* () {
311
+ const listing = yield* listOperation(input.loaded.authority, input.loaded.operation, input.maximum, input.client, true);
312
+ if (listing.truncated || listing.deleteMarkers.length > 0) {
313
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Event response loss could not be reconciled within the bounded namespace." });
314
+ }
315
+ const versions = listing.versions.filter((version) => version.key === input.key);
316
+ if (versions.length === 0)
317
+ return null;
318
+ if (versions.length !== 1)
319
+ return yield* JournalIntegrityError.make({ reason: "Immutable event key has more than one version." });
320
+ const metadata = versions[0];
321
+ const object = yield* getObject(input.loaded.authority, metadata.key, metadata.versionId, input.client, true);
322
+ yield* pureIntegrity(() => validateRetainedObject(object, metadata.key, metadata.versionId, metadata.etag));
323
+ if (!sameBytes(object.bytes, input.bytes)) {
324
+ return yield* JournalIntegrityError.make({ reason: "Existing event key contains different canonical bytes." });
325
+ }
326
+ return object;
327
+ });
328
+ const capturePut = (effect) => effect.pipe(Effect.map((result) => ({ _tag: "Result", result })), Effect.catch((error) => Effect.succeed({ _tag: "Error", error })));
329
+ const writeEvent = (input) => Effect.gen(function* () {
330
+ const key = journalEventKey(input.loaded.operation, input.event.sequence, input.event.transactionId);
331
+ const bytes = encodeJournalEvent(input.event);
332
+ const request = {
333
+ bucketName: input.loaded.authority.bucketName,
334
+ expectedBucketOwner: input.loaded.authority.expectedBucketOwner,
335
+ region: input.loaded.authority.region,
336
+ key,
337
+ bytes,
338
+ checksumSha256: objectChecksum(bytes),
339
+ condition: { _tag: "IfNoneMatch" }
340
+ };
341
+ for (let attempt = 0; attempt < 2; attempt += 1) {
342
+ const outcome = yield* capturePut(input.client.putEvent(request));
343
+ if (outcome._tag === "Result" && outcome.result._tag === "Committed") {
344
+ const committed = outcome.result;
345
+ const object = yield* getObject(input.loaded.authority, key, committed.versionId, input.client, true);
346
+ yield* pureIntegrity(() => validateRetainedObject(object, key, committed.versionId, committed.etag));
347
+ if (object.checksumSha256 !== committed.checksumSha256 || !sameBytes(object.bytes, bytes)) {
348
+ return yield* JournalIntegrityError.make({ reason: "Committed event failed its immediate exact-version re-read." });
349
+ }
350
+ return object;
351
+ }
352
+ const recovered = yield* recoverExactEvent({ ...input, key, bytes });
353
+ if (recovered !== null)
354
+ return recovered;
355
+ if (outcome._tag === "Result" && outcome.result._tag === "PreconditionFailed") {
356
+ return yield* JournalConflict.make({ reason: "Event conditional create conflicted without an exact recoverable version." });
357
+ }
358
+ if (outcome._tag === "Error" && outcome.error.commitment === "unknown" && attempt === 0)
359
+ continue;
360
+ if (outcome._tag === "Error" && outcome.error.commitment === "not-committed" && attempt === 0)
361
+ continue;
362
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Event write has no acknowledged or authoritatively absent terminal outcome." });
363
+ }
364
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Event write exceeded its bounded reconciliation." });
365
+ });
366
+ const putHeadOnce = (input) => {
367
+ const previous = input.loaded.entries.at(-1);
368
+ const head = makeJournalHead({
369
+ event: input.event,
370
+ eventKey: input.eventObject.key,
371
+ eventVersionId: input.eventObject.versionId,
372
+ eventChecksumSha256: input.eventObject.checksumSha256,
373
+ eventDigest: eventDigest(input.eventObject.bytes),
374
+ previousHeadVersionId: previous?.headObject.versionId ?? null,
375
+ previousHeadEtag: previous?.headObject.etag ?? null
376
+ });
377
+ const bytes = encodeJournalHead(head);
378
+ const request = {
379
+ bucketName: input.loaded.authority.bucketName,
380
+ expectedBucketOwner: input.loaded.authority.expectedBucketOwner,
381
+ region: input.loaded.authority.region,
382
+ key: journalHeadKey(input.loaded.operation),
383
+ bytes,
384
+ checksumSha256: objectChecksum(bytes),
385
+ condition: previous === undefined
386
+ ? { _tag: "IfNoneMatch" }
387
+ : { _tag: "IfMatch", etag: previous.headObject.etag }
388
+ };
389
+ return capturePut(input.client.putHead(request)).pipe(Effect.map((outcome) => ({ outcome, head })));
390
+ };
391
+ const logicalRecordEquals = (left, right) => encodeCanonicalJson(left.record) === encodeCanonicalJson(right.record) &&
392
+ encodeCanonicalJson(left.workflow) === encodeCanonicalJson(right.workflow);
393
+ const commitTransaction = (input) => Effect.gen(function* () {
394
+ const current = input.loaded.entries.at(-1);
395
+ yield* pureTransition(() => admitJournalTransition(input.loaded.state, input.record.tag));
396
+ const event = makeJournalEvent({
397
+ releasePoint: input.loaded.operation.releasePoint,
398
+ operationKey: input.loaded.operation.operationKey,
399
+ sequence: (current?.event.sequence ?? 0) + 1,
400
+ transactionId: input.transactionId,
401
+ previous: current?.event ?? null,
402
+ previousHead: current === undefined ? null : {
403
+ versionId: current.headObject.versionId,
404
+ etag: current.headObject.etag,
405
+ eventDigest: current.head.eventDigest
406
+ },
407
+ workflow: input.workflow,
408
+ record: input.record
409
+ });
410
+ const eventObject = yield* writeEvent({ ...input, event });
411
+ const first = yield* putHeadOnce({ ...input, event, eventObject });
412
+ if (first.outcome._tag === "Result" && first.outcome.result._tag === "Committed") {
413
+ const verified = yield* loadJournal({
414
+ expectedAuthority: input.loaded.authority,
415
+ client: input.client,
416
+ operation: input.loaded.operation,
417
+ maximum: input.maximum,
418
+ allowStandaloneOrphans: false,
419
+ afterMutation: true
420
+ });
421
+ const entry = verified.entries.find((candidate) => candidate.event.transactionId === input.transactionId);
422
+ if (entry === undefined) {
423
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Head response succeeded but exact transaction is not reachable after re-read." });
424
+ }
425
+ return acknowledgement(verified, entry);
426
+ }
427
+ let recovered = yield* loadJournal({
428
+ expectedAuthority: input.loaded.authority,
429
+ client: input.client,
430
+ operation: input.loaded.operation,
431
+ maximum: input.maximum,
432
+ allowStandaloneOrphans: true,
433
+ afterMutation: true
434
+ });
435
+ const reached = recovered.entries.find((candidate) => candidate.event.transactionId === input.transactionId);
436
+ if (reached !== undefined)
437
+ return acknowledgement(recovered, reached);
438
+ const recoveredCurrent = recovered.entries.at(-1);
439
+ const oldCurrent = input.loaded.entries.at(-1);
440
+ const predecessorUnchanged = recoveredCurrent?.headObject.versionId === oldCurrent?.headObject.versionId &&
441
+ recoveredCurrent?.headObject.etag === oldCurrent?.headObject.etag &&
442
+ (recoveredCurrent !== undefined) === (oldCurrent !== undefined);
443
+ if (predecessorUnchanged) {
444
+ const retry = yield* putHeadOnce({ loaded: recovered, client: input.client, event, eventObject });
445
+ recovered = yield* loadJournal({
446
+ expectedAuthority: input.loaded.authority,
447
+ client: input.client,
448
+ operation: input.loaded.operation,
449
+ maximum: input.maximum,
450
+ allowStandaloneOrphans: true,
451
+ afterMutation: true
452
+ });
453
+ const retried = recovered.entries.find((candidate) => candidate.event.transactionId === input.transactionId);
454
+ if (retried !== undefined)
455
+ return acknowledgement(recovered, retried);
456
+ if (retry.outcome._tag === "Error" || retry.outcome.result._tag === "PreconditionFailed") {
457
+ if (!input.allowRebase) {
458
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Head CAS did not acknowledge the transaction within its bounded retry." });
459
+ }
460
+ }
461
+ const afterRetry = recovered.entries.at(-1);
462
+ const stillUnchanged = afterRetry?.headObject.versionId === oldCurrent?.headObject.versionId &&
463
+ afterRetry?.headObject.etag === oldCurrent?.headObject.etag &&
464
+ (afterRetry !== undefined) === (oldCurrent !== undefined);
465
+ if (stillUnchanged) {
466
+ return yield* JournalStorageOutcomeUnknown.make({
467
+ reason: "Head CAS remained authoritatively absent after its one bounded retry."
468
+ });
469
+ }
470
+ }
471
+ if (!input.allowRebase) {
472
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Head transaction is absent after its bounded reconciliation." });
473
+ }
474
+ yield* pureTransition(() => admitJournalTransition(recovered.state, input.record.tag)).pipe(Effect.mapError((error) => error instanceof JournalTransitionError
475
+ ? JournalConflict.make({ reason: "A concurrent journal transition made this append inadmissible." })
476
+ : error));
477
+ const rebasedCurrent = recovered.entries.at(-1);
478
+ const rebasedEvent = makeJournalEvent({
479
+ releasePoint: recovered.operation.releasePoint,
480
+ operationKey: recovered.operation.operationKey,
481
+ sequence: (rebasedCurrent?.event.sequence ?? 0) + 1,
482
+ transactionId: input.transactionId,
483
+ previous: rebasedCurrent?.event ?? null,
484
+ previousHead: rebasedCurrent === undefined ? null : {
485
+ versionId: rebasedCurrent.headObject.versionId,
486
+ etag: rebasedCurrent.headObject.etag,
487
+ eventDigest: rebasedCurrent.head.eventDigest
488
+ },
489
+ workflow: input.workflow,
490
+ record: input.record
491
+ });
492
+ const rebasedObject = yield* writeEvent({ loaded: recovered, client: input.client, event: rebasedEvent, maximum: input.maximum });
493
+ yield* putHeadOnce({ loaded: recovered, client: input.client, event: rebasedEvent, eventObject: rebasedObject });
494
+ const terminal = yield* loadJournal({
495
+ expectedAuthority: input.loaded.authority,
496
+ client: input.client,
497
+ operation: input.loaded.operation,
498
+ maximum: input.maximum,
499
+ allowStandaloneOrphans: true,
500
+ afterMutation: true
501
+ });
502
+ const committed = terminal.entries.find((candidate) => candidate.event.transactionId === input.transactionId);
503
+ if (committed === undefined) {
504
+ return yield* JournalStorageOutcomeUnknown.make({ reason: "Rebased head CAS did not acknowledge the transaction." });
505
+ }
506
+ return acknowledgement(terminal, committed);
507
+ });
508
+ const orphanBindsCurrent = (loaded, orphan) => {
509
+ const current = loaded.entries.at(-1);
510
+ if (current === undefined) {
511
+ return orphan.event.sequence === 1 && orphan.event.previous === null;
512
+ }
513
+ return orphan.event.sequence === current.event.sequence + 1 && orphan.event.previous !== null &&
514
+ orphan.event.previous.headVersionId === current.headObject.versionId &&
515
+ orphan.event.previous.headEtag === current.headObject.etag &&
516
+ orphan.event.previous.eventDigest === current.head.eventDigest;
517
+ };
518
+ const acknowledgeExistingOrphan = (input) => Effect.gen(function* () {
519
+ yield* putHeadOnce({
520
+ loaded: input.loaded,
521
+ client: input.client,
522
+ event: input.orphan.event,
523
+ eventObject: input.orphan.eventObject
524
+ });
525
+ let recovered = yield* loadJournal({
526
+ expectedAuthority: input.loaded.authority,
527
+ client: input.client,
528
+ operation: input.loaded.operation,
529
+ maximum: input.maximum,
530
+ allowStandaloneOrphans: true,
531
+ afterMutation: true
532
+ });
533
+ if (recovered.entries.some((entry) => entry.event.transactionId === input.orphan.event.transactionId)) {
534
+ return recovered;
535
+ }
536
+ if (!orphanBindsCurrent(recovered, input.orphan)) {
537
+ yield* commitTransaction({
538
+ loaded: recovered,
539
+ client: input.client,
540
+ record: input.orphan.event.record,
541
+ workflow: input.orphan.event.workflow,
542
+ transactionId: input.orphan.event.transactionId,
543
+ maximum: input.maximum,
544
+ allowRebase: true
545
+ });
546
+ return yield* loadJournal({
547
+ expectedAuthority: input.loaded.authority,
548
+ client: input.client,
549
+ operation: input.loaded.operation,
550
+ maximum: input.maximum,
551
+ allowStandaloneOrphans: false,
552
+ afterMutation: true
553
+ });
554
+ }
555
+ yield* putHeadOnce({
556
+ loaded: recovered,
557
+ client: input.client,
558
+ event: input.orphan.event,
559
+ eventObject: input.orphan.eventObject
560
+ });
561
+ recovered = yield* loadJournal({
562
+ expectedAuthority: input.loaded.authority,
563
+ client: input.client,
564
+ operation: input.loaded.operation,
565
+ maximum: input.maximum,
566
+ allowStandaloneOrphans: true,
567
+ afterMutation: true
568
+ });
569
+ if (!recovered.entries.some((entry) => entry.event.transactionId === input.orphan.event.transactionId)) {
570
+ return yield* JournalStorageOutcomeUnknown.make({
571
+ reason: "Existing orphan event did not acquire an acknowledged head within its bounded CAS retry."
572
+ });
573
+ }
574
+ return recovered;
575
+ });
576
+ const reconcileLoaded = (input) => Effect.gen(function* () {
577
+ const reachableTransactions = new Set(input.loaded.entries.map((entry) => entry.event.transactionId));
578
+ const standalone = input.loaded.orphans.filter((orphan) => !reachableTransactions.has(orphan.event.transactionId));
579
+ if (standalone.length === 0)
580
+ return input.loaded;
581
+ const transactions = new Map();
582
+ for (const orphan of standalone) {
583
+ const attempts = transactions.get(orphan.event.transactionId) ?? [];
584
+ attempts.push(orphan);
585
+ transactions.set(orphan.event.transactionId, attempts);
586
+ }
587
+ if (transactions.size !== 1) {
588
+ return yield* JournalConflict.make({ reason: "More than one unacknowledged journal transaction requires adjudication." });
589
+ }
590
+ const [transactionId, attempts] = [...transactions.entries()][0];
591
+ const basis = attempts[0];
592
+ if (attempts.some((attempt) => !logicalRecordEquals(basis.event, attempt.event))) {
593
+ return yield* JournalIntegrityError.make({ reason: "One orphan transaction carries multiple logical records." });
594
+ }
595
+ const directlyAdoptable = attempts.filter((attempt) => orphanBindsCurrent(input.loaded, attempt));
596
+ if (directlyAdoptable.length > 1) {
597
+ return yield* JournalIntegrityError.make({ reason: "One orphan transaction has multiple attempts for the current predecessor." });
598
+ }
599
+ if (directlyAdoptable.length === 1) {
600
+ yield* acknowledgeExistingOrphan({
601
+ loaded: input.loaded,
602
+ orphan: directlyAdoptable[0],
603
+ client: input.client,
604
+ maximum: input.maximum
605
+ });
606
+ }
607
+ else {
608
+ yield* commitTransaction({
609
+ loaded: input.loaded,
610
+ client: input.client,
611
+ record: basis.event.record,
612
+ workflow: basis.event.workflow,
613
+ transactionId,
614
+ maximum: input.maximum,
615
+ allowRebase: true
616
+ });
617
+ }
618
+ return yield* loadJournal({
619
+ expectedAuthority: input.loaded.authority,
620
+ client: input.client,
621
+ operation: input.loaded.operation,
622
+ maximum: input.maximum,
623
+ allowStandaloneOrphans: false,
624
+ afterMutation: true
625
+ });
626
+ });
627
+ export const makeS3CanonicalOperationJournal = (options) => {
628
+ const maximum = 512;
629
+ const load = (operation, allowStandaloneOrphans) => loadJournal({
630
+ expectedAuthority: options.authority,
631
+ client: options.client,
632
+ operation,
633
+ maximum,
634
+ allowStandaloneOrphans
635
+ });
636
+ return {
637
+ read: (operation) => load(operation, false).pipe(Effect.mapError((error) => error instanceof JournalStorageOutcomeUnknown
638
+ ? JournalStorageUnavailable.make({ reason: error.reason })
639
+ : error), Effect.map(snapshot)),
640
+ reconcile: (operation) => Effect.gen(function* () {
641
+ const loaded = yield* load(operation, true);
642
+ return snapshot(yield* reconcileLoaded({ loaded, client: options.client, maximum }));
643
+ }),
644
+ append: (request) => Effect.gen(function* () {
645
+ const operation = yield* pureInput(() => validateJournalOperation(request));
646
+ const record = yield* pureInput(() => makeCanonicalJournalRecord(request));
647
+ const transactionId = yield* pureInput(() => validateTransactionId(randomUUID()));
648
+ const initial = yield* load(operation, true);
649
+ const loaded = yield* reconcileLoaded({ loaded: initial, client: options.client, maximum });
650
+ const workflow = yield* pureInput(() => validateJournalWorkflow({
651
+ repositoryId: loaded.authority.oidc.repositoryId,
652
+ runId: loaded.authority.oidc.runId,
653
+ runAttempt: loaded.authority.oidc.runAttempt
654
+ }));
655
+ return yield* commitTransaction({
656
+ loaded,
657
+ client: options.client,
658
+ record,
659
+ workflow,
660
+ transactionId,
661
+ maximum,
662
+ allowRebase: true
663
+ });
664
+ })
665
+ };
666
+ };
667
+ //# sourceMappingURL=s3.js.map