@mannyc1/ts-release 0.0.7 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (635) hide show
  1. package/ARCHITECTURE.md +124 -92
  2. package/CHANGELOG.md +115 -0
  3. package/LICENSE +21 -0
  4. package/README.md +278 -324
  5. package/SPEC.md +206 -310
  6. package/apps/release-ts/README.md +32 -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 +117 -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 +39239 -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 +8 -0
  82. package/dist/drivers/archive.d.ts.map +1 -0
  83. package/dist/drivers/archive.js +101 -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/redact.d.ts +4 -0
  106. package/dist/drivers/redact.d.ts.map +1 -0
  107. package/dist/drivers/redact.js +24 -0
  108. package/dist/drivers/redact.js.map +1 -0
  109. package/dist/drivers/seccomp-helper-source.d.ts +7 -0
  110. package/dist/drivers/seccomp-helper-source.d.ts.map +1 -0
  111. package/dist/drivers/seccomp-helper-source.js +121 -0
  112. package/dist/drivers/seccomp-helper-source.js.map +1 -0
  113. package/dist/drivers/utils.d.ts +4 -0
  114. package/dist/drivers/utils.d.ts.map +1 -0
  115. package/dist/drivers/utils.js +5 -0
  116. package/dist/drivers/utils.js.map +1 -0
  117. package/dist/drivers/workspace.d.ts +6 -0
  118. package/dist/drivers/workspace.d.ts.map +1 -0
  119. package/dist/drivers/workspace.js +49 -0
  120. package/dist/drivers/workspace.js.map +1 -0
  121. package/dist/extensions/provider-adapter.d.ts +48 -0
  122. package/dist/extensions/provider-adapter.d.ts.map +1 -0
  123. package/dist/extensions/provider-adapter.js +64 -0
  124. package/dist/extensions/provider-adapter.js.map +1 -0
  125. package/dist/host.d.ts +33 -0
  126. package/dist/host.d.ts.map +1 -0
  127. package/dist/host.js +20 -0
  128. package/dist/host.js.map +1 -0
  129. package/dist/index.d.ts +19 -1
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +12 -1
  132. package/dist/index.js.map +1 -1
  133. package/dist/model/artifact-collection.d.ts +84 -0
  134. package/dist/model/artifact-collection.d.ts.map +1 -0
  135. package/dist/model/artifact-collection.js +185 -0
  136. package/dist/model/artifact-collection.js.map +1 -0
  137. package/dist/model/authority.d.ts +89 -0
  138. package/dist/model/authority.d.ts.map +1 -0
  139. package/dist/model/authority.js +80 -0
  140. package/dist/model/authority.js.map +1 -0
  141. package/dist/model/bun-targets.d.ts +34 -0
  142. package/dist/model/bun-targets.d.ts.map +1 -0
  143. package/dist/model/bun-targets.js +17 -0
  144. package/dist/model/bun-targets.js.map +1 -0
  145. package/dist/model/canonical.d.ts +8 -0
  146. package/dist/model/canonical.d.ts.map +1 -0
  147. package/dist/model/canonical.js +205 -0
  148. package/dist/model/canonical.js.map +1 -0
  149. package/dist/model/catalog.d.ts +76 -0
  150. package/dist/model/catalog.d.ts.map +1 -0
  151. package/dist/model/catalog.js +174 -0
  152. package/dist/model/catalog.js.map +1 -0
  153. package/dist/model/digest.d.ts +53 -0
  154. package/dist/model/digest.d.ts.map +1 -0
  155. package/dist/model/digest.js +127 -0
  156. package/dist/model/digest.js.map +1 -0
  157. package/dist/model/errors.d.ts +14 -0
  158. package/dist/model/errors.d.ts.map +1 -0
  159. package/dist/model/errors.js +8 -0
  160. package/dist/model/errors.js.map +1 -0
  161. package/dist/model/primitives.d.ts +19 -0
  162. package/dist/model/primitives.d.ts.map +1 -0
  163. package/dist/model/primitives.js +18 -0
  164. package/dist/model/primitives.js.map +1 -0
  165. package/dist/model/pypi.d.ts +12 -0
  166. package/dist/model/pypi.d.ts.map +1 -0
  167. package/dist/model/pypi.js +20 -0
  168. package/dist/model/pypi.js.map +1 -0
  169. package/dist/model/python-distribution.d.ts +33 -0
  170. package/dist/model/python-distribution.d.ts.map +1 -0
  171. package/dist/model/python-distribution.js +367 -0
  172. package/dist/model/python-distribution.js.map +1 -0
  173. package/dist/model/secret-patterns.d.ts +2 -0
  174. package/dist/model/secret-patterns.d.ts.map +1 -0
  175. package/dist/model/secret-patterns.js +12 -0
  176. package/dist/model/secret-patterns.js.map +1 -0
  177. package/dist/platform/bun.d.ts +7 -0
  178. package/dist/platform/bun.d.ts.map +1 -0
  179. package/dist/platform/bun.js +15 -0
  180. package/dist/platform/bun.js.map +1 -0
  181. package/dist/platform/credentials.d.ts +32 -0
  182. package/dist/platform/credentials.d.ts.map +1 -0
  183. package/dist/platform/credentials.js +772 -0
  184. package/dist/platform/credentials.js.map +1 -0
  185. package/dist/platform/host-support.d.ts +2 -0
  186. package/dist/platform/host-support.d.ts.map +1 -0
  187. package/dist/platform/host-support.js +4 -0
  188. package/dist/platform/host-support.js.map +1 -0
  189. package/dist/platform/node.d.ts +7 -0
  190. package/dist/platform/node.d.ts.map +1 -0
  191. package/dist/platform/node.js +15 -0
  192. package/dist/platform/node.js.map +1 -0
  193. package/dist/platform/release-runtime.d.ts +11 -0
  194. package/dist/platform/release-runtime.d.ts.map +1 -0
  195. package/dist/platform/release-runtime.js +34 -0
  196. package/dist/platform/release-runtime.js.map +1 -0
  197. package/dist/platform/services.d.ts +15 -0
  198. package/dist/platform/services.d.ts.map +1 -0
  199. package/dist/platform/services.js +30 -0
  200. package/dist/platform/services.js.map +1 -0
  201. package/dist/platform/source-observer.d.ts +5 -0
  202. package/dist/platform/source-observer.d.ts.map +1 -0
  203. package/dist/platform/source-observer.js +159 -0
  204. package/dist/platform/source-observer.js.map +1 -0
  205. package/dist/provider-sdk.d.ts +14 -0
  206. package/dist/provider-sdk.d.ts.map +1 -0
  207. package/dist/provider-sdk.js +10 -0
  208. package/dist/provider-sdk.js.map +1 -0
  209. package/dist/publication/adapter.d.ts +212 -0
  210. package/dist/publication/adapter.d.ts.map +1 -0
  211. package/dist/publication/adapter.js +83 -0
  212. package/dist/publication/adapter.js.map +1 -0
  213. package/dist/publication/authority.d.ts +137 -0
  214. package/dist/publication/authority.d.ts.map +1 -0
  215. package/dist/publication/authority.js +233 -0
  216. package/dist/publication/authority.js.map +1 -0
  217. package/dist/publication/catalog-git.d.ts +37 -0
  218. package/dist/publication/catalog-git.d.ts.map +1 -0
  219. package/dist/publication/catalog-git.js +451 -0
  220. package/dist/publication/catalog-git.js.map +1 -0
  221. package/dist/publication/claim.d.ts +39 -0
  222. package/dist/publication/claim.d.ts.map +1 -0
  223. package/dist/publication/claim.js +31 -0
  224. package/dist/publication/claim.js.map +1 -0
  225. package/dist/publication/coordinator.d.ts +246 -0
  226. package/dist/publication/coordinator.d.ts.map +1 -0
  227. package/dist/publication/coordinator.js +370 -0
  228. package/dist/publication/coordinator.js.map +1 -0
  229. package/dist/publication/github.d.ts +36 -0
  230. package/dist/publication/github.d.ts.map +1 -0
  231. package/dist/publication/github.js +644 -0
  232. package/dist/publication/github.js.map +1 -0
  233. package/dist/publication/http.d.ts +69 -0
  234. package/dist/publication/http.d.ts.map +1 -0
  235. package/dist/publication/http.js +29 -0
  236. package/dist/publication/http.js.map +1 -0
  237. package/dist/publication/index.d.ts +5 -0
  238. package/dist/publication/index.d.ts.map +1 -0
  239. package/dist/publication/index.js +5 -0
  240. package/dist/publication/index.js.map +1 -0
  241. package/dist/publication/npm.d.ts +40 -0
  242. package/dist/publication/npm.d.ts.map +1 -0
  243. package/dist/publication/npm.js +359 -0
  244. package/dist/publication/npm.js.map +1 -0
  245. package/dist/publication/profiles.d.ts +136 -0
  246. package/dist/publication/profiles.d.ts.map +1 -0
  247. package/dist/publication/profiles.js +90 -0
  248. package/dist/publication/profiles.js.map +1 -0
  249. package/dist/publication/publisher.d.ts +82 -0
  250. package/dist/publication/publisher.d.ts.map +1 -0
  251. package/dist/publication/publisher.js +53 -0
  252. package/dist/publication/publisher.js.map +1 -0
  253. package/dist/publication/pypi.d.ts +45 -0
  254. package/dist/publication/pypi.d.ts.map +1 -0
  255. package/dist/publication/pypi.js +369 -0
  256. package/dist/publication/pypi.js.map +1 -0
  257. package/dist/publication/recovery.d.ts +663 -0
  258. package/dist/publication/recovery.d.ts.map +1 -0
  259. package/dist/publication/recovery.js +252 -0
  260. package/dist/publication/recovery.js.map +1 -0
  261. package/dist/publication/report.d.ts +1061 -0
  262. package/dist/publication/report.d.ts.map +1 -0
  263. package/dist/publication/report.js +441 -0
  264. package/dist/publication/report.js.map +1 -0
  265. package/dist/recipes/config.d.ts +296 -0
  266. package/dist/recipes/config.d.ts.map +1 -0
  267. package/dist/recipes/config.js +325 -0
  268. package/dist/recipes/config.js.map +1 -0
  269. package/dist/release/capabilities.d.ts +12 -0
  270. package/dist/release/capabilities.d.ts.map +1 -0
  271. package/dist/release/capabilities.js +395 -0
  272. package/dist/release/capabilities.js.map +1 -0
  273. package/dist/release/compiler.d.ts +5 -0
  274. package/dist/release/compiler.d.ts.map +1 -0
  275. package/dist/release/compiler.js +19 -0
  276. package/dist/release/compiler.js.map +1 -0
  277. package/dist/release/config.d.ts +5 -0
  278. package/dist/release/config.d.ts.map +1 -0
  279. package/dist/release/config.js +10 -0
  280. package/dist/release/config.js.map +1 -0
  281. package/dist/release/context.d.ts +96 -0
  282. package/dist/release/context.d.ts.map +1 -0
  283. package/dist/release/context.js +168 -0
  284. package/dist/release/context.js.map +1 -0
  285. package/dist/release/graph.d.ts +271 -0
  286. package/dist/release/graph.d.ts.map +1 -0
  287. package/dist/release/graph.js +766 -0
  288. package/dist/release/graph.js.map +1 -0
  289. package/dist/release/inspect.d.ts +88 -0
  290. package/dist/release/inspect.d.ts.map +1 -0
  291. package/dist/release/inspect.js +75 -0
  292. package/dist/release/inspect.js.map +1 -0
  293. package/dist/release/prepare.d.ts +24 -0
  294. package/dist/release/prepare.d.ts.map +1 -0
  295. package/dist/release/prepare.js +1116 -0
  296. package/dist/release/prepare.js.map +1 -0
  297. package/dist/release/prepared-ref.d.ts +60 -0
  298. package/dist/release/prepared-ref.d.ts.map +1 -0
  299. package/dist/release/prepared-ref.js +131 -0
  300. package/dist/release/prepared-ref.js.map +1 -0
  301. package/dist/release/prepared-store.d.ts +90 -0
  302. package/dist/release/prepared-store.d.ts.map +1 -0
  303. package/dist/release/prepared-store.js +337 -0
  304. package/dist/release/prepared-store.js.map +1 -0
  305. package/dist/release/prepared.d.ts +172 -0
  306. package/dist/release/prepared.d.ts.map +1 -0
  307. package/dist/release/prepared.js +268 -0
  308. package/dist/release/prepared.js.map +1 -0
  309. package/dist/release/staging.d.ts +31 -0
  310. package/dist/release/staging.d.ts.map +1 -0
  311. package/dist/release/staging.js +218 -0
  312. package/dist/release/staging.js.map +1 -0
  313. package/dist/resolve/authored.d.ts +53 -0
  314. package/dist/resolve/authored.d.ts.map +1 -0
  315. package/dist/resolve/authored.js +55 -0
  316. package/dist/resolve/authored.js.map +1 -0
  317. package/dist/resolve/encode.d.ts +3 -0
  318. package/dist/resolve/encode.d.ts.map +1 -0
  319. package/dist/resolve/encode.js +21 -0
  320. package/dist/resolve/encode.js.map +1 -0
  321. package/dist/resolve/errors.d.ts +7 -0
  322. package/dist/resolve/errors.d.ts.map +1 -0
  323. package/dist/resolve/errors.js +17 -0
  324. package/dist/resolve/errors.js.map +1 -0
  325. package/dist/resolve/facts.d.ts +12 -0
  326. package/dist/resolve/facts.d.ts.map +1 -0
  327. package/dist/resolve/facts.js +18 -0
  328. package/dist/resolve/facts.js.map +1 -0
  329. package/dist/resolve/resolve.d.ts +10 -0
  330. package/dist/resolve/resolve.d.ts.map +1 -0
  331. package/dist/resolve/resolve.js +242 -0
  332. package/dist/resolve/resolve.js.map +1 -0
  333. package/dist/store.d.ts +11 -0
  334. package/dist/store.d.ts.map +1 -0
  335. package/dist/store.js +9 -0
  336. package/dist/store.js.map +1 -0
  337. package/examples/README.md +20 -30
  338. package/examples/github-release/release.config.json +11 -18
  339. package/examples/homebrew-tap/README.md +11 -0
  340. package/examples/homebrew-tap/release.config.json +40 -28
  341. package/examples/multi-target/release.config.json +28 -53
  342. package/examples/npm-first-publish/release.config.json +23 -25
  343. package/examples/npm-only/release.config.json +22 -30
  344. package/examples/portable-cli/README.md +17 -0
  345. package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-arm64 +1 -0
  346. package/examples/portable-cli/artifacts/portable-example-0.1.0-darwin-x64 +1 -0
  347. package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-arm64 +1 -0
  348. package/examples/portable-cli/artifacts/portable-example-0.1.0-linux-x64 +1 -0
  349. package/examples/portable-cli/artifacts/portable-example-0.1.0-windows-x64.exe +1 -0
  350. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_10_15_x86_64.whl +1 -0
  351. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-macosx_11_0_arm64.whl +1 -0
  352. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_aarch64.whl +1 -0
  353. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-manylinux2014_x86_64.whl +1 -0
  354. package/examples/portable-cli/artifacts/portable_example-0.1.0-py3-none-win_amd64.whl +1 -0
  355. package/examples/portable-cli/package.json +9 -0
  356. package/examples/portable-cli/release.config.json +53 -0
  357. package/examples/portable-cli/src/cli.ts +3 -0
  358. package/examples/pypi-registry/README.md +8 -0
  359. package/examples/scoop-bucket/README.md +10 -0
  360. package/examples/scoop-bucket/release.config.json +40 -30
  361. package/package.json +60 -156
  362. package/src/api/api.ts +365 -0
  363. package/src/api/errors.ts +36 -0
  364. package/src/api/input.ts +92 -0
  365. package/src/api/runtime.ts +14 -0
  366. package/src/api/types.ts +103 -0
  367. package/src/capabilities/bun-targets.ts +2 -0
  368. package/src/capabilities/field-ownership.ts +60 -0
  369. package/src/capabilities/module.ts +158 -0
  370. package/src/capabilities/registry.ts +333 -0
  371. package/src/config/config.ts +48 -0
  372. package/src/correction/coordinator.ts +336 -0
  373. package/src/correction/index.ts +2 -0
  374. package/src/correction/intent.ts +172 -0
  375. package/src/drivers/archive.ts +102 -0
  376. package/src/drivers/contain.ts +20 -0
  377. package/src/drivers/environment.ts +28 -0
  378. package/src/drivers/errors.ts +6 -0
  379. package/src/drivers/glob.ts +137 -0
  380. package/src/drivers/process.ts +340 -0
  381. package/src/drivers/redact.ts +31 -0
  382. package/src/drivers/seccomp-helper-source.ts +121 -0
  383. package/src/drivers/utils.ts +10 -0
  384. package/src/drivers/workspace.ts +40 -0
  385. package/src/extensions/provider-adapter.ts +99 -0
  386. package/src/host.ts +140 -0
  387. package/src/index.ts +64 -0
  388. package/src/model/artifact-collection.ts +237 -0
  389. package/src/model/authority.ts +116 -0
  390. package/src/model/bun-targets.ts +34 -0
  391. package/src/model/canonical.ts +205 -0
  392. package/src/model/catalog.ts +220 -0
  393. package/src/model/digest.ts +172 -0
  394. package/src/model/errors.ts +6 -0
  395. package/src/model/primitives.ts +37 -0
  396. package/src/model/pypi.ts +30 -0
  397. package/src/model/python-distribution.ts +360 -0
  398. package/src/model/secret-patterns.ts +11 -0
  399. package/src/platform/bun.ts +38 -0
  400. package/src/platform/credentials.ts +1083 -0
  401. package/src/platform/host-support.ts +4 -0
  402. package/src/platform/node.ts +38 -0
  403. package/src/platform/release-runtime.ts +47 -0
  404. package/src/platform/services.ts +57 -0
  405. package/src/platform/source-observer.ts +193 -0
  406. package/src/provider-sdk.ts +48 -0
  407. package/src/publication/adapter.ts +132 -0
  408. package/src/publication/authority.ts +397 -0
  409. package/src/publication/catalog-git.ts +603 -0
  410. package/src/publication/claim.ts +51 -0
  411. package/src/publication/coordinator.ts +578 -0
  412. package/src/publication/github.ts +954 -0
  413. package/src/publication/http.ts +101 -0
  414. package/src/publication/index.ts +4 -0
  415. package/src/publication/npm.ts +525 -0
  416. package/src/publication/profiles.ts +94 -0
  417. package/src/publication/publisher.ts +130 -0
  418. package/src/publication/pypi.ts +463 -0
  419. package/src/publication/recovery.ts +349 -0
  420. package/src/publication/report.ts +628 -0
  421. package/src/recipes/config.ts +395 -0
  422. package/src/release/capabilities.ts +459 -0
  423. package/src/release/compiler.ts +28 -0
  424. package/src/release/config.ts +12 -0
  425. package/src/release/context.ts +223 -0
  426. package/src/release/graph.ts +866 -0
  427. package/src/release/inspect.ts +83 -0
  428. package/src/release/prepare.ts +1331 -0
  429. package/src/release/prepared-ref.ts +193 -0
  430. package/src/release/prepared-store.ts +377 -0
  431. package/src/release/prepared.ts +299 -0
  432. package/src/release/staging.ts +257 -0
  433. package/src/resolve/authored.ts +64 -0
  434. package/src/resolve/encode.ts +22 -0
  435. package/src/resolve/errors.ts +15 -0
  436. package/src/resolve/facts.ts +18 -0
  437. package/src/resolve/resolve.ts +328 -0
  438. package/src/store.ts +28 -0
  439. package/templates/README.md +55 -72
  440. package/templates/bun-cli-github/README.md +7 -9
  441. package/templates/bun-cli-github/release.config.json +35 -73
  442. package/templates/github-actions/release.yml +57 -0
  443. package/templates/github-actions/reviewed-release.yml +80 -0
  444. package/templates/multi-target-homebrew/README.md +10 -0
  445. package/templates/multi-target-homebrew/release.config.json +43 -60
  446. package/templates/multi-target-scoop/README.md +10 -0
  447. package/templates/multi-target-scoop/release.config.json +43 -62
  448. package/templates/npm-github/release.config.json +25 -38
  449. package/templates/npm-github/reviewed-release.config.json +37 -0
  450. package/templates/npm-only/README.md +10 -0
  451. package/templates/npm-only/release.config.json +15 -30
  452. package/templates/portable-cli/README.md +13 -0
  453. package/templates/portable-cli/release.config.json +53 -0
  454. package/dist/artifacts/adapter.d.ts +0 -39
  455. package/dist/artifacts/adapter.d.ts.map +0 -1
  456. package/dist/artifacts/adapter.js +0 -23
  457. package/dist/artifacts/adapter.js.map +0 -1
  458. package/dist/artifacts/registry.d.ts +0 -21
  459. package/dist/artifacts/registry.d.ts.map +0 -1
  460. package/dist/artifacts/registry.js +0 -21
  461. package/dist/artifacts/registry.js.map +0 -1
  462. package/dist/config/errors.d.ts +0 -24
  463. package/dist/config/errors.d.ts.map +0 -1
  464. package/dist/config/errors.js +0 -19
  465. package/dist/config/errors.js.map +0 -1
  466. package/dist/config/load.d.ts +0 -9
  467. package/dist/config/load.d.ts.map +0 -1
  468. package/dist/config/load.js +0 -29
  469. package/dist/config/load.js.map +0 -1
  470. package/dist/config/schema.d.ts +0 -12
  471. package/dist/config/schema.d.ts.map +0 -1
  472. package/dist/config/schema.js +0 -19
  473. package/dist/config/schema.js.map +0 -1
  474. package/dist/domain/artifact.d.ts +0 -118
  475. package/dist/domain/artifact.d.ts.map +0 -1
  476. package/dist/domain/artifact.js +0 -197
  477. package/dist/domain/artifact.js.map +0 -1
  478. package/dist/domain/evidence.d.ts +0 -59
  479. package/dist/domain/evidence.d.ts.map +0 -1
  480. package/dist/domain/evidence.js +0 -51
  481. package/dist/domain/evidence.js.map +0 -1
  482. package/dist/domain/operation.d.ts +0 -143
  483. package/dist/domain/operation.d.ts.map +0 -1
  484. package/dist/domain/operation.js +0 -198
  485. package/dist/domain/operation.js.map +0 -1
  486. package/dist/domain/release.d.ts +0 -93
  487. package/dist/domain/release.d.ts.map +0 -1
  488. package/dist/domain/release.js +0 -82
  489. package/dist/domain/release.js.map +0 -1
  490. package/dist/domain/remote-state.d.ts +0 -58
  491. package/dist/domain/remote-state.d.ts.map +0 -1
  492. package/dist/domain/remote-state.js +0 -55
  493. package/dist/domain/remote-state.js.map +0 -1
  494. package/dist/domain/target.d.ts +0 -148
  495. package/dist/domain/target.d.ts.map +0 -1
  496. package/dist/domain/target.js +0 -151
  497. package/dist/domain/target.js.map +0 -1
  498. package/dist/host/host.d.ts +0 -32
  499. package/dist/host/host.d.ts.map +0 -1
  500. package/dist/host/host.js +0 -24
  501. package/dist/host/host.js.map +0 -1
  502. package/dist/host/http-live.d.ts +0 -6
  503. package/dist/host/http-live.d.ts.map +0 -1
  504. package/dist/host/http-live.js +0 -86
  505. package/dist/host/http-live.js.map +0 -1
  506. package/dist/host/http.d.ts +0 -43
  507. package/dist/host/http.d.ts.map +0 -1
  508. package/dist/host/http.js +0 -59
  509. package/dist/host/http.js.map +0 -1
  510. package/dist/host/platform.d.ts +0 -10
  511. package/dist/host/platform.d.ts.map +0 -1
  512. package/dist/host/platform.js +0 -114
  513. package/dist/host/platform.js.map +0 -1
  514. package/dist/host/test.d.ts +0 -23
  515. package/dist/host/test.d.ts.map +0 -1
  516. package/dist/host/test.js +0 -222
  517. package/dist/host/test.js.map +0 -1
  518. package/dist/internal/workspace-path.d.ts +0 -15
  519. package/dist/internal/workspace-path.d.ts.map +0 -1
  520. package/dist/internal/workspace-path.js +0 -36
  521. package/dist/internal/workspace-path.js.map +0 -1
  522. package/dist/planner/artifact-inventory.d.ts +0 -9
  523. package/dist/planner/artifact-inventory.d.ts.map +0 -1
  524. package/dist/planner/artifact-inventory.js +0 -86
  525. package/dist/planner/artifact-inventory.js.map +0 -1
  526. package/dist/planner/create-release-plan.d.ts +0 -5
  527. package/dist/planner/create-release-plan.d.ts.map +0 -1
  528. package/dist/planner/create-release-plan.js +0 -25
  529. package/dist/planner/create-release-plan.js.map +0 -1
  530. package/dist/planner/errors.d.ts +0 -67
  531. package/dist/planner/errors.d.ts.map +0 -1
  532. package/dist/planner/errors.js +0 -58
  533. package/dist/planner/errors.js.map +0 -1
  534. package/dist/planner/evidence-recorder.d.ts +0 -28
  535. package/dist/planner/evidence-recorder.d.ts.map +0 -1
  536. package/dist/planner/evidence-recorder.js +0 -362
  537. package/dist/planner/evidence-recorder.js.map +0 -1
  538. package/dist/planner/executor.d.ts +0 -58
  539. package/dist/planner/executor.d.ts.map +0 -1
  540. package/dist/planner/executor.js +0 -147
  541. package/dist/planner/executor.js.map +0 -1
  542. package/dist/planner/normalize-release.d.ts +0 -19
  543. package/dist/planner/normalize-release.d.ts.map +0 -1
  544. package/dist/planner/normalize-release.js +0 -342
  545. package/dist/planner/normalize-release.js.map +0 -1
  546. package/dist/planner/reconcile.d.ts +0 -17
  547. package/dist/planner/reconcile.d.ts.map +0 -1
  548. package/dist/planner/reconcile.js +0 -259
  549. package/dist/planner/reconcile.js.map +0 -1
  550. package/dist/planner/render-plan.d.ts +0 -15
  551. package/dist/planner/render-plan.d.ts.map +0 -1
  552. package/dist/planner/render-plan.js +0 -231
  553. package/dist/planner/render-plan.js.map +0 -1
  554. package/dist/targets/adapter-helpers.d.ts +0 -79
  555. package/dist/targets/adapter-helpers.d.ts.map +0 -1
  556. package/dist/targets/adapter-helpers.js +0 -194
  557. package/dist/targets/adapter-helpers.js.map +0 -1
  558. package/dist/targets/adapter.d.ts +0 -17
  559. package/dist/targets/adapter.d.ts.map +0 -1
  560. package/dist/targets/adapter.js +0 -2
  561. package/dist/targets/adapter.js.map +0 -1
  562. package/dist/targets/github-release.d.ts +0 -25
  563. package/dist/targets/github-release.d.ts.map +0 -1
  564. package/dist/targets/github-release.js +0 -82
  565. package/dist/targets/github-release.js.map +0 -1
  566. package/dist/targets/github.d.ts +0 -11
  567. package/dist/targets/github.d.ts.map +0 -1
  568. package/dist/targets/github.js +0 -117
  569. package/dist/targets/github.js.map +0 -1
  570. package/dist/targets/homebrew.d.ts +0 -11
  571. package/dist/targets/homebrew.d.ts.map +0 -1
  572. package/dist/targets/homebrew.js +0 -210
  573. package/dist/targets/homebrew.js.map +0 -1
  574. package/dist/targets/live.d.ts +0 -5
  575. package/dist/targets/live.d.ts.map +0 -1
  576. package/dist/targets/live.js +0 -50
  577. package/dist/targets/live.js.map +0 -1
  578. package/dist/targets/npm.d.ts +0 -10
  579. package/dist/targets/npm.d.ts.map +0 -1
  580. package/dist/targets/npm.js +0 -112
  581. package/dist/targets/npm.js.map +0 -1
  582. package/dist/targets/pypi.d.ts +0 -11
  583. package/dist/targets/pypi.d.ts.map +0 -1
  584. package/dist/targets/pypi.js +0 -141
  585. package/dist/targets/pypi.js.map +0 -1
  586. package/dist/targets/registry.d.ts +0 -25
  587. package/dist/targets/registry.d.ts.map +0 -1
  588. package/dist/targets/registry.js +0 -34
  589. package/dist/targets/registry.js.map +0 -1
  590. package/dist/targets/scoop.d.ts +0 -11
  591. package/dist/targets/scoop.d.ts.map +0 -1
  592. package/dist/targets/scoop.js +0 -88
  593. package/dist/targets/scoop.js.map +0 -1
  594. package/dist/types/effect-internal.d.ts +0 -5
  595. package/dist/types/effect-internal.d.ts.map +0 -1
  596. package/dist/types/effect-internal.js +0 -2
  597. package/dist/types/effect-internal.js.map +0 -1
  598. package/dist/workflows/config.d.ts +0 -202
  599. package/dist/workflows/config.d.ts.map +0 -1
  600. package/dist/workflows/config.js +0 -420
  601. package/dist/workflows/config.js.map +0 -1
  602. package/dist/workflows/diagnostics.d.ts +0 -62
  603. package/dist/workflows/diagnostics.d.ts.map +0 -1
  604. package/dist/workflows/diagnostics.js +0 -530
  605. package/dist/workflows/diagnostics.js.map +0 -1
  606. package/dist/workflows/distribution.d.ts +0 -25
  607. package/dist/workflows/distribution.d.ts.map +0 -1
  608. package/dist/workflows/distribution.js +0 -24
  609. package/dist/workflows/distribution.js.map +0 -1
  610. package/dist/workflows/evidence.d.ts +0 -17
  611. package/dist/workflows/evidence.d.ts.map +0 -1
  612. package/dist/workflows/evidence.js +0 -32
  613. package/dist/workflows/evidence.js.map +0 -1
  614. package/dist/workflows/index.d.ts +0 -8
  615. package/dist/workflows/index.d.ts.map +0 -1
  616. package/dist/workflows/index.js +0 -7
  617. package/dist/workflows/index.js.map +0 -1
  618. package/dist/workflows/init.d.ts +0 -84
  619. package/dist/workflows/init.d.ts.map +0 -1
  620. package/dist/workflows/init.js +0 -487
  621. package/dist/workflows/init.js.map +0 -1
  622. package/dist/workflows/live.d.ts +0 -9
  623. package/dist/workflows/live.d.ts.map +0 -1
  624. package/dist/workflows/live.js +0 -7
  625. package/dist/workflows/live.js.map +0 -1
  626. package/dist/workflows/options.d.ts +0 -30
  627. package/dist/workflows/options.d.ts.map +0 -1
  628. package/dist/workflows/options.js +0 -16
  629. package/dist/workflows/options.js.map +0 -1
  630. package/examples/non-strict-skips/artifacts/release-example-skips-0.1.0.tgz +0 -1
  631. package/examples/non-strict-skips/release.config.json +0 -31
  632. package/examples/pypi-registry/release.config.json +0 -31
  633. package/templates/github-actions/plan-and-approved-execute.yml +0 -58
  634. package/templates/github-actions/plan-only.yml +0 -33
  635. package/templates/github-actions/trusted-publishing.yml +0 -61
@@ -0,0 +1,101 @@
1
+ import * as Effect from "effect/Effect"
2
+ import * as Context from "effect/Context"
3
+ import * as Schema from "effect/Schema"
4
+ import type { SubjectId } from "../model/authority.js"
5
+ import type {
6
+ AnonymousAccess,
7
+ CredentialAuthorityError,
8
+ PublisherOperation,
9
+ ScopedSecret
10
+ } from "./authority.js"
11
+
12
+ /** Raw host transport failure. Provider meaning is assigned only by the
13
+ * authority-checking sink/adapter that knows whether dispatch started. */
14
+ export class PublicationHttpError
15
+ extends Schema.TaggedErrorClass<PublicationHttpError>()("PublicationHttpError", {
16
+ commitment: Schema.Literals(["before-dispatch", "unknown"]),
17
+ reason: Schema.String
18
+ }) {}
19
+
20
+ export type HttpRequest = {
21
+ readonly method: "GET" | "POST" | "PATCH"
22
+ readonly url: string
23
+ readonly headers?: Readonly<Record<string, string>>
24
+ readonly body?: Uint8Array | string
25
+ }
26
+ export type HttpResponse = {
27
+ readonly status: number
28
+ readonly headers: Readonly<Record<string, string>>
29
+ readonly body: Uint8Array | string
30
+ }
31
+ export type PublicationHttp = {
32
+ readonly request: (request: HttpRequest) => Effect.Effect<HttpResponse, PublicationHttpError>
33
+ }
34
+
35
+ /** Read-only HTTP intent; authorization is injected and consumed by the host. */
36
+ export interface HttpObservationRequest {
37
+ readonly subject: SubjectId
38
+ readonly method: "GET"
39
+ readonly url: string
40
+ readonly headers?: Readonly<Record<string, string>>
41
+ readonly body?: Uint8Array | string
42
+ }
43
+
44
+ /** Host failure shared by authorization implementations without exposing secrets. */
45
+ export interface HttpAuthorizationError {
46
+ readonly _tag: "CredentialPlatformError"
47
+ readonly phase: "observe" | "mutate" | "resource" | "spawn"
48
+ readonly commitment: "before-dispatch" | "unknown"
49
+ readonly reason: string
50
+ }
51
+
52
+ export interface MutationHttpRequest {
53
+ readonly method: "POST" | "PATCH"
54
+ readonly url: string
55
+ readonly headers?: Readonly<Record<string, string>>
56
+ readonly body?: Uint8Array | string
57
+ /** Host-owned credential projection; callers still never receive the secret. */
58
+ readonly credentialScheme?: "bearer" | "pypi-token-basic"
59
+ }
60
+
61
+ export interface AuthorizedMutationHttpShape {
62
+ readonly execute: (
63
+ operation: PublisherOperation,
64
+ request: MutationHttpRequest,
65
+ grant: ScopedSecret
66
+ ) => Effect.Effect<HttpResponse, CredentialAuthorityError | HttpAuthorizationError>
67
+ }
68
+
69
+ /** Host-owned mutation HTTP sink; callers never receive or inject credentials. */
70
+ export class AuthorizedMutationHttp
71
+ extends Context.Service<AuthorizedMutationHttp, AuthorizedMutationHttpShape>()(
72
+ "ts-release/AuthorizedMutationHttp"
73
+ ) {}
74
+
75
+ export interface HttpAuthorizerShape {
76
+ readonly execute: (
77
+ input: HttpObservationRequest,
78
+ grant: AnonymousAccess | ScopedSecret
79
+ ) => Effect.Effect<HttpResponse, CredentialAuthorityError | HttpAuthorizationError>
80
+ }
81
+
82
+ /** Opaque observation sink implemented by a host platform layer. */
83
+ export class HttpAuthorizer
84
+ extends Context.Service<HttpAuthorizer, HttpAuthorizerShape>()(
85
+ "ts-release/HttpAuthorizer"
86
+ ) {}
87
+
88
+ export const bodyText = (response: HttpResponse): string => typeof response.body === "string"
89
+ ? response.body : new TextDecoder("utf-8", { fatal: true }).decode(response.body)
90
+
91
+ export const bodyJson = (response: HttpResponse): unknown => {
92
+ try {
93
+ return JSON.parse(bodyText(response)) as unknown
94
+ } catch (cause) {
95
+ throw PublicationHttpError.make({ commitment: "before-dispatch", reason: cause instanceof Error ? cause.message : String(cause) })
96
+ }
97
+ }
98
+
99
+ export const authHeaders = (credential: string): Readonly<Record<string, string>> => ({
100
+ authorization: `Bearer ${credential}`, accept: "application/json"
101
+ })
@@ -0,0 +1,4 @@
1
+ export * from "./http.js"
2
+ export * from "./adapter.js"
3
+ export * from "./npm.js"
4
+ export * from "./github.js"
@@ -0,0 +1,525 @@
1
+ import { join } from "node:path"
2
+ import * as Effect from "effect/Effect"
3
+ import type { CredentialRequest, ResolvedAuthStrategy } from "../model/authority.js"
4
+ import { CredentialRequest as CredentialRequestSchema } from "../model/authority.js"
5
+ import {
6
+ digestEquals,
7
+ formatNpmSha1Shasum,
8
+ formatNpmSha512Sri,
9
+ formatSha256Hex,
10
+ parseNpmSha1Shasum,
11
+ parseNpmSha512Sri,
12
+ sha1Digest,
13
+ sha256Digest,
14
+ sha512Digest,
15
+ type Sha1Digest,
16
+ type Sha512Digest
17
+ } from "../model/digest.js"
18
+ import { NonEmptyName } from "../model/primitives.js"
19
+ import type { PreparedNpmPublication } from "../release/prepared.js"
20
+ import type { PreparedBundle } from "../release/prepared-store.js"
21
+ import type { CredentialGrant, MutationCredentialGrant } from "./authority.js"
22
+ import type {
23
+ CertifiedPublisherResult,
24
+ CertifiedPublisherSpawnShape,
25
+ NpmPublishOperation,
26
+ NpmUserConfigResourceShape
27
+ } from "./publisher.js"
28
+ import type { HttpAuthorizerShape } from "./http.js"
29
+ import {
30
+ ReleaseSubjectError,
31
+ type ReleaseObservationContext,
32
+ type ReleaseSubject
33
+ } from "./coordinator.js"
34
+ import {
35
+ Conflict,
36
+ AbsenceBasis,
37
+ AuthoritativelyAbsent,
38
+ CreateAuthorizationProof,
39
+ Difference,
40
+ InconclusiveObservation,
41
+ MutationPrecondition,
42
+ NeedsMutation,
43
+ OutcomeUnknown,
44
+ PresentEquivalent,
45
+ PresentDifferent,
46
+ ProviderAlreadyEquivalent,
47
+ ProviderAuthorizedCreate,
48
+ ProviderBlocked,
49
+ RejectedBeforeDispatch,
50
+ SafeReason,
51
+ VisibilityBasis,
52
+ VisibilityPending,
53
+ type MutationDecision,
54
+ type Observation,
55
+ type ProviderDecision
56
+ } from "./report.js"
57
+ import { makeRecoveryCapabilityProfile } from "./recovery.js"
58
+
59
+ /**
60
+ * Timing values are policy bounds, not measured provider facts. They remain
61
+ * ASSUMED/UNVERIFIED until an explicitly authorized live run records evidence.
62
+ */
63
+ export const npmRecoveryCapabilityProfile = makeRecoveryCapabilityProfile({
64
+ observation: "conditional",
65
+ authoritativeAbsence: "provider-specific",
66
+ createAuthorization: "authenticated-namespace-and-unique-coordinate",
67
+ replay: "coordinate-unique",
68
+ identifierReuse: "consumed-after-delete",
69
+ // The authored correction surface currently produces an operator proposal;
70
+ // no conditional npm correction adapter is installed.
71
+ correction: [],
72
+ exposure: "persistent-to-consumers",
73
+ historyRequirement: "optional-evidence",
74
+ readConvergence: {
75
+ contract: {
76
+ _tag: "assumed",
77
+ basis: "ASSUMED/UNVERIFIED: no authorized live mutation evidence establishes npm read-convergence timing."
78
+ },
79
+ observationRetry: {
80
+ maxAttempts: 6,
81
+ backoff: { baseMs: 2_000, factor: 2, capMs: 30_000 },
82
+ totalBudgetMs: 120_000
83
+ },
84
+ retryEligible: "VisibilityPending | Inconclusive",
85
+ exhaustion: "UncertainSubject with full trace"
86
+ }
87
+ })
88
+
89
+ /** Primary provider documentation reviewed for this protocol implementation. */
90
+ export const npmProviderProtocolDocumentation = Object.freeze({
91
+ reviewedAt: "2026-08-12",
92
+ packageMetadata: "https://github.com/npm/registry/blob/main/docs/responses/package-metadata.md",
93
+ publish: "https://docs.npmjs.com/cli/v11/commands/npm-publish/",
94
+ distTags: "https://docs.npmjs.com/adding-dist-tags-to-packages/",
95
+ trustedPublishing: "https://docs.npmjs.com/trusted-publishers/"
96
+ })
97
+
98
+ type NpmPublicationContract = PreparedNpmPublication & {
99
+ readonly distTag: { readonly toString: () => string }
100
+ readonly access: "public" | "restricted"
101
+ readonly authentication:
102
+ | { readonly strategy: "token" }
103
+ | {
104
+ readonly strategy: "trusted-publishing"
105
+ readonly attestation: {
106
+ readonly provider: "github-actions"
107
+ readonly runner: "github-hosted"
108
+ readonly repository: string
109
+ readonly workflow: string
110
+ readonly workflowRef: string
111
+ readonly allowedAction: "npm-publish-direct"
112
+ }
113
+ }
114
+ readonly provenance: "automatic" | "required" | "disabled"
115
+ }
116
+
117
+ const contractOf = (publication: PreparedNpmPublication): NpmPublicationContract =>
118
+ publication as NpmPublicationContract
119
+
120
+ const fingerprint = (value: string): SafeReason => SafeReason.make(
121
+ `provider value sha256-${formatSha256Hex(sha256Digest(new TextEncoder().encode(value)))}`
122
+ )
123
+
124
+ const registryEndpoint = (publication: NpmPublicationContract): string => {
125
+ const value = publication.registryUrl.toString()
126
+ return value.endsWith("/") ? value : `${value}/`
127
+ }
128
+
129
+ const registryPackageUrl = (publication: NpmPublicationContract): string =>
130
+ `${registryEndpoint(publication)}${encodeURIComponent(publication.packageName).replace(/^%40/u, "@")}`
131
+
132
+ const asObject = (value: unknown): Readonly<Record<string, unknown>> | undefined =>
133
+ typeof value === "object" && value !== null && !Array.isArray(value)
134
+ ? value as Readonly<Record<string, unknown>>
135
+ : undefined
136
+
137
+ const parseJson = (body: Uint8Array | string): unknown | undefined => {
138
+ try {
139
+ const text = typeof body === "string"
140
+ ? body
141
+ : new TextDecoder("utf-8", { fatal: true }).decode(body)
142
+ return JSON.parse(text) as unknown
143
+ } catch {
144
+ return undefined
145
+ }
146
+ }
147
+
148
+ type RegistryPackageFacts = {
149
+ readonly name: string
150
+ readonly versions: Readonly<Record<string, unknown>>
151
+ readonly distTags: Readonly<Record<string, unknown>>
152
+ }
153
+
154
+ const registryPackageFacts = (value: unknown): RegistryPackageFacts | undefined => {
155
+ const metadata = asObject(value)
156
+ if (metadata === undefined || typeof metadata.name !== "string") return undefined
157
+ const versions = asObject(metadata.versions)
158
+ const distTags = asObject(metadata["dist-tags"])
159
+ return versions === undefined || distTags === undefined
160
+ ? undefined
161
+ : { name: metadata.name, versions, distTags }
162
+ }
163
+
164
+ type RegistryVersionFacts = {
165
+ readonly name: string
166
+ readonly version: string
167
+ readonly integrity: Sha512Digest
168
+ readonly shasum: Sha1Digest
169
+ }
170
+
171
+ const registryVersionFacts = (value: unknown): RegistryVersionFacts | undefined => {
172
+ const metadata = asObject(value)
173
+ const dist = metadata === undefined ? undefined : asObject(metadata.dist)
174
+ if (metadata === undefined || dist === undefined || typeof metadata.name !== "string" ||
175
+ typeof metadata.version !== "string") return undefined
176
+ try {
177
+ return {
178
+ name: metadata.name,
179
+ version: metadata.version,
180
+ integrity: parseNpmSha512Sri(dist.integrity),
181
+ shasum: parseNpmSha1Shasum(dist.shasum)
182
+ }
183
+ } catch {
184
+ return undefined
185
+ }
186
+ }
187
+
188
+ const observationRequests = (
189
+ publication: PreparedNpmPublication
190
+ ): readonly [CredentialRequest, ...Array<CredentialRequest>] => {
191
+ const make = (strategy: ResolvedAuthStrategy): CredentialRequest => CredentialRequestSchema.make({
192
+ subject: publication.authority.subject,
193
+ provider: publication.authority.provider,
194
+ audience: publication.authority.audience,
195
+ purpose: "observe",
196
+ strategy
197
+ })
198
+ const first = publication.authority.observationStrategies[0]!
199
+ return [make(first), ...publication.authority.observationStrategies.slice(1).map(make)]
200
+ }
201
+
202
+ const mutationRequest = (publication: PreparedNpmPublication): CredentialRequest =>
203
+ CredentialRequestSchema.make({
204
+ subject: publication.authority.subject,
205
+ provider: publication.authority.provider,
206
+ audience: publication.authority.audience,
207
+ purpose: "publish",
208
+ strategy: publication.authority.publishStrategy
209
+ })
210
+
211
+ const inconclusive = (
212
+ publication: PreparedNpmPublication,
213
+ reason: string
214
+ ): InconclusiveObservation => InconclusiveObservation.make({
215
+ subject: publication.authority.subject,
216
+ reason: SafeReason.make(reason)
217
+ })
218
+
219
+ const difference = (
220
+ field: "name" | "version" | "integrity" | "shasum" | "dist-tag",
221
+ expected: string,
222
+ observed: string
223
+ ): Difference =>
224
+ Difference.make({
225
+ field: NonEmptyName.make(field),
226
+ expected: SafeReason.make(expected),
227
+ observed: fingerprint(observed)
228
+ })
229
+
230
+ const visibleVersionAbsent = (publication: NpmPublicationContract): AuthoritativelyAbsent =>
231
+ AuthoritativelyAbsent.make({
232
+ subject: publication.authority.subject,
233
+ basis: AbsenceBasis.make({
234
+ kind: NonEmptyName.make("npm-visible-package-version-absent"),
235
+ detail: SafeReason.make("Authoritative package metadata omitted the exact prepared version coordinate.")
236
+ })
237
+ })
238
+
239
+ const trustedDirectCreate = (publication: NpmPublicationContract): boolean =>
240
+ publication.authentication.strategy === "trusted-publishing" &&
241
+ publication.authentication.attestation.provider === "github-actions" &&
242
+ publication.authentication.attestation.runner === "github-hosted" &&
243
+ publication.authentication.attestation.allowedAction === "npm-publish-direct" &&
244
+ publication.authority.publishStrategy.kind === "trusted-publishing" &&
245
+ publication.authority.publishStrategy.repository === publication.authentication.attestation.repository &&
246
+ publication.authority.publishStrategy.workflow ===
247
+ `.github/workflows/${publication.authentication.attestation.workflow}` &&
248
+ publication.authority.publishStrategy.workflowRef === publication.authentication.attestation.workflowRef &&
249
+ publication.authority.publishStrategy.allowedAction === "npm-publish-direct" &&
250
+ publication.authority.publishStrategy.publisherSink === "certified-npm-cli"
251
+
252
+ const authorizedCreateAbsence = (publication: NpmPublicationContract): AuthoritativelyAbsent =>
253
+ AuthoritativelyAbsent.make({
254
+ subject: publication.authority.subject,
255
+ basis: AbsenceBasis.make({
256
+ kind: NonEmptyName.make("npm-trusted-direct-create"),
257
+ detail: SafeReason.make("The prepared trusted-publishing attestation authorizes this exact direct-create coordinate.")
258
+ })
259
+ })
260
+
261
+ const visibilityPending = (publication: NpmPublicationContract): VisibilityPending =>
262
+ VisibilityPending.make({
263
+ subject: publication.authority.subject,
264
+ expectation: SafeReason.make("The exact published npm version and dist-tag become visible."),
265
+ basis: VisibilityBasis.make({
266
+ kind: NonEmptyName.make("npm-post-publish-read"),
267
+ detail: SafeReason.make("The same invocation dispatched one publish and is rereading provider metadata only.")
268
+ })
269
+ })
270
+
271
+ const decide = (
272
+ publication: NpmPublicationContract,
273
+ observation: Observation
274
+ ): ProviderDecision => {
275
+ switch (observation._tag) {
276
+ case "PresentEquivalent":
277
+ return ProviderAlreadyEquivalent.make({ subject: publication.authority.subject })
278
+ case "PresentDifferent":
279
+ return Conflict.make({ subject: publication.authority.subject, differences: observation.differences })
280
+ case "AuthoritativelyAbsent":
281
+ return observation.basis.kind === "npm-visible-package-version-absent"
282
+ ? NeedsMutation.make({
283
+ subject: publication.authority.subject,
284
+ precondition: MutationPrecondition.make({ kind: NonEmptyName.make("npm-visible-package-version-absent") })
285
+ })
286
+ : trustedDirectCreate(publication) && observation.basis.kind === "npm-trusted-direct-create"
287
+ ? ProviderAuthorizedCreate.make({
288
+ subject: publication.authority.subject,
289
+ proof: CreateAuthorizationProof.make({ kind: NonEmptyName.make("npm-trusted-direct-create") })
290
+ })
291
+ : ProviderBlocked.make({
292
+ subject: publication.authority.subject,
293
+ reason: SafeReason.make("The npm namespace has no exact prepared create authorization.")
294
+ })
295
+ case "VisibilityPending":
296
+ case "Inconclusive":
297
+ return ProviderBlocked.make({
298
+ subject: publication.authority.subject,
299
+ reason: SafeReason.make("npm observation did not prove exact equivalence or an authorized absent coordinate.")
300
+ })
301
+ }
302
+ }
303
+
304
+ const publishOperation = (
305
+ publication: NpmPublicationContract,
306
+ decision: MutationDecision
307
+ ): NpmPublishOperation => ({
308
+ _tag: "PublishOperation",
309
+ subject: publication.authority.subject,
310
+ provider: publication.authority.provider,
311
+ audience: publication.authority.audience,
312
+ purpose: "publish",
313
+ decision
314
+ })
315
+
316
+ const sinkFailure = (publication: NpmPublicationContract, cause: unknown): ReleaseSubjectError =>
317
+ new ReleaseSubjectError({
318
+ subject: publication.authority.subject,
319
+ phase: "mutate",
320
+ commitment: typeof cause === "object" && cause !== null && "commitment" in cause && cause.commitment === "unknown"
321
+ ? "unknown"
322
+ : "before-dispatch",
323
+ reason: SafeReason.make("The certified npm publisher boundary rejected or lost the prepared operation.")
324
+ })
325
+
326
+ const publisherAttempt = (
327
+ publication: NpmPublicationContract,
328
+ result: CertifiedPublisherResult
329
+ ): RejectedBeforeDispatch | OutcomeUnknown => result._tag === "RejectedBeforeStart"
330
+ ? RejectedBeforeDispatch.make({
331
+ subject: publication.authority.subject,
332
+ reason: SafeReason.make("The certified npm publisher process did not start.")
333
+ })
334
+ : OutcomeUnknown.make({
335
+ subject: publication.authority.subject,
336
+ reason: SafeReason.make(result._tag === "PublisherExited"
337
+ ? "The npm publisher started and exited; exact registry reobservation must establish its effect."
338
+ : "The npm publisher started, but its terminal process result was unavailable.")
339
+ })
340
+
341
+ const validMutationDecision = (
342
+ publication: NpmPublicationContract,
343
+ decision: MutationDecision
344
+ ): boolean => decision._tag === "NeedsMutation"
345
+ ? decision.precondition.kind === "npm-visible-package-version-absent"
346
+ : decision.proof.kind === "npm-trusted-direct-create" && trustedDirectCreate(publication)
347
+
348
+ /** Exact Plan-225 npm subject over host-owned observation, credential, and process sinks. */
349
+ export const makeNpmSubject = (
350
+ bundle: PreparedBundle,
351
+ publication: PreparedNpmPublication,
352
+ http: HttpAuthorizerShape,
353
+ userConfigs: NpmUserConfigResourceShape,
354
+ publisher: CertifiedPublisherSpawnShape
355
+ ): ReleaseSubject => {
356
+ const intent = contractOf(publication)
357
+ const packageArtifact = bundle.manifest.artifacts.find((artifact) =>
358
+ artifact.id.toString() === intent.artifactId.toString())
359
+ const bytes = bundle.blobs.get(intent.artifactId.toString())
360
+ const expectedIntegrity = bytes === undefined ? undefined : sha512Digest(bytes)
361
+ const expectedShasum = bytes === undefined ? undefined : sha1Digest(bytes)
362
+ const tarballPath = packageArtifact === undefined
363
+ ? undefined
364
+ : join(bundle.directory, "blobs", packageArtifact.blob.hex)
365
+
366
+ const observe = Effect.fn("NpmReleaseSubject.observe")(function*(
367
+ grant: CredentialGrant,
368
+ context: ReleaseObservationContext
369
+ ) {
370
+ if (bytes === undefined || packageArtifact === undefined || tarballPath === undefined ||
371
+ expectedIntegrity === undefined || expectedShasum === undefined) {
372
+ return inconclusive(intent, "The exact prepared npm artifact bytes are unavailable.")
373
+ }
374
+ if (grant._tag === "WorkloadIdentity") {
375
+ return yield* new ReleaseSubjectError({
376
+ subject: publication.authority.subject,
377
+ phase: "observe",
378
+ commitment: "before-dispatch",
379
+ reason: SafeReason.make("Workload identity cannot authorize npm metadata observation.")
380
+ })
381
+ }
382
+ const response = yield* http.execute({
383
+ subject: intent.authority.subject,
384
+ method: "GET",
385
+ url: registryPackageUrl(intent),
386
+ headers: { accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8" }
387
+ }, grant).pipe(Effect.mapError((cause) => new ReleaseSubjectError({
388
+ subject: intent.authority.subject,
389
+ phase: "observe",
390
+ commitment: cause._tag === "CredentialPlatformError" ? cause.commitment : "before-dispatch",
391
+ reason: SafeReason.make("npm metadata observation could not be completed by the host HTTP boundary.")
392
+ })))
393
+
394
+ if (response.status === 404) {
395
+ if (context.phase === "post-mutation" && context.attempt._tag !== "RejectedBeforeDispatch") {
396
+ return visibilityPending(intent)
397
+ }
398
+ return trustedDirectCreate(intent)
399
+ ? authorizedCreateAbsence(intent)
400
+ : inconclusive(intent, "npm package visibility is unavailable and no trusted direct-create proof exists.")
401
+ }
402
+ if (response.status < 200 || response.status >= 300) {
403
+ return inconclusive(intent, `npm metadata observation returned HTTP ${response.status}.`)
404
+ }
405
+
406
+ const packument = registryPackageFacts(parseJson(response.body))
407
+ if (packument === undefined) {
408
+ return inconclusive(intent, "npm package metadata was malformed or omitted versions or dist-tags.")
409
+ }
410
+ if (packument.name !== intent.packageName) {
411
+ return PresentDifferent.make({
412
+ subject: intent.authority.subject,
413
+ differences: [difference("name", intent.packageName.toString(), packument.name)]
414
+ })
415
+ }
416
+ const rawVersion = packument.versions[intent.version.toString()]
417
+ if (rawVersion === undefined) {
418
+ return context.phase === "post-mutation" && context.attempt._tag !== "RejectedBeforeDispatch"
419
+ ? visibilityPending(intent)
420
+ : visibleVersionAbsent(intent)
421
+ }
422
+ const observed = registryVersionFacts(rawVersion)
423
+ if (observed === undefined) return inconclusive(intent, "The exact npm version metadata was malformed.")
424
+
425
+ const differences: Array<Difference> = []
426
+ if (observed.name !== intent.packageName) {
427
+ differences.push(difference("name", intent.packageName.toString(), observed.name))
428
+ }
429
+ if (observed.version !== intent.version) {
430
+ differences.push(difference("version", intent.version.toString(), observed.version))
431
+ }
432
+ if (!digestEquals(observed.integrity, expectedIntegrity)) {
433
+ differences.push(difference(
434
+ "integrity",
435
+ formatNpmSha512Sri(expectedIntegrity),
436
+ formatNpmSha512Sri(observed.integrity)
437
+ ))
438
+ }
439
+ if (!digestEquals(observed.shasum, expectedShasum)) {
440
+ differences.push(difference(
441
+ "shasum",
442
+ formatNpmSha1Shasum(expectedShasum),
443
+ formatNpmSha1Shasum(observed.shasum)
444
+ ))
445
+ }
446
+ if (differences.length > 0) {
447
+ return PresentDifferent.make({
448
+ subject: intent.authority.subject,
449
+ differences: differences as [Difference, ...Array<Difference>]
450
+ })
451
+ }
452
+ const tag = packument.distTags[intent.distTag.toString()]
453
+ if (tag !== intent.version) {
454
+ if (context.phase === "post-mutation" && context.attempt._tag !== "RejectedBeforeDispatch") {
455
+ return visibilityPending(intent)
456
+ }
457
+ return PresentDifferent.make({
458
+ subject: intent.authority.subject,
459
+ differences: [difference(
460
+ "dist-tag",
461
+ intent.version.toString(),
462
+ typeof tag === "string" ? tag : "<missing>"
463
+ )]
464
+ })
465
+ }
466
+ return PresentEquivalent.make({ subject: intent.authority.subject })
467
+ })
468
+
469
+ const mutate = (
470
+ decision: MutationDecision,
471
+ grant: MutationCredentialGrant
472
+ ) => {
473
+ if (!validMutationDecision(intent, decision) || tarballPath === undefined) {
474
+ return Effect.fail(new ReleaseSubjectError({
475
+ subject: intent.authority.subject,
476
+ phase: "mutate",
477
+ commitment: "before-dispatch",
478
+ reason: SafeReason.make("The npm mutation lacks its exact prepared absence proof or tarball path.")
479
+ }))
480
+ }
481
+ const operation = publishOperation(intent, decision)
482
+ const publisherSpec = {
483
+ operation,
484
+ cwd: bundle.directory,
485
+ tarballPath,
486
+ packageName: intent.packageName,
487
+ version: intent.version,
488
+ registryUrl: intent.registryUrl,
489
+ distTag: intent.distTag,
490
+ access: intent.access,
491
+ provenance: intent.provenance
492
+ } as const
493
+ return Effect.scoped(Effect.gen(function*() {
494
+ if (grant._tag === "WorkloadIdentity") {
495
+ yield* publisher.preflightTrustedNpm(operation, grant)
496
+ return yield* publisher.spawn({
497
+ _tag: "WorkloadPublisherSpec",
498
+ ...publisherSpec
499
+ }, grant)
500
+ }
501
+ const userConfig = yield* userConfigs.acquire({
502
+ operation,
503
+ registryUrl: registryEndpoint(intent)
504
+ }, grant)
505
+ return yield* publisher.spawn({
506
+ _tag: "NpmPublisherSpec",
507
+ ...publisherSpec,
508
+ userConfig
509
+ }, grant)
510
+ })).pipe(
511
+ Effect.map((result) => publisherAttempt(intent, result)),
512
+ Effect.mapError((cause) => sinkFailure(intent, cause))
513
+ )
514
+ }
515
+
516
+ return {
517
+ id: intent.authority.subject,
518
+ recovery: npmRecoveryCapabilityProfile,
519
+ observationRequests: observationRequests(intent),
520
+ mutationRequest: mutationRequest(intent),
521
+ observe,
522
+ decide: (observation) => decide(intent, observation),
523
+ mutate
524
+ }
525
+ }