@geekmidas/cli 10.0.0-alpha.10 → 10.0.0-alpha.101

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 (489) hide show
  1. package/README.md +315 -414
  2. package/bin/adjacent-tsconfig.mjs +46 -8
  3. package/bin/gkm.mjs +11 -3
  4. package/bin/owning-tsconfig-jsx-register.mjs +18 -0
  5. package/bin/owning-tsconfig-jsx.mjs +108 -0
  6. package/dist/EndpointGenerator-Br97xgs_.mjs +1031 -0
  7. package/dist/EndpointGenerator-Br97xgs_.mjs.map +1 -0
  8. package/dist/EndpointGenerator-By5_tYE9.cjs +1090 -0
  9. package/dist/EndpointGenerator-By5_tYE9.cjs.map +1 -0
  10. package/dist/GoDaddyProvider-BOuLf_Py.cjs +388 -0
  11. package/dist/GoDaddyProvider-BOuLf_Py.cjs.map +1 -0
  12. package/dist/GoDaddyProvider-u9MF-Dqk.mjs +388 -0
  13. package/dist/GoDaddyProvider-u9MF-Dqk.mjs.map +1 -0
  14. package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-BNpS9aRJ.mjs} +29 -25
  15. package/dist/HostingerProvider-BNpS9aRJ.mjs.map +1 -0
  16. package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-DR1iws1P.cjs} +29 -25
  17. package/dist/HostingerProvider-DR1iws1P.cjs.map +1 -0
  18. package/dist/LegacyStateStore-DWmHGNgH.cjs +124 -0
  19. package/dist/LegacyStateStore-DWmHGNgH.cjs.map +1 -0
  20. package/dist/LegacyStateStore-vhkx7Bbq.mjs +124 -0
  21. package/dist/LegacyStateStore-vhkx7Bbq.mjs.map +1 -0
  22. package/dist/LocalStateStore-BVKDADoG.cjs +178 -0
  23. package/dist/LocalStateStore-BVKDADoG.cjs.map +1 -0
  24. package/dist/LocalStateStore-FVsg0UoM.mjs +167 -0
  25. package/dist/LocalStateStore-FVsg0UoM.mjs.map +1 -0
  26. package/dist/OpenApiTsGenerator-BgSX_Z-e.cjs +541 -0
  27. package/dist/OpenApiTsGenerator-BgSX_Z-e.cjs.map +1 -0
  28. package/dist/OpenApiTsGenerator-C8aTX--y.mjs +536 -0
  29. package/dist/OpenApiTsGenerator-C8aTX--y.mjs.map +1 -0
  30. package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-Bllus2NR.cjs} +21 -22
  31. package/dist/Route53Provider-Bllus2NR.cjs.map +1 -0
  32. package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-QXxjkZO1.mjs} +13 -13
  33. package/dist/Route53Provider-QXxjkZO1.mjs.map +1 -0
  34. package/dist/S3StateStore-B8seZUsw.mjs +223 -0
  35. package/dist/S3StateStore-B8seZUsw.mjs.map +1 -0
  36. package/dist/S3StateStore-B_2gE9Un.cjs +222 -0
  37. package/dist/S3StateStore-B_2gE9Un.cjs.map +1 -0
  38. package/dist/SSMStateStore-CTDEI5Bi.cjs +204 -0
  39. package/dist/SSMStateStore-CTDEI5Bi.cjs.map +1 -0
  40. package/dist/SSMStateStore-DGTbBomw.mjs +205 -0
  41. package/dist/SSMStateStore-DGTbBomw.mjs.map +1 -0
  42. package/dist/SubscriberGenerator-1-IsjIwF.mjs +449 -0
  43. package/dist/SubscriberGenerator-1-IsjIwF.mjs.map +1 -0
  44. package/dist/SubscriberGenerator-BlIOdbi-.cjs +490 -0
  45. package/dist/SubscriberGenerator-BlIOdbi-.cjs.map +1 -0
  46. package/dist/add-BB2tLVc2.cjs +720 -0
  47. package/dist/add-BB2tLVc2.cjs.map +1 -0
  48. package/dist/add-CIbhGE5v.mjs +718 -0
  49. package/dist/add-CIbhGE5v.mjs.map +1 -0
  50. package/dist/appPorts-C9z9Pzn9.mjs +223 -0
  51. package/dist/appPorts-C9z9Pzn9.mjs.map +1 -0
  52. package/dist/appPorts-Cu79hJF6.cjs +264 -0
  53. package/dist/appPorts-Cu79hJF6.cjs.map +1 -0
  54. package/dist/aws-8QQ8n-t6.mjs +89 -0
  55. package/dist/aws-8QQ8n-t6.mjs.map +1 -0
  56. package/dist/aws-DY9NqQIT.cjs +100 -0
  57. package/dist/aws-DY9NqQIT.cjs.map +1 -0
  58. package/dist/awsStore-Bx5nCFnS.mjs +121 -0
  59. package/dist/awsStore-Bx5nCFnS.mjs.map +1 -0
  60. package/dist/awsStore-u3ehhMoY.cjs +138 -0
  61. package/dist/awsStore-u3ehhMoY.cjs.map +1 -0
  62. package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-C8DnCmxK.mjs} +11 -8
  63. package/dist/backup-provisioner-C8DnCmxK.mjs.map +1 -0
  64. package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-oDEsPj02.cjs} +22 -20
  65. package/dist/backup-provisioner-oDEsPj02.cjs.map +1 -0
  66. package/dist/backups/runner.cjs +519 -0
  67. package/dist/backups/runner.cjs.map +1 -0
  68. package/dist/backups/runner.d.cts +102 -0
  69. package/dist/backups/runner.d.cts.map +1 -0
  70. package/dist/backups/runner.d.mts +102 -0
  71. package/dist/backups/runner.d.mts.map +1 -0
  72. package/dist/backups/runner.mjs +506 -0
  73. package/dist/backups/runner.mjs.map +1 -0
  74. package/dist/{bundler-BY1OmV1e.cjs → bundler-Ba6BER3w.cjs} +38 -35
  75. package/dist/bundler-Ba6BER3w.cjs.map +1 -0
  76. package/dist/{bundler-Be8Zg4Wd.mjs → bundler-CHjRYVKh.mjs} +36 -32
  77. package/dist/bundler-CHjRYVKh.mjs.map +1 -0
  78. package/dist/cli-CtlqYRlN.cjs +71 -0
  79. package/dist/cli-CtlqYRlN.cjs.map +1 -0
  80. package/dist/cli-DOlkhrsh.mjs +71 -0
  81. package/dist/cli-DOlkhrsh.mjs.map +1 -0
  82. package/dist/compose-FDP_TaFt.mjs +3154 -0
  83. package/dist/compose-FDP_TaFt.mjs.map +1 -0
  84. package/dist/compose-uAWLy-nR.cjs +3267 -0
  85. package/dist/compose-uAWLy-nR.cjs.map +1 -0
  86. package/dist/config-D48erO2j.d.mts +269 -0
  87. package/dist/config-D48erO2j.d.mts.map +1 -0
  88. package/dist/config-DHDtsQrB.d.cts +269 -0
  89. package/dist/config-DHDtsQrB.d.cts.map +1 -0
  90. package/dist/config.cjs +421 -11
  91. package/dist/config.cjs.map +1 -0
  92. package/dist/config.d.cts +4 -120
  93. package/dist/config.d.mts +4 -120
  94. package/dist/config.mjs +405 -4
  95. package/dist/config.mjs.map +1 -0
  96. package/dist/credentialSchemas-DDda4Mmm.cjs +272 -0
  97. package/dist/credentialSchemas-DDda4Mmm.cjs.map +1 -0
  98. package/dist/credentialSchemas-DvitraL-.mjs +237 -0
  99. package/dist/credentialSchemas-DvitraL-.mjs.map +1 -0
  100. package/dist/credentials-B5N5yKk6.mjs +267 -0
  101. package/dist/credentials-B5N5yKk6.mjs.map +1 -0
  102. package/dist/credentials-Zqr3QQYB.cjs +350 -0
  103. package/dist/credentials-Zqr3QQYB.cjs.map +1 -0
  104. package/dist/databases-BeGP5eDh.mjs +495 -0
  105. package/dist/databases-BeGP5eDh.mjs.map +1 -0
  106. package/dist/databases-DGALFDG3.cjs +598 -0
  107. package/dist/databases-DGALFDG3.cjs.map +1 -0
  108. package/dist/define-6poNqm5O.mjs +106 -0
  109. package/dist/define-6poNqm5O.mjs.map +1 -0
  110. package/dist/define-crmMcXFS.cjs +153 -0
  111. package/dist/define-crmMcXFS.cjs.map +1 -0
  112. package/dist/deploy/public.cjs +212 -0
  113. package/dist/deploy/public.cjs.map +1 -0
  114. package/dist/deploy/public.d.cts +653 -0
  115. package/dist/deploy/public.d.cts.map +1 -0
  116. package/dist/deploy/public.d.mts +653 -0
  117. package/dist/deploy/public.d.mts.map +1 -0
  118. package/dist/deploy/public.mjs +145 -0
  119. package/dist/deploy/public.mjs.map +1 -0
  120. package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
  121. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
  122. package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
  123. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
  124. package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
  125. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
  126. package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
  127. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
  128. package/dist/deploy/sniffer-envparser-worker.cjs +54 -0
  129. package/dist/deploy/sniffer-envparser-worker.cjs.map +1 -0
  130. package/dist/deploy/sniffer-envparser-worker.d.cts +1 -0
  131. package/dist/deploy/sniffer-envparser-worker.d.mts +1 -0
  132. package/dist/deploy/sniffer-envparser-worker.mjs +55 -0
  133. package/dist/deploy/sniffer-envparser-worker.mjs.map +1 -0
  134. package/dist/deploy/sniffer-hooks.cjs +13 -7
  135. package/dist/deploy/sniffer-hooks.cjs.map +1 -1
  136. package/dist/deploy/sniffer-hooks.d.cts +1 -2
  137. package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
  138. package/dist/deploy/sniffer-hooks.d.mts +1 -2
  139. package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
  140. package/dist/deploy/sniffer-hooks.mjs +10 -3
  141. package/dist/deploy/sniffer-hooks.mjs.map +1 -1
  142. package/dist/deploy/sniffer-loader.cjs +16 -7
  143. package/dist/deploy/sniffer-loader.cjs.map +1 -1
  144. package/dist/deploy/sniffer-loader.d.cts +1 -1
  145. package/dist/deploy/sniffer-loader.d.mts +1 -1
  146. package/dist/deploy/sniffer-loader.mjs +14 -3
  147. package/dist/deploy/sniffer-loader.mjs.map +1 -1
  148. package/dist/deploy/sniffer-routes-worker.cjs +11 -11
  149. package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
  150. package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
  151. package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
  152. package/dist/deploy/sniffer-routes-worker.mjs +4 -4
  153. package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
  154. package/dist/deploy/sniffer-worker.cjs +15 -6
  155. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  156. package/dist/deploy/sniffer-worker.d.cts +1 -3
  157. package/dist/deploy/sniffer-worker.d.cts.map +1 -1
  158. package/dist/deploy/sniffer-worker.d.mts +1 -3
  159. package/dist/deploy/sniffer-worker.d.mts.map +1 -1
  160. package/dist/deploy/sniffer-worker.mjs +15 -4
  161. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  162. package/dist/deploy-DUUc3jV9.cjs +2390 -0
  163. package/dist/deploy-DUUc3jV9.cjs.map +1 -0
  164. package/dist/deploy-DgZxTnGS.mjs +2317 -0
  165. package/dist/deploy-DgZxTnGS.mjs.map +1 -0
  166. package/dist/derive-B4vDpzgP.mjs +150 -0
  167. package/dist/derive-B4vDpzgP.mjs.map +1 -0
  168. package/dist/derive-DAbo49sm.cjs +161 -0
  169. package/dist/derive-DAbo49sm.cjs.map +1 -0
  170. package/dist/discover-BfhVW_kT.cjs +600 -0
  171. package/dist/discover-BfhVW_kT.cjs.map +1 -0
  172. package/dist/discover-CvTtV5ZD.d.cts +108 -0
  173. package/dist/discover-CvTtV5ZD.d.cts.map +1 -0
  174. package/dist/discover-W2kab9Lc.d.mts +108 -0
  175. package/dist/discover-W2kab9Lc.d.mts.map +1 -0
  176. package/dist/discover-kziEht4W.mjs +527 -0
  177. package/dist/discover-kziEht4W.mjs.map +1 -0
  178. package/dist/dns-DDDCfj75.mjs +926 -0
  179. package/dist/dns-DDDCfj75.mjs.map +1 -0
  180. package/dist/dns-DnE_02tB.cjs +1057 -0
  181. package/dist/dns-DnE_02tB.cjs.map +1 -0
  182. package/dist/dokploy-BrfdeVEu.cjs +38 -0
  183. package/dist/dokploy-BrfdeVEu.cjs.map +1 -0
  184. package/dist/dokploy-DBlGSdnb.mjs +38 -0
  185. package/dist/dokploy-DBlGSdnb.mjs.map +1 -0
  186. package/dist/drivers-BLU1fNs_.cjs +200 -0
  187. package/dist/drivers-BLU1fNs_.cjs.map +1 -0
  188. package/dist/drivers-C08LL4E8.mjs +177 -0
  189. package/dist/drivers-C08LL4E8.mjs.map +1 -0
  190. package/dist/{emit-CiZS_5Ub.mjs → emit-C1e8qD08.mjs} +13 -26
  191. package/dist/emit-C1e8qD08.mjs.map +1 -0
  192. package/dist/{emit-CbcRolsa.cjs → emit-Dmc1nvdS.cjs} +31 -57
  193. package/dist/emit-Dmc1nvdS.cjs.map +1 -0
  194. package/dist/encryption-CeW3xpE1.cjs +90 -0
  195. package/dist/encryption-CeW3xpE1.cjs.map +1 -0
  196. package/dist/encryption-DC8zsh2s.mjs +89 -0
  197. package/dist/encryption-DC8zsh2s.mjs.map +1 -0
  198. package/dist/engine-BXxvcxVq.cjs +3195 -0
  199. package/dist/engine-BXxvcxVq.cjs.map +1 -0
  200. package/dist/engine-z0UClzE9.mjs +3082 -0
  201. package/dist/engine-z0UClzE9.mjs.map +1 -0
  202. package/dist/errors-D8Gwp5kU.mjs +23 -0
  203. package/dist/errors-D8Gwp5kU.mjs.map +1 -0
  204. package/dist/errors-DMC4Umsb.cjs +34 -0
  205. package/dist/errors-DMC4Umsb.cjs.map +1 -0
  206. package/dist/github-DJgO5z37.mjs +829 -0
  207. package/dist/github-DJgO5z37.mjs.map +1 -0
  208. package/dist/github-DWoFgxtl.cjs +829 -0
  209. package/dist/github-DWoFgxtl.cjs.map +1 -0
  210. package/dist/identity-CBXr4wNi.mjs +129 -0
  211. package/dist/identity-CBXr4wNi.mjs.map +1 -0
  212. package/dist/identity-CbLfgQNT.cjs +182 -0
  213. package/dist/identity-CbLfgQNT.cjs.map +1 -0
  214. package/dist/{index-C6e-ULLx.d.mts → index-8OfpOtSI.d.cts} +39 -24
  215. package/dist/index-8OfpOtSI.d.cts.map +1 -0
  216. package/dist/{index-CR5urhWX.d.cts → index-Dpji6Bxq.d.mts} +39 -24
  217. package/dist/index-Dpji6Bxq.d.mts.map +1 -0
  218. package/dist/index.cjs +10022 -12718
  219. package/dist/index.cjs.map +1 -1
  220. package/dist/index.d.cts +1 -1
  221. package/dist/index.d.mts +1 -1
  222. package/dist/index.mjs +10648 -13356
  223. package/dist/index.mjs.map +1 -1
  224. package/dist/local-BwC2v2Y8.mjs +224 -0
  225. package/dist/local-BwC2v2Y8.mjs.map +1 -0
  226. package/dist/local-DNhnkugT.cjs +241 -0
  227. package/dist/local-DNhnkugT.cjs.map +1 -0
  228. package/dist/migrate-B1OjPwUY.cjs +181 -0
  229. package/dist/migrate-B1OjPwUY.cjs.map +1 -0
  230. package/dist/migrate-CWSCkzu3.cjs +271 -0
  231. package/dist/migrate-CWSCkzu3.cjs.map +1 -0
  232. package/dist/migrate-DIVxoju6.mjs +266 -0
  233. package/dist/migrate-DIVxoju6.mjs.map +1 -0
  234. package/dist/migrate-DoI2hWNH.mjs +181 -0
  235. package/dist/migrate-DoI2hWNH.mjs.map +1 -0
  236. package/dist/openapi.cjs +214 -10
  237. package/dist/openapi.cjs.map +1 -0
  238. package/dist/openapi.d.cts +38 -17
  239. package/dist/openapi.d.cts.map +1 -1
  240. package/dist/openapi.d.mts +38 -17
  241. package/dist/openapi.d.mts.map +1 -1
  242. package/dist/openapi.mjs +208 -5
  243. package/dist/openapi.mjs.map +1 -0
  244. package/dist/projectBucket-BBbQ1lHF.cjs +263 -0
  245. package/dist/projectBucket-BBbQ1lHF.cjs.map +1 -0
  246. package/dist/projectBucket-C_DN4WzF.mjs +222 -0
  247. package/dist/projectBucket-C_DN4WzF.mjs.map +1 -0
  248. package/dist/provider-BqpjG9QM.cjs +57 -0
  249. package/dist/provider-BqpjG9QM.cjs.map +1 -0
  250. package/dist/provider-CEOKk8NS.mjs +46 -0
  251. package/dist/provider-CEOKk8NS.mjs.map +1 -0
  252. package/dist/ready-BtxiI7Qb.cjs +403 -0
  253. package/dist/ready-BtxiI7Qb.cjs.map +1 -0
  254. package/dist/ready-CzHNHhI6.mjs +374 -0
  255. package/dist/ready-CzHNHhI6.mjs.map +1 -0
  256. package/dist/reconcile/public.cjs +3 -5
  257. package/dist/reconcile/public.d.cts +11 -87
  258. package/dist/reconcile/public.d.cts.map +1 -1
  259. package/dist/reconcile/public.d.mts +11 -87
  260. package/dist/reconcile/public.d.mts.map +1 -1
  261. package/dist/reconcile/public.mjs +3 -4
  262. package/dist/{reconcile-CFs8C_1a.mjs → reconcile--I7V4Klj.mjs} +4 -7
  263. package/dist/reconcile--I7V4Klj.mjs.map +1 -0
  264. package/dist/{reconcile-D0pimNiy.cjs → reconcile-CuCQBa5-.cjs} +5 -8
  265. package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
  266. package/dist/resolve-WAwYMN6q.cjs +316 -0
  267. package/dist/resolve-WAwYMN6q.cjs.map +1 -0
  268. package/dist/resolve-pmXIdi9j.mjs +263 -0
  269. package/dist/resolve-pmXIdi9j.mjs.map +1 -0
  270. package/dist/rollback-CLtwbByg.mjs +136 -0
  271. package/dist/rollback-CLtwbByg.mjs.map +1 -0
  272. package/dist/rollback-Cz8F9xSB.cjs +165 -0
  273. package/dist/rollback-Cz8F9xSB.cjs.map +1 -0
  274. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  275. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  276. package/dist/run-BJLIerMM.mjs +133 -0
  277. package/dist/run-BJLIerMM.mjs.map +1 -0
  278. package/dist/run-fVZ-rLnc.cjs +174 -0
  279. package/dist/run-fVZ-rLnc.cjs.map +1 -0
  280. package/dist/runtime-ACdfK59n.d.cts +82 -0
  281. package/dist/runtime-ACdfK59n.d.cts.map +1 -0
  282. package/dist/runtime-YyQuekxi.d.mts +82 -0
  283. package/dist/runtime-YyQuekxi.d.mts.map +1 -0
  284. package/dist/s3-CrPoA89T.cjs +215 -0
  285. package/dist/s3-CrPoA89T.cjs.map +1 -0
  286. package/dist/s3-DQXZdmCM.mjs +215 -0
  287. package/dist/s3-DQXZdmCM.mjs.map +1 -0
  288. package/dist/sandbox/config-worker.cjs +43 -0
  289. package/dist/sandbox/config-worker.cjs.map +1 -0
  290. package/dist/sandbox/config-worker.d.cts +1 -0
  291. package/dist/sandbox/config-worker.d.mts +1 -0
  292. package/dist/sandbox/config-worker.mjs +44 -0
  293. package/dist/sandbox/config-worker.mjs.map +1 -0
  294. package/dist/sandbox/credentials-worker.cjs +54 -0
  295. package/dist/sandbox/credentials-worker.cjs.map +1 -0
  296. package/dist/sandbox/credentials-worker.d.cts +1 -0
  297. package/dist/sandbox/credentials-worker.d.mts +1 -0
  298. package/dist/sandbox/credentials-worker.mjs +55 -0
  299. package/dist/sandbox/credentials-worker.mjs.map +1 -0
  300. package/dist/sandbox/discover-worker.cjs +47 -0
  301. package/dist/sandbox/discover-worker.cjs.map +1 -0
  302. package/dist/sandbox/discover-worker.d.cts +1 -0
  303. package/dist/sandbox/discover-worker.d.mts +1 -0
  304. package/dist/sandbox/discover-worker.mjs +48 -0
  305. package/dist/sandbox/discover-worker.mjs.map +1 -0
  306. package/dist/sandbox/migrate-worker.cjs +75 -0
  307. package/dist/sandbox/migrate-worker.cjs.map +1 -0
  308. package/dist/sandbox/migrate-worker.d.cts +1 -0
  309. package/dist/sandbox/migrate-worker.d.mts +1 -0
  310. package/dist/sandbox/migrate-worker.mjs +76 -0
  311. package/dist/sandbox/migrate-worker.mjs.map +1 -0
  312. package/dist/sandbox-C4g1eG31.d.mts +104 -0
  313. package/dist/sandbox-C4g1eG31.d.mts.map +1 -0
  314. package/dist/sandbox-CHv3OYXg.cjs +165 -0
  315. package/dist/sandbox-CHv3OYXg.cjs.map +1 -0
  316. package/dist/sandbox-CbVB7uOD.mjs +118 -0
  317. package/dist/sandbox-CbVB7uOD.mjs.map +1 -0
  318. package/dist/sandbox-CdKgQ3XU.d.cts +104 -0
  319. package/dist/sandbox-CdKgQ3XU.d.cts.map +1 -0
  320. package/dist/{workspace-C6VJQVtG.cjs → schemas-BCwKKA42.mjs} +958 -1842
  321. package/dist/schemas-BCwKKA42.mjs.map +1 -0
  322. package/dist/{workspace-zoqRbihZ.mjs → schemas-BQ_v0lEX.cjs} +1048 -1658
  323. package/dist/schemas-BQ_v0lEX.cjs.map +1 -0
  324. package/dist/secretsManager-CQORubp9.mjs +97 -0
  325. package/dist/secretsManager-CQORubp9.mjs.map +1 -0
  326. package/dist/secretsManager-RAGcEDX1.cjs +108 -0
  327. package/dist/secretsManager-RAGcEDX1.cjs.map +1 -0
  328. package/dist/seeds-BHKUAExH.mjs +8148 -0
  329. package/dist/seeds-BHKUAExH.mjs.map +1 -0
  330. package/dist/seeds-Dk4WHhjU.cjs +9115 -0
  331. package/dist/seeds-Dk4WHhjU.cjs.map +1 -0
  332. package/dist/sniffer-BjBZ01PE.cjs +1998 -0
  333. package/dist/sniffer-BjBZ01PE.cjs.map +1 -0
  334. package/dist/sniffer-CaXl51vO.mjs +1825 -0
  335. package/dist/sniffer-CaXl51vO.mjs.map +1 -0
  336. package/dist/sst-B-Uz4cvm.cjs +464 -0
  337. package/dist/sst-B-Uz4cvm.cjs.map +1 -0
  338. package/dist/sst-C1pxbFEd.mjs +441 -0
  339. package/dist/sst-C1pxbFEd.mjs.map +1 -0
  340. package/dist/stages-DJrOYLZ-.mjs +176 -0
  341. package/dist/stages-DJrOYLZ-.mjs.map +1 -0
  342. package/dist/stages-_3RVNG83.cjs +176 -0
  343. package/dist/stages-_3RVNG83.cjs.map +1 -0
  344. package/dist/target/public.cjs +15 -0
  345. package/dist/target/public.d.cts +28 -0
  346. package/dist/target/public.d.cts.map +1 -0
  347. package/dist/target/public.d.mts +28 -0
  348. package/dist/target/public.d.mts.map +1 -0
  349. package/dist/target/public.mjs +4 -0
  350. package/dist/terminal-Bs_lNQhL.mjs +85 -0
  351. package/dist/terminal-Bs_lNQhL.mjs.map +1 -0
  352. package/dist/terminal-CsQz4oT0.cjs +85 -0
  353. package/dist/terminal-CsQz4oT0.cjs.map +1 -0
  354. package/dist/types-B6UXlEkf.d.cts +7650 -0
  355. package/dist/types-B6UXlEkf.d.cts.map +1 -0
  356. package/dist/types-HqVPddRK.d.mts +7649 -0
  357. package/dist/types-HqVPddRK.d.mts.map +1 -0
  358. package/dist/utils-D2Nk1Nv2.cjs +205 -0
  359. package/dist/utils-D2Nk1Nv2.cjs.map +1 -0
  360. package/dist/utils-D_fxUqvU.mjs +156 -0
  361. package/dist/utils-D_fxUqvU.mjs.map +1 -0
  362. package/dist/vitest.cjs +65 -0
  363. package/dist/vitest.cjs.map +1 -0
  364. package/dist/vitest.d.cts +29 -0
  365. package/dist/vitest.d.cts.map +1 -0
  366. package/dist/vitest.d.mts +29 -0
  367. package/dist/vitest.d.mts.map +1 -0
  368. package/dist/vitest.mjs +65 -0
  369. package/dist/vitest.mjs.map +1 -0
  370. package/dist/workerRuntime-BXfhbe13.cjs +108 -0
  371. package/dist/workerRuntime-BXfhbe13.cjs.map +1 -0
  372. package/dist/workerRuntime-CsOyBRx2.mjs +79 -0
  373. package/dist/workerRuntime-CsOyBRx2.mjs.map +1 -0
  374. package/dist/workspace/index.cjs +8 -4
  375. package/dist/workspace/index.d.cts +3 -3
  376. package/dist/workspace/index.d.mts +3 -3
  377. package/dist/workspace/index.mjs +2 -3
  378. package/dist/workspace-BwqQnool.cjs +2806 -0
  379. package/dist/workspace-BwqQnool.cjs.map +1 -0
  380. package/dist/workspace-D1QbNd55.mjs +2394 -0
  381. package/dist/workspace-D1QbNd55.mjs.map +1 -0
  382. package/package.json +54 -22
  383. package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
  384. package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
  385. package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
  386. package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
  387. package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
  388. package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
  389. package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
  390. package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
  391. package/dist/LocalStateProvider-Bn6tS-oL.mjs +0 -42
  392. package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
  393. package/dist/LocalStateProvider-Db9SEjyH.cjs +0 -43
  394. package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
  395. package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
  396. package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
  397. package/dist/SSMStateProvider-BRt2py-A.mjs +0 -66
  398. package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
  399. package/dist/SSMStateProvider-DyX8s9HI.cjs +0 -66
  400. package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
  401. package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
  402. package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
  403. package/dist/bundler-BY1OmV1e.cjs.map +0 -1
  404. package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
  405. package/dist/chunk-Duj1WY3L.mjs +0 -7
  406. package/dist/config-BZ1F0WuA.cjs +0 -462
  407. package/dist/config-BZ1F0WuA.cjs.map +0 -1
  408. package/dist/config-DVVph9yz.mjs +0 -402
  409. package/dist/config-DVVph9yz.mjs.map +0 -1
  410. package/dist/config.d.cts.map +0 -1
  411. package/dist/config.d.mts.map +0 -1
  412. package/dist/credentials-B5zRHdAl.mjs +0 -141
  413. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  414. package/dist/credentials-BapzjyV5.cjs +0 -195
  415. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  416. package/dist/credentials-Xamqe_NJ.cjs +0 -2681
  417. package/dist/credentials-Xamqe_NJ.cjs.map +0 -1
  418. package/dist/credentials-dP8vRVRv.mjs +0 -2549
  419. package/dist/credentials-dP8vRVRv.mjs.map +0 -1
  420. package/dist/discover-CAlFgYec.mjs +0 -229
  421. package/dist/discover-CAlFgYec.mjs.map +0 -1
  422. package/dist/discover-DTmFeloL.cjs +0 -271
  423. package/dist/discover-DTmFeloL.cjs.map +0 -1
  424. package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
  425. package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
  426. package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
  427. package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
  428. package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
  429. package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
  430. package/dist/emit-CbcRolsa.cjs.map +0 -1
  431. package/dist/emit-CiZS_5Ub.mjs.map +0 -1
  432. package/dist/encryption-C6jaU0hE.cjs +0 -54
  433. package/dist/encryption-C6jaU0hE.cjs.map +0 -1
  434. package/dist/encryption-CHzzeR8a.cjs +0 -4
  435. package/dist/encryption-CQUncu7v.mjs +0 -3
  436. package/dist/encryption-D-abyhZx.mjs +0 -42
  437. package/dist/encryption-D-abyhZx.mjs.map +0 -1
  438. package/dist/fullstack-secrets-C-GGohke.cjs +0 -111
  439. package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
  440. package/dist/fullstack-secrets-D1o9-G5l.mjs +0 -87
  441. package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
  442. package/dist/generator-CNzBw7g5.cjs +0 -289
  443. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  444. package/dist/generator-VE2JrFlY.mjs +0 -253
  445. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  446. package/dist/index-C6e-ULLx.d.mts.map +0 -1
  447. package/dist/index-CR5urhWX.d.cts.map +0 -1
  448. package/dist/openapi-SjsgARie.cjs +0 -2075
  449. package/dist/openapi-SjsgARie.cjs.map +0 -1
  450. package/dist/openapi-Xx0A7Wg0.mjs +0 -2021
  451. package/dist/openapi-Xx0A7Wg0.mjs.map +0 -1
  452. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  453. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  454. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  455. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  456. package/dist/openapi-react-query.cjs +0 -4
  457. package/dist/openapi-react-query.d.cts +0 -11
  458. package/dist/openapi-react-query.d.cts.map +0 -1
  459. package/dist/openapi-react-query.d.mts +0 -11
  460. package/dist/openapi-react-query.d.mts.map +0 -1
  461. package/dist/openapi-react-query.mjs +0 -4
  462. package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
  463. package/dist/reconcile-D0pimNiy.cjs.map +0 -1
  464. package/dist/setup-BA8ciTPU.mjs +0 -11
  465. package/dist/setup-BsZvZP6f.cjs +0 -11
  466. package/dist/setup-C8KOx8_8.mjs +0 -443
  467. package/dist/setup-C8KOx8_8.mjs.map +0 -1
  468. package/dist/setup-hC6hI86f.cjs +0 -473
  469. package/dist/setup-hC6hI86f.cjs.map +0 -1
  470. package/dist/storage-BJmzYxt8.cjs +0 -363
  471. package/dist/storage-BJmzYxt8.cjs.map +0 -1
  472. package/dist/storage-BM9hGpgv.cjs +0 -7
  473. package/dist/storage-Bi24WfoW.mjs +0 -297
  474. package/dist/storage-Bi24WfoW.mjs.map +0 -1
  475. package/dist/storage-CYlGwWTj.mjs +0 -3
  476. package/dist/sync-CmEuNZsB.mjs +0 -76
  477. package/dist/sync-CmEuNZsB.mjs.map +0 -1
  478. package/dist/sync-D306yOWu.cjs +0 -4
  479. package/dist/sync-SizaChmC.cjs +0 -93
  480. package/dist/sync-SizaChmC.cjs.map +0 -1
  481. package/dist/sync-hOqAWHR6.mjs +0 -3
  482. package/dist/types-6pkp2RRj.d.mts +0 -2220
  483. package/dist/types-6pkp2RRj.d.mts.map +0 -1
  484. package/dist/types-Y3fKQSAK.d.cts +0 -2220
  485. package/dist/types-Y3fKQSAK.d.cts.map +0 -1
  486. package/dist/workspace-BzrG_2SI.mjs +0 -8
  487. package/dist/workspace-C6VJQVtG.cjs.map +0 -1
  488. package/dist/workspace-XXtNhqJl.cjs +0 -9
  489. package/dist/workspace-zoqRbihZ.mjs.map +0 -1
@@ -0,0 +1,829 @@
1
+ import { t as GkmError } from "./errors-D8Gwp5kU.mjs";
2
+ import { N as assertDeployedStage, U as stageProvider, lt as s3SecretsKey, ut as s3SecretsLocation } from "./workspace-D1QbNd55.mjs";
3
+ import { c as stageDnsDomains, x as stageBackups } from "./dns-DDDCfj75.mjs";
4
+ import { Ft as isRemoteStore, It as secretsStoreFor, dt as constructGlobs, fn as getKeyPath, hn as readKey, pn as keystoreProject } from "./seeds-BHKUAExH.mjs";
5
+ import { n as deployIdentity } from "./identity-CBXr4wNi.mjs";
6
+ import { r as discover } from "./discover-kziEht4W.mjs";
7
+ import { loadWorkspaceConfig } from "./config.mjs";
8
+ import { c as bucketName, l as iamUserName, o as backupsUserName, s as IAM_USER_PATH } from "./deploy-DgZxTnGS.mjs";
9
+ import { n as PROJECT_BUCKET_LIFECYCLE_ACTIONS, o as projectBucketName, t as PROJECT_BUCKET_CREATE_ACTIONS } from "./projectBucket-C_DN4WzF.mjs";
10
+ import { n as secretsParameterName } from "./aws-8QQ8n-t6.mjs";
11
+ import { t as secretsManagerSecretName } from "./secretsManager-CQORubp9.mjs";
12
+ import { execFileSync } from "node:child_process";
13
+ import { AttachRolePolicyCommand, CreateOpenIDConnectProviderCommand, CreateRoleCommand, DeleteRolePolicyCommand, DetachRolePolicyCommand, GetRoleCommand, IAMClient, ListAttachedRolePoliciesCommand, ListOpenIDConnectProvidersCommand, ListRoleTagsCommand, PutRolePolicyCommand, TagRoleCommand, UntagRoleCommand, UpdateAssumeRolePolicyCommand } from "@aws-sdk/client-iam";
14
+ //#region src/deploy/githubOidc.ts
15
+ /**
16
+ * The `sub` GitHub puts in a deploy job's OIDC token — what the deploy role's
17
+ * trust policy has to match exactly.
18
+ *
19
+ * It is not always `repo:<owner>/<name>:environment:<stage>`. A repository
20
+ * (or its organisation) decides the format, and says which through
21
+ * `GET /repos/{owner}/{repo}/actions/oidc/customization/sub`:
22
+ *
23
+ * - the default: `repo:<owner>/<name>:environment:<stage>`;
24
+ * - the immutable subject — the default for repositories created after
25
+ * 15 July 2026, opt-in before — puts the owner's and the repository's ids in
26
+ * the `repo` segment: `repo:<owner>@<ownerId>/<name>@<repoId>:environment:<stage>`.
27
+ * The API hands that segment back as `sub_claim_prefix`;
28
+ * - a custom template (`use_default: false`) builds the `sub` from
29
+ * `include_claim_keys`, in order, each as `<key>:<value>` joined by `:`,
30
+ * where `context` is `environment:<stage>` in an environment job.
31
+ *
32
+ * A `:` inside a value is sent as `%3A`.
33
+ *
34
+ * See https://docs.github.com/en/actions/reference/security/oidc.
35
+ */
36
+ /**
37
+ * Template keys whose values are known for a repository's environment job
38
+ * before the job runs. Anything else — `job_workflow_ref`, `ref`, `sha`,
39
+ * `run_id`, `workflow`, `actor`, a custom property — depends on the run.
40
+ */
41
+ const SUPPORTED_CLAIM_KEYS = [
42
+ "repo",
43
+ "context",
44
+ "environment",
45
+ "repository",
46
+ "repository_owner",
47
+ "repository_owner_id",
48
+ "repository_id",
49
+ "repository_visibility"
50
+ ];
51
+ const NEEDS_FACTS = /* @__PURE__ */ new Set([
52
+ "repository_owner_id",
53
+ "repository_id",
54
+ "repository_visibility"
55
+ ]);
56
+ /** A `:` inside a claim value is sent as `%3A`. */
57
+ function claim(value) {
58
+ return value.replaceAll(":", "%3A");
59
+ }
60
+ /** Whether {@link oidcSubject} needs the repository's ids or visibility. */
61
+ function needsRepoFacts(customization) {
62
+ const immutableWithoutPrefix = customization.use_immutable_subject === true && !customization.sub_claim_prefix;
63
+ if (customization.use_default) return immutableWithoutPrefix;
64
+ return (customization.include_claim_keys ?? []).some((key) => NEEDS_FACTS.has(key) || key === "repo" && immutableWithoutPrefix);
65
+ }
66
+ /**
67
+ * The exact `sub` of a job in `repo`'s `stage` environment.
68
+ *
69
+ * @throws OidcSubjectNotSupported when a custom template includes a claim
70
+ * whose value depends on the run, so no one subject can be trusted.
71
+ */
72
+ function oidcSubject(repo, stage, customization, facts) {
73
+ const [owner = "", name = ""] = repo.split("/");
74
+ const environment = `environment:${claim(stage)}`;
75
+ const repoSegment = () => {
76
+ if (customization.sub_claim_prefix) return customization.sub_claim_prefix;
77
+ if (customization.use_immutable_subject) {
78
+ if (!facts) throw new RepoFactsRequired(repo);
79
+ return `repo:${owner}@${facts.ownerId}/${name}@${facts.repoId}`;
80
+ }
81
+ return `repo:${repo}`;
82
+ };
83
+ const immutable = customization.use_immutable_subject === true || customization.sub_claim_prefix !== void 0;
84
+ if (customization.use_default) return {
85
+ subject: `${repoSegment()}:${environment}`,
86
+ kind: immutable ? "immutable" : "default"
87
+ };
88
+ const keys = customization.include_claim_keys ?? [];
89
+ const unsupported = keys.filter((key) => !SUPPORTED_CLAIM_KEYS.includes(key));
90
+ if (keys.length === 0 || unsupported.length > 0) throw new OidcSubjectNotSupported(repo, keys, unsupported);
91
+ if (keys.some((key) => NEEDS_FACTS.has(key)) && !facts) throw new RepoFactsRequired(repo);
92
+ return {
93
+ subject: keys.map((key) => {
94
+ switch (key) {
95
+ case "repo": return repoSegment();
96
+ case "context":
97
+ case "environment": return environment;
98
+ case "repository": return `repository:${claim(repo)}`;
99
+ case "repository_owner": return `repository_owner:${claim(owner)}`;
100
+ case "repository_owner_id": return `repository_owner_id:${facts.ownerId}`;
101
+ case "repository_id": return `repository_id:${facts.repoId}`;
102
+ default: return `repository_visibility:${claim(facts.visibility)}`;
103
+ }
104
+ }).join(":"),
105
+ kind: "custom"
106
+ };
107
+ }
108
+ /** The endpoint a repository's subject format is read from. */
109
+ function customizationEndpoint(repo) {
110
+ return `repos/${repo}/actions/oidc/customization/sub`;
111
+ }
112
+ /**
113
+ * The `sub` GitHub will send for `repo`'s `stage` environment, read from the
114
+ * repository's OIDC settings through `gh`.
115
+ *
116
+ * A repository on a custom template that names no keys of its own uses its
117
+ * organisation's, read from `orgs/{owner}/actions/oidc/customization/sub`.
118
+ * When the settings cannot be read at all — no permission, or a GitHub
119
+ * Enterprise Server without the endpoint — the default format is assumed, with
120
+ * a warning saying where to check it.
121
+ */
122
+ function resolveOidcSubject(gh, repo, stage) {
123
+ const endpoint = customizationEndpoint(repo);
124
+ let customization;
125
+ try {
126
+ customization = JSON.parse(gh(["api", endpoint]));
127
+ } catch {
128
+ return {
129
+ subject: `repo:${repo}:environment:${claim(stage)}`,
130
+ kind: "assumed",
131
+ warning: `Could not read ${endpoint}, so the default subject format is assumed. Check it with: gh api ${endpoint} — a repository on the immutable subject or a custom template sends a different sub, and the role would not be assumable.`
132
+ };
133
+ }
134
+ if (!customization.use_default && (customization.include_claim_keys ?? []).length === 0) {
135
+ const [owner = ""] = repo.split("/");
136
+ const orgEndpoint = `orgs/${owner}/actions/oidc/customization/sub`;
137
+ let org;
138
+ try {
139
+ org = JSON.parse(gh(["api", orgEndpoint]));
140
+ } catch {
141
+ throw new OrgOidcTemplateUnreadable(repo, orgEndpoint);
142
+ }
143
+ customization = {
144
+ ...customization,
145
+ include_claim_keys: org.include_claim_keys ?? [],
146
+ use_immutable_subject: customization.use_immutable_subject ?? org.use_immutable_subject
147
+ };
148
+ }
149
+ const facts = needsRepoFacts(customization) ? readRepoFacts(gh, repo) : void 0;
150
+ return oidcSubject(repo, stage, customization, facts);
151
+ }
152
+ function readRepoFacts(gh, repo) {
153
+ const raw = JSON.parse(gh(["api", `repos/${repo}`]));
154
+ return {
155
+ ownerId: raw.owner.id,
156
+ repoId: raw.id,
157
+ visibility: raw.visibility
158
+ };
159
+ }
160
+ /**
161
+ * The repository's custom subject template includes a claim whose value
162
+ * depends on the run — or names none — so no one subject can be trusted.
163
+ */
164
+ var OidcSubjectNotSupported = class extends GkmError {
165
+ repo;
166
+ includeClaimKeys;
167
+ unsupportedKeys;
168
+ constructor(repo, includeClaimKeys, unsupportedKeys) {
169
+ super(`${repo} builds its OIDC subject from a custom template, ${JSON.stringify(includeClaimKeys)}, and ${unsupportedKeys.length > 0 ? `${unsupportedKeys.join(", ")} depend${unsupportedKeys.length === 1 ? "s" : ""} on the run` : "it names no claims"}, so the deploy role cannot trust one exact subject. Set the repository back to the default subject — gh api --method PUT ${customizationEndpoint(repo)} -F use_default=true — (or keep the immutable one by also passing -F use_immutable_subject=true), or use a template built only from ${SUPPORTED_CLAIM_KEYS.join(", ")}; then run this again.`);
170
+ this.repo = repo;
171
+ this.includeClaimKeys = includeClaimKeys;
172
+ this.unsupportedKeys = unsupportedKeys;
173
+ this.name = "OidcSubjectNotSupported";
174
+ }
175
+ };
176
+ /** The subject needs the repository's ids, and none were read. */
177
+ var RepoFactsRequired = class extends GkmError {
178
+ repo;
179
+ constructor(repo) {
180
+ super(`The OIDC subject of ${repo} includes its owner and repository ids; read them with gh api repos/${repo} and pass them in.`);
181
+ this.repo = repo;
182
+ this.name = "RepoFactsRequired";
183
+ }
184
+ };
185
+ /**
186
+ * The repository uses its organisation's subject template, and that template
187
+ * could not be read — so what GitHub sends is unknown, and is not guessed.
188
+ */
189
+ var OrgOidcTemplateUnreadable = class extends GkmError {
190
+ repo;
191
+ endpoint;
192
+ constructor(repo, endpoint) {
193
+ super(`${repo} uses its organisation's OIDC subject template, and ${endpoint} could not be read. Run this as an organisation owner (gh auth refresh -s admin:org), or set the repository back to the default subject with gh api --method PUT ${customizationEndpoint(repo)} -F use_default=true; then run this again.`);
194
+ this.repo = repo;
195
+ this.endpoint = endpoint;
196
+ this.name = "OrgOidcTemplateUnreadable";
197
+ }
198
+ };
199
+ //#endregion
200
+ //#region src/deploy/githubPolicy.ts
201
+ /**
202
+ * What SST needs to create a stack is most of AWS, so this is the default
203
+ * outside compose — said out loud in the output, and replaceable with
204
+ * `--policy-arn`.
205
+ */
206
+ const DEFAULT_POLICY_ARN = "arn:aws:iam::aws:policy/AdministratorAccess";
207
+ /** The name of the inline policy a compose stage's role is given. */
208
+ const SCOPED_POLICY_NAME = "gkm-deploy";
209
+ /** Every target the stage's apps deploy through. */
210
+ function deployTargets(workspace) {
211
+ const targets = /* @__PURE__ */ new Set([workspace.deploy?.default ?? "dokploy"]);
212
+ for (const app of Object.values(workspace.apps)) targets.add(app.resolvedDeployTarget);
213
+ return [...targets].sort();
214
+ }
215
+ /**
216
+ * The access the stage's deploy role is given: `--policy-arn` when passed,
217
+ * the scoped policy for a stage only the compose target deploys, and
218
+ * `AdministratorAccess` otherwise.
219
+ */
220
+ function deployAccess(workspace, stage, policyArn, manifest = {}) {
221
+ const buckets = Object.entries(manifest).filter(([, d]) => d.kind === "objects").map(([id]) => id);
222
+ if (policyArn) return {
223
+ kind: "managed",
224
+ policyArn,
225
+ reason: "--policy-arn"
226
+ };
227
+ const targets = deployTargets(workspace);
228
+ if (targets.length !== 1 || targets[0] !== "compose") return {
229
+ kind: "managed",
230
+ policyArn: DEFAULT_POLICY_ARN,
231
+ reason: `the ${targets.join(", ")} target${targets.length === 1 ? "" : "s"} deploy${targets.length === 1 ? "s" : ""} infrastructure; --policy-arn to narrow`
232
+ };
233
+ const project = workspace.name;
234
+ const store = workspace.secrets.store ?? "file";
235
+ const state = workspace.state;
236
+ if (typeof store === "object" && typeof store.provider === "object" || state !== void 0 && typeof state.provider === "object") return {
237
+ kind: "managed",
238
+ policyArn: DEFAULT_POLICY_ARN,
239
+ reason: `a custom ${typeof store === "object" && typeof store.provider === "object" ? "secrets store" : "state provider"} cannot be scoped; --policy-arn to narrow`
240
+ };
241
+ const describe = [];
242
+ const build = [];
243
+ const projectBucketIn = (account) => projectBucketName(deployIdentity(workspace, stage).scope, account);
244
+ const projectBucketStatement = (account) => ({
245
+ Sid: "ProjectBucket",
246
+ Effect: "Allow",
247
+ Action: [...PROJECT_BUCKET_CREATE_ACTIONS],
248
+ Resource: `arn:aws:s3:::${projectBucketIn(account)}`
249
+ });
250
+ const stateInSecretsBucket = typeof store === "object" && store.provider === "s3" && state?.provider === "s3" && state.bucket === store.bucket;
251
+ if (typeof store === "object" && store.provider === "s3") {
252
+ const location = s3SecretsLocation(store, state);
253
+ const key = s3SecretsKey(location.prefix, project, stage);
254
+ const named = location.bucket;
255
+ const bucketIn = (account) => named ?? projectBucketIn(account);
256
+ describe.push(named ? `read and update s3://${named}/${key}` : `read and update ${key} in the project bucket ${projectBucketIn("<account>")}${stateInSecretsBucket ? "" : ", creating it"}`);
257
+ build.push((account) => [{
258
+ Sid: "StageSecrets",
259
+ Effect: "Allow",
260
+ Action: ["s3:GetObject", "s3:PutObject"],
261
+ Resource: `arn:aws:s3:::${bucketIn(account)}/${key}`
262
+ }, ...stateInSecretsBucket ? [] : [{
263
+ Sid: "StageSecretsBucket",
264
+ Effect: "Allow",
265
+ Action: ["s3:ListBucket"],
266
+ Resource: `arn:aws:s3:::${bucketIn(account)}`
267
+ }, ...named ? [] : [projectBucketStatement(account)]]]);
268
+ } else if (typeof store === "object" && store.provider === "ssm") {
269
+ const { region } = store;
270
+ const name = secretsParameterName(project, stage);
271
+ describe.push(`read and update ${name} (SSM, ${region})`);
272
+ build.push((account) => [{
273
+ Sid: "StageSecrets",
274
+ Effect: "Allow",
275
+ Action: ["ssm:GetParameter", "ssm:PutParameter"],
276
+ Resource: `arn:aws:ssm:${region}:${account}:parameter${name}`
277
+ }]);
278
+ } else if (typeof store === "object" && store.provider === "secrets-manager") {
279
+ const { region, kmsKeyId } = store;
280
+ const name = secretsManagerSecretName(project, stage);
281
+ describe.push(`read and update ${name} (Secrets Manager, ${region})`);
282
+ build.push((account) => {
283
+ const statements = [{
284
+ Sid: "StageSecrets",
285
+ Effect: "Allow",
286
+ Action: [
287
+ "secretsmanager:GetSecretValue",
288
+ "secretsmanager:PutSecretValue",
289
+ "secretsmanager:CreateSecret"
290
+ ],
291
+ Resource: `arn:aws:secretsmanager:${region}:${account}:secret:${name}-??????`
292
+ }];
293
+ if (kmsKeyId) statements.push({
294
+ Sid: "StageSecretsKey",
295
+ Effect: "Allow",
296
+ Action: ["kms:Decrypt", "kms:GenerateDataKey"],
297
+ Resource: kmsKeyId.startsWith("arn:") ? kmsKeyId : "*",
298
+ Condition: { StringEquals: { "kms:ViaService": `secretsmanager.${region}.amazonaws.com` } }
299
+ });
300
+ return statements;
301
+ });
302
+ }
303
+ if (state?.provider === "ssm") {
304
+ const { region } = state;
305
+ const path = `/gkm/${project}/${stage}/`;
306
+ describe.push(`read and write the deploy state under ${path} (SSM, ${region})`);
307
+ build.push((account) => [{
308
+ Sid: "StageState",
309
+ Effect: "Allow",
310
+ Action: [
311
+ "ssm:GetParameter",
312
+ "ssm:PutParameter",
313
+ "ssm:DeleteParameter"
314
+ ],
315
+ Resource: `arn:aws:ssm:${region}:${account}:parameter${path}*`
316
+ }]);
317
+ } else if (state?.provider === "s3") {
318
+ const prefix = (state.prefix ?? "gkm").replace(/\/+$/, "");
319
+ const path = `${prefix ? `${prefix}/` : ""}${project}/${stage}/`;
320
+ const named = state.bucket;
321
+ const bucketIn = (account) => named ?? projectBucketIn(account);
322
+ describe.push(named ? `read and write the deploy state under s3://${named}/${path}` : `create the project bucket ${projectBucketIn("<account>")}, and read and write the deploy state under ${path} in it`);
323
+ build.push((account) => [...stateBucketStatements(bucketIn(account), path), ...named ? [] : [projectBucketStatement(account)]]);
324
+ }
325
+ const objects = stageProvider(workspace, "objects", stage);
326
+ if (objects.mode === "provider" && objects.name === "s3" && buckets.length) {
327
+ const { scope } = deployIdentity(workspace, stage);
328
+ const names = [...buckets].sort().map((id) => ({
329
+ bucket: bucketName({
330
+ scope,
331
+ stage,
332
+ id
333
+ }),
334
+ user: iamUserName({
335
+ scope,
336
+ stage,
337
+ id
338
+ })
339
+ }));
340
+ const suffix = "?".repeat(6);
341
+ describe.push(`create and configure the buckets ${names.map((n) => n.bucket).join(", ")} and their IAM users (S3, IAM)`);
342
+ build.push((account) => [{
343
+ Sid: "StageBuckets",
344
+ Effect: "Allow",
345
+ Action: [
346
+ "s3:CreateBucket",
347
+ "s3:ListBucket",
348
+ "s3:GetBucketTagging",
349
+ "s3:PutBucketTagging",
350
+ "s3:GetBucketPublicAccessBlock",
351
+ "s3:PutBucketPublicAccessBlock",
352
+ "s3:GetBucketPolicy",
353
+ "s3:PutBucketPolicy",
354
+ "s3:GetEncryptionConfiguration",
355
+ "s3:PutEncryptionConfiguration",
356
+ "s3:GetBucketVersioning",
357
+ "s3:PutBucketVersioning",
358
+ "s3:GetBucketCORS",
359
+ "s3:PutBucketCORS"
360
+ ],
361
+ Resource: names.flatMap((n) => [`arn:aws:s3:::${n.bucket}`, `arn:aws:s3:::${n.bucket}-${suffix}`])
362
+ }, {
363
+ Sid: "StageBucketUsers",
364
+ Effect: "Allow",
365
+ Action: [
366
+ "iam:GetUser",
367
+ "iam:CreateUser",
368
+ "iam:TagUser",
369
+ "iam:ListUserTags",
370
+ "iam:GetUserPolicy",
371
+ "iam:PutUserPolicy",
372
+ "iam:ListAccessKeys",
373
+ "iam:CreateAccessKey",
374
+ "iam:DeleteAccessKey"
375
+ ],
376
+ Resource: names.map((n) => `arn:aws:iam::${account}:user${IAM_USER_PATH}${n.user}`)
377
+ }]);
378
+ }
379
+ if (stageBackups(workspace, manifest, stage).mode === "on") {
380
+ const { scope } = deployIdentity(workspace, stage);
381
+ const user = backupsUserName(scope, stage);
382
+ const bucketIn = (account) => projectBucketName(scope, account);
383
+ describe.push(`create the project bucket ${bucketIn("<account>")} and keep its lifecycle, and create the backups user ${user} and its key (S3, IAM)`);
384
+ build.push((account) => [{
385
+ Sid: "StageBackupsBucket",
386
+ Effect: "Allow",
387
+ Action: ["s3:ListBucket", .../* @__PURE__ */ new Set([...PROJECT_BUCKET_CREATE_ACTIONS, ...PROJECT_BUCKET_LIFECYCLE_ACTIONS])],
388
+ Resource: `arn:aws:s3:::${bucketIn(account)}`
389
+ }, {
390
+ Sid: "StageBackupsUser",
391
+ Effect: "Allow",
392
+ Action: [
393
+ "iam:GetUser",
394
+ "iam:CreateUser",
395
+ "iam:TagUser",
396
+ "iam:ListUserTags",
397
+ "iam:GetUserPolicy",
398
+ "iam:PutUserPolicy",
399
+ "iam:ListAccessKeys",
400
+ "iam:CreateAccessKey",
401
+ "iam:DeleteAccessKey"
402
+ ],
403
+ Resource: `arn:aws:iam::${account}:user${IAM_USER_PATH}${user}`
404
+ }]);
405
+ }
406
+ for (const { domain, config } of stageDnsDomains(stage, workspace.domains, workspace.dns)) {
407
+ if (config.provider !== "route53") continue;
408
+ const zoneId = config.hostedZoneId?.replace(/^\/?hostedzone\//, "");
409
+ describe.push(`write the A, AAAA and CNAME records of ${domain} (Route53${zoneId ? `, ${zoneId}` : ""})`);
410
+ build.push(() => [
411
+ {
412
+ Sid: "StageDnsRecords",
413
+ Effect: "Allow",
414
+ Action: ["route53:ChangeResourceRecordSets", "route53:ListResourceRecordSets"],
415
+ Resource: `arn:aws:route53:::hostedzone/${zoneId ?? "*"}`
416
+ },
417
+ {
418
+ Sid: "StageDnsChanges",
419
+ Effect: "Allow",
420
+ Action: ["route53:GetChange"],
421
+ Resource: "arn:aws:route53:::change/*"
422
+ },
423
+ ...zoneId ? [] : [{
424
+ Sid: "StageDnsZones",
425
+ Effect: "Allow",
426
+ Action: ["route53:ListHostedZonesByName"],
427
+ Resource: "*"
428
+ }]
429
+ ]);
430
+ }
431
+ return {
432
+ kind: "scoped",
433
+ statements: (account) => build.flatMap((statements) => statements(account)),
434
+ describe
435
+ };
436
+ }
437
+ /**
438
+ * Reading and writing one stage's deploy state in `bucket`, as the deploy
439
+ * role is given it.
440
+ */
441
+ function stateBucketStatements(bucket, path) {
442
+ return [{
443
+ Sid: "StageState",
444
+ Effect: "Allow",
445
+ Action: [
446
+ "s3:GetObject",
447
+ "s3:PutObject",
448
+ "s3:DeleteObject"
449
+ ],
450
+ Resource: `arn:aws:s3:::${bucket}/${path}*`
451
+ }, {
452
+ Sid: "StageStateBucket",
453
+ Effect: "Allow",
454
+ Action: ["s3:ListBucket"],
455
+ Resource: `arn:aws:s3:::${bucket}`
456
+ }];
457
+ }
458
+ /** The scoped access as a policy document, or null when it allows nothing. */
459
+ function scopedPolicyDocument(statements) {
460
+ if (statements.length === 0) return null;
461
+ return JSON.stringify({
462
+ Version: "2012-10-17",
463
+ Statement: statements
464
+ });
465
+ }
466
+ /** The account an IAM ARN is in: `arn:aws:iam::<account>:…`. */
467
+ function accountOf(arn) {
468
+ return arn.split(":")[4] ?? "";
469
+ }
470
+ //#endregion
471
+ //#region src/deploy/github.ts
472
+ /**
473
+ * `gkm deploy:github` — let GitHub Actions deploy one stage, with no keys.
474
+ *
475
+ * A stage usually lives in its own AWS account — staging in one, production in
476
+ * another — so this runs once per stage, with that account's profile:
477
+ *
478
+ * gkm deploy:github --stage staging --profile acme-dev
479
+ * gkm deploy:github --stage prod --profile acme-prod
480
+ *
481
+ * In the stage's account it makes sure GitHub's OIDC provider exists, and a
482
+ * role that only this repository's `<stage>` environment can assume. On
483
+ * GitHub it creates that environment and gives it what the generated deploy
484
+ * workflow reads: `AWS_ROLE_ARN`, and — when the stage's secrets are kept in
485
+ * the local file — its key as `GKM_SECRETS_KEY`. With `secrets.store` set to
486
+ * S3, SSM or Secrets Manager the deploy job reads them with the role instead, so
487
+ * no key is handed to GitHub, and this checks the stage's store in the same
488
+ * account, with the same profile. Re-running it converges rather than duplicating.
489
+ *
490
+ * The role trusts the exact `sub` GitHub sends for the environment, read from
491
+ * the repository's OIDC subject settings (`githubOidc.ts`) — the default, the
492
+ * immutable subject with the owner's and repository's ids, or a custom
493
+ * template. A re-run rewrites an existing role's trust to it, so running this
494
+ * again repairs a role that trusted the wrong format. What the role may do is
495
+ * `githubPolicy.ts`: `AdministratorAccess` for SST, and for a compose stage
496
+ * only its own secrets (and deploy state, when that is in AWS).
497
+ */
498
+ const logger = console;
499
+ const GITHUB_OIDC_HOST = "token.actions.githubusercontent.com";
500
+ const AUDIENCE = "sts.amazonaws.com";
501
+ /**
502
+ * The tag recording which managed policy gkm attached to the role — so a
503
+ * re-run detaches only what gkm put there, never a policy someone else did.
504
+ */
505
+ const POLICY_TAG = "gkm:policy-arn";
506
+ const defaultGh = (args, input) => execFileSync("gh", args, {
507
+ encoding: "utf-8",
508
+ stdio: [
509
+ "pipe",
510
+ "pipe",
511
+ "pipe"
512
+ ],
513
+ ...input === void 0 ? {} : { input }
514
+ }).trim();
515
+ /** The role a stage deploys as: `<project>-github-<stage>`, within IAM's 64. */
516
+ function roleName(project, stage) {
517
+ return `${project}-github-${stage}`.toLowerCase().replace(/[^a-z0-9+=,.@_-]/g, "-").slice(0, 64);
518
+ }
519
+ /**
520
+ * Who may assume the role: a workflow job whose OIDC token carries exactly
521
+ * `subject` — the repository's `<stage>` environment, in the format the
522
+ * repository sends (see `githubOidc.ts`), and nothing else. Not another
523
+ * branch's job, not another environment's: that is what keeps a staging
524
+ * deploy from using the production role.
525
+ */
526
+ function trustPolicy(providerArn, subject) {
527
+ return JSON.stringify({
528
+ Version: "2012-10-17",
529
+ Statement: [{
530
+ Effect: "Allow",
531
+ Principal: { Federated: providerArn },
532
+ Action: "sts:AssumeRoleWithWebIdentity",
533
+ Condition: { StringEquals: {
534
+ [`${GITHUB_OIDC_HOST}:aud`]: AUDIENCE,
535
+ [`${GITHUB_OIDC_HOST}:sub`]: subject
536
+ } }
537
+ }]
538
+ });
539
+ }
540
+ /**
541
+ * The subject a trust policy trusts, or undefined when it names none. IAM
542
+ * hands documents back URL-encoded.
543
+ */
544
+ function trustedSubject(document) {
545
+ if (!document) return void 0;
546
+ let parsed;
547
+ try {
548
+ parsed = JSON.parse(safeDecode(document));
549
+ } catch {
550
+ return;
551
+ }
552
+ for (const statement of parsed.Statement ?? []) for (const operator of Object.values(statement.Condition ?? {})) {
553
+ const value = operator[`${GITHUB_OIDC_HOST}:sub`];
554
+ if (typeof value === "string") return value;
555
+ if (Array.isArray(value)) return value.join(", ");
556
+ }
557
+ }
558
+ function safeDecode(value) {
559
+ try {
560
+ return decodeURIComponent(value);
561
+ } catch {
562
+ return value;
563
+ }
564
+ }
565
+ /** GitHub's OIDC provider in this account, created if it is not there. */
566
+ async function ensureOidcProvider(iam) {
567
+ const { OpenIDConnectProviderList = [] } = await iam.send(new ListOpenIDConnectProvidersCommand({}));
568
+ const existing = OpenIDConnectProviderList.find((p) => p.Arn?.endsWith(`oidc-provider/${GITHUB_OIDC_HOST}`))?.Arn;
569
+ if (existing) return existing;
570
+ return (await iam.send(new CreateOpenIDConnectProviderCommand({
571
+ Url: `https://${GITHUB_OIDC_HOST}`,
572
+ ClientIDList: [AUDIENCE]
573
+ }))).OpenIDConnectProviderArn;
574
+ }
575
+ function isNoSuchEntity(error) {
576
+ return error.name === "NoSuchEntityException";
577
+ }
578
+ /**
579
+ * The deploy role, created or brought back to this trust and access.
580
+ *
581
+ * Converges: re-running rewrites the trust, and moves the role from one access
582
+ * to another — detaching a managed policy only when the role's
583
+ * {@link POLICY_TAG} says gkm attached it.
584
+ */
585
+ async function ensureRole(iam, name, trust, access) {
586
+ let arn;
587
+ let created = false;
588
+ let previousSubject;
589
+ let recorded;
590
+ try {
591
+ const { Role } = await iam.send(new GetRoleCommand({ RoleName: name }));
592
+ previousSubject = trustedSubject(Role.AssumeRolePolicyDocument);
593
+ await iam.send(new UpdateAssumeRolePolicyCommand({
594
+ RoleName: name,
595
+ PolicyDocument: trust
596
+ }));
597
+ arn = Role.Arn;
598
+ const { Tags = [] } = await iam.send(new ListRoleTagsCommand({ RoleName: name }));
599
+ recorded = Tags.find((tag) => tag.Key === POLICY_TAG)?.Value;
600
+ } catch (error) {
601
+ if (!isNoSuchEntity(error)) throw error;
602
+ const { Role } = await iam.send(new CreateRoleCommand({
603
+ RoleName: name,
604
+ AssumeRolePolicyDocument: trust,
605
+ Description: "Deploys from GitHub Actions (gkm deploy:github)",
606
+ MaxSessionDuration: 7200
607
+ }));
608
+ arn = Role.Arn;
609
+ created = true;
610
+ }
611
+ const detached = [];
612
+ const leftAttached = [];
613
+ const detach = async (policyArn) => {
614
+ try {
615
+ await iam.send(new DetachRolePolicyCommand({
616
+ RoleName: name,
617
+ PolicyArn: policyArn
618
+ }));
619
+ detached.push(policyArn);
620
+ } catch (error) {
621
+ if (!isNoSuchEntity(error)) throw error;
622
+ }
623
+ };
624
+ const deleteInline = async () => {
625
+ try {
626
+ await iam.send(new DeleteRolePolicyCommand({
627
+ RoleName: name,
628
+ PolicyName: SCOPED_POLICY_NAME
629
+ }));
630
+ } catch (error) {
631
+ if (!isNoSuchEntity(error)) throw error;
632
+ }
633
+ };
634
+ if ("managed" in access) {
635
+ await iam.send(new AttachRolePolicyCommand({
636
+ RoleName: name,
637
+ PolicyArn: access.managed
638
+ }));
639
+ if (recorded && recorded !== access.managed) await detach(recorded);
640
+ if (recorded !== access.managed) await iam.send(new TagRoleCommand({
641
+ RoleName: name,
642
+ Tags: [{
643
+ Key: POLICY_TAG,
644
+ Value: access.managed
645
+ }]
646
+ }));
647
+ if (!created) await deleteInline();
648
+ return {
649
+ arn,
650
+ created,
651
+ previousSubject,
652
+ detached,
653
+ leftAttached
654
+ };
655
+ }
656
+ if (access.inline) await iam.send(new PutRolePolicyCommand({
657
+ RoleName: name,
658
+ PolicyName: SCOPED_POLICY_NAME,
659
+ PolicyDocument: access.inline
660
+ }));
661
+ else if (!created) await deleteInline();
662
+ if (created) return {
663
+ arn,
664
+ created,
665
+ previousSubject,
666
+ detached,
667
+ leftAttached
668
+ };
669
+ if (recorded) {
670
+ await detach(recorded);
671
+ await iam.send(new UntagRoleCommand({
672
+ RoleName: name,
673
+ TagKeys: [POLICY_TAG]
674
+ }));
675
+ }
676
+ const { AttachedPolicies = [] } = await iam.send(new ListAttachedRolePoliciesCommand({ RoleName: name }));
677
+ for (const policy of AttachedPolicies) if (policy.PolicyArn && !detached.includes(policy.PolicyArn)) leftAttached.push(policy.PolicyArn);
678
+ return {
679
+ arn,
680
+ created,
681
+ previousSubject,
682
+ detached,
683
+ leftAttached
684
+ };
685
+ }
686
+ /**
687
+ * An IAM client for the stage's account.
688
+ *
689
+ * `fromIni` for a named profile, deliberately: it resolves exactly that
690
+ * profile — keys, assume-role, `credential_process` or SSO, whichever
691
+ * ~/.aws/config says — and never falls back to AWS_* in the environment. The
692
+ * provider chain checks the environment first, so exported staging keys would
693
+ * quietly win over `--profile prod` and the production role would land in the
694
+ * staging account.
695
+ */
696
+ async function iamFor(profile, endpoint) {
697
+ const config = { region: "us-east-1" };
698
+ if (profile) {
699
+ const { fromIni } = await import("@aws-sdk/credential-providers");
700
+ config.credentials = fromIni({ profile });
701
+ }
702
+ if (endpoint) {
703
+ config.endpoint = endpoint;
704
+ config.credentials = {
705
+ accessKeyId: "test",
706
+ secretAccessKey: "test"
707
+ };
708
+ }
709
+ return new IAMClient(config);
710
+ }
711
+ async function deployGithubCommand(options, deps = {}) {
712
+ const gh = deps.gh ?? defaultGh;
713
+ const { workspace } = await loadWorkspaceConfig(deps.cwd);
714
+ assertDeployedStage(workspace.stages, options.stage);
715
+ const repo = options.repo ?? gh([
716
+ "repo",
717
+ "view",
718
+ "--json",
719
+ "nameWithOwner",
720
+ "-q",
721
+ ".nameWithOwner"
722
+ ]);
723
+ const role = roleName(workspace.name, options.stage);
724
+ const oidc = resolveOidcSubject(gh, repo, options.stage);
725
+ const manifest = await discover({
726
+ patterns: constructGlobs(workspace),
727
+ cwd: workspace.root
728
+ });
729
+ const access = deployAccess(workspace, options.stage, options.policyArn, manifest);
730
+ const key = await readKey(options.stage, keystoreProject(workspace));
731
+ const keyPath = getKeyPath(options.stage, keystoreProject(workspace));
732
+ const hasKey = key !== null;
733
+ const remote = isRemoteStore(workspace, options.stage);
734
+ const store = await secretsStoreFor(workspace, options.stage, { ...options.profile ? { profile: options.profile } : {} });
735
+ const hasSecrets = remote && await store.read(options.stage) !== null;
736
+ const via = options.profile ? `profile "${options.profile}"` : "the default credentials";
737
+ logger.log(`\n🔐 GitHub → AWS for stage "${options.stage}"\n`);
738
+ logger.log(` Repository: ${repo}`);
739
+ logger.log(` AWS profile: ${options.profile ?? "(default credentials)"}`);
740
+ logger.log(` Role: ${role}`);
741
+ if (access.kind === "managed") logger.log(` Policy: ${access.policyArn} (${access.reason})`);
742
+ else if (access.describe.length > 0) {
743
+ logger.log(` Policy: inline "${SCOPED_POLICY_NAME}", scoped to the compose deploy — only:`);
744
+ for (const line of access.describe) logger.log(` ${line}`);
745
+ } else logger.log(" Policy: none — a compose deploy with file secrets and local state reads nothing from AWS");
746
+ logger.log(` Trusted by: ${oidc.subject} only (${SUBJECT_KINDS[oidc.kind]})`);
747
+ if (oidc.warning) logger.log(` ⚠ ${oidc.warning}`);
748
+ if (remote) logger.log(` Secrets: ${hasSecrets ? `in the store (${store.name}), read with ${via}` : `none in the store yet — gkm secrets:set <KEY> '…' --stage ${options.stage}`}`);
749
+ else logger.log(` Secrets key: ${hasKey ? keyPath : `none at ${keyPath} — run gkm secrets:init --stage ${options.stage} first`}`);
750
+ if (options.dryRun) {
751
+ if (access.kind === "scoped") {
752
+ const document = scopedPolicyDocument(access.statements("<account>"));
753
+ if (document) logger.log(`\n Inline policy:\n${JSON.stringify(JSON.parse(document), null, 2).replace(/^/gm, " ")}`);
754
+ }
755
+ logger.log("\n --dry-run: nothing changed.\n");
756
+ return {
757
+ repo,
758
+ subject: oidc.subject
759
+ };
760
+ }
761
+ const iam = deps.iam ?? await iamFor(options.profile);
762
+ const providerArn = await ensureOidcProvider(iam).catch((error) => {
763
+ if (/SSO session/i.test(String(error?.message)) && options.profile) throw new SsoSessionExpired(options.profile);
764
+ throw error;
765
+ });
766
+ const outcome = await ensureRole(iam, role, trustPolicy(providerArn, oidc.subject), access.kind === "managed" ? { managed: access.policyArn } : { inline: scopedPolicyDocument(access.statements(accountOf(providerArn))) });
767
+ const roleArn = outcome.arn;
768
+ logger.log(`\n ✓ AWS: ${roleArn}${outcome.created ? " (created)" : ""}`);
769
+ if (!outcome.created) logger.log(outcome.previousSubject === oidc.subject ? ` ✓ Trust: unchanged, ${oidc.subject}` : ` ✓ Trust: ${outcome.previousSubject ?? "(no subject)"} → ${oidc.subject}`);
770
+ for (const detached of outcome.detached) logger.log(` ✓ Detached ${detached} (attached by gkm, no longer needed)`);
771
+ if (access.kind === "scoped") for (const attached of outcome.leftAttached) logger.log(` ⚠ ${attached} is still attached to ${role}. gkm has no record of attaching it, so it is left; the compose deploy does not need it. Detach it with: aws iam detach-role-policy --role-name ${role} --policy-arn ${attached}${options.profile ? ` --profile ${options.profile}` : ""}`);
772
+ gh([
773
+ "api",
774
+ "--method",
775
+ "PUT",
776
+ `repos/${repo}/environments/${options.stage}`
777
+ ]);
778
+ gh([
779
+ "variable",
780
+ "set",
781
+ "AWS_ROLE_ARN",
782
+ "--env",
783
+ options.stage,
784
+ "--repo",
785
+ repo,
786
+ "--body",
787
+ roleArn
788
+ ]);
789
+ logger.log(` ✓ GitHub: environment "${options.stage}", AWS_ROLE_ARN`);
790
+ if (remote) {
791
+ if (!hasSecrets) logger.log(` ⚠ The "${options.stage}" store holds no secrets yet; set them with gkm secrets:set <KEY> '…' --stage ${options.stage}${options.profile ? ` (AWS_PROFILE=${options.profile})` : ""}.`);
792
+ } else if (hasKey) {
793
+ gh([
794
+ "secret",
795
+ "set",
796
+ "GKM_SECRETS_KEY",
797
+ "--env",
798
+ options.stage,
799
+ "--repo",
800
+ repo
801
+ ], key);
802
+ logger.log(" ✓ GitHub: GKM_SECRETS_KEY");
803
+ } else logger.log(` ⚠ No secrets key for "${options.stage}"; run gkm secrets:init --stage ${options.stage}, then this again.`);
804
+ logger.log(`\n Protect it: add required reviewers to the "${options.stage}" environment in the repository settings.\n`);
805
+ return {
806
+ roleArn,
807
+ repo,
808
+ subject: oidc.subject
809
+ };
810
+ }
811
+ const SUBJECT_KINDS = {
812
+ default: "the repository's default subject",
813
+ immutable: "the repository's immutable subject",
814
+ custom: "the repository's custom subject template",
815
+ assumed: "assumed: the default format"
816
+ };
817
+ /** The profile's SSO login has lapsed; the fix is one command away. */
818
+ var SsoSessionExpired = class extends GkmError {
819
+ profile;
820
+ constructor(profile) {
821
+ super(`The SSO session for profile "${profile}" has expired or is invalid. Run: aws sso login --profile ${profile}`);
822
+ this.profile = profile;
823
+ this.name = "SsoSessionExpired";
824
+ }
825
+ };
826
+ //#endregion
827
+ export { deployGithubCommand };
828
+
829
+ //# sourceMappingURL=github-DJgO5z37.mjs.map