@geekmidas/cli 10.0.0-alpha.75 → 10.0.0-alpha.76

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 (157) hide show
  1. package/dist/{LegacyStateStore-BFnXUFlx.cjs → LegacyStateStore-DwngfJxr.cjs} +2 -2
  2. package/dist/{LegacyStateStore-BFnXUFlx.cjs.map → LegacyStateStore-DwngfJxr.cjs.map} +1 -1
  3. package/dist/{LegacyStateStore-cpt3K1vx.mjs → LegacyStateStore-dyq07_Ir.mjs} +2 -2
  4. package/dist/{LegacyStateStore-cpt3K1vx.mjs.map → LegacyStateStore-dyq07_Ir.mjs.map} +1 -1
  5. package/dist/{LocalStateStore-zQGZ9b4J.cjs → LocalStateStore-B0NCde8Z.cjs} +2 -2
  6. package/dist/{LocalStateStore-zQGZ9b4J.cjs.map → LocalStateStore-B0NCde8Z.cjs.map} +1 -1
  7. package/dist/{LocalStateStore-RH9F2ZEy.mjs → LocalStateStore-DLxCCatI.mjs} +2 -2
  8. package/dist/{LocalStateStore-RH9F2ZEy.mjs.map → LocalStateStore-DLxCCatI.mjs.map} +1 -1
  9. package/dist/{S3StateStore-CT-ZMlQY.cjs → S3StateStore-BOenb-3o.cjs} +2 -2
  10. package/dist/{S3StateStore-CT-ZMlQY.cjs.map → S3StateStore-BOenb-3o.cjs.map} +1 -1
  11. package/dist/{S3StateStore-DBeBc0c0.mjs → S3StateStore-CGK_4hlo.mjs} +2 -2
  12. package/dist/{S3StateStore-DBeBc0c0.mjs.map → S3StateStore-CGK_4hlo.mjs.map} +1 -1
  13. package/dist/{SSMStateStore-rnzNfOaV.mjs → SSMStateStore-B_5_RqY-.mjs} +2 -2
  14. package/dist/{SSMStateStore-rnzNfOaV.mjs.map → SSMStateStore-B_5_RqY-.mjs.map} +1 -1
  15. package/dist/{SSMStateStore-HmsH3c4v.cjs → SSMStateStore-DYeD__7p.cjs} +2 -2
  16. package/dist/{SSMStateStore-HmsH3c4v.cjs.map → SSMStateStore-DYeD__7p.cjs.map} +1 -1
  17. package/dist/{add-Cvzdw8cf.mjs → add-B7IMXzou.mjs} +3 -3
  18. package/dist/{add-Cvzdw8cf.mjs.map → add-B7IMXzou.mjs.map} +1 -1
  19. package/dist/{add-CHBin8TF.cjs → add-j2yI3cbS.cjs} +3 -3
  20. package/dist/{add-CHBin8TF.cjs.map → add-j2yI3cbS.cjs.map} +1 -1
  21. package/dist/{aws-DojzQnLd.mjs → aws-Bja4zGSs.mjs} +13 -9
  22. package/dist/aws-Bja4zGSs.mjs.map +1 -0
  23. package/dist/{aws-DkHdTV-p.cjs → aws-CQAuluiu.cjs} +13 -9
  24. package/dist/aws-CQAuluiu.cjs.map +1 -0
  25. package/dist/awsStore-7VmS_cZR.cjs +54 -0
  26. package/dist/awsStore-7VmS_cZR.cjs.map +1 -0
  27. package/dist/awsStore-B529csle.mjs +43 -0
  28. package/dist/awsStore-B529csle.mjs.map +1 -0
  29. package/dist/{bundler-_8AEZhrs.cjs → bundler-Cf6OgaOe.cjs} +5 -5
  30. package/dist/bundler-Cf6OgaOe.cjs.map +1 -0
  31. package/dist/{bundler-xjp5RwRS.mjs → bundler-DO6bHhnb.mjs} +5 -5
  32. package/dist/bundler-DO6bHhnb.mjs.map +1 -0
  33. package/dist/{cli-BTGfA0B7.mjs → cli-BCPOHmg9.mjs} +3 -3
  34. package/dist/{cli-BTGfA0B7.mjs.map → cli-BCPOHmg9.mjs.map} +1 -1
  35. package/dist/{cli-B4ktxAsM.cjs → cli-CNanUB7a.cjs} +3 -3
  36. package/dist/{cli-B4ktxAsM.cjs.map → cli-CNanUB7a.cjs.map} +1 -1
  37. package/dist/{compose-DdH2JQJD.mjs → compose-Dq4VCtu5.mjs} +4 -3
  38. package/dist/compose-Dq4VCtu5.mjs.map +1 -0
  39. package/dist/{compose-UKyv_1yU.cjs → compose-h_6oNnHC.cjs} +4 -3
  40. package/dist/compose-h_6oNnHC.cjs.map +1 -0
  41. package/dist/{config-B38YWicj.d.cts → config-CWyhLSY1.d.cts} +3 -3
  42. package/dist/{config-B38YWicj.d.cts.map → config-CWyhLSY1.d.cts.map} +1 -1
  43. package/dist/{config-DA0kRTQe.d.mts → config-CqAvPP-f.d.mts} +3 -3
  44. package/dist/{config-DA0kRTQe.d.mts.map → config-CqAvPP-f.d.mts.map} +1 -1
  45. package/dist/config.cjs +1 -1
  46. package/dist/config.d.cts +3 -3
  47. package/dist/config.d.mts +3 -3
  48. package/dist/config.mjs +1 -1
  49. package/dist/deploy/public.cjs +6 -6
  50. package/dist/deploy/public.d.cts +3 -3
  51. package/dist/deploy/public.d.cts.map +1 -1
  52. package/dist/deploy/public.d.mts +3 -3
  53. package/dist/deploy/public.d.mts.map +1 -1
  54. package/dist/deploy/public.mjs +6 -6
  55. package/dist/{deploy-XUZoA1us.cjs → deploy-CT3R9de9.cjs} +5 -5
  56. package/dist/{deploy-XUZoA1us.cjs.map → deploy-CT3R9de9.cjs.map} +1 -1
  57. package/dist/{deploy-CuSsiFIc.mjs → deploy-CVXEx7Nm.mjs} +5 -5
  58. package/dist/{deploy-CuSsiFIc.mjs.map → deploy-CVXEx7Nm.mjs.map} +1 -1
  59. package/dist/{dokploy-DZXTQX10.mjs → dokploy-CYm2ozFs.mjs} +2 -2
  60. package/dist/{dokploy-DZXTQX10.mjs.map → dokploy-CYm2ozFs.mjs.map} +1 -1
  61. package/dist/{dokploy-Cvgg_pID.cjs → dokploy-eSGmlhhj.cjs} +2 -2
  62. package/dist/{dokploy-Cvgg_pID.cjs.map → dokploy-eSGmlhhj.cjs.map} +1 -1
  63. package/dist/{encryption-JkeMPugf.mjs → encryption-DC0rsR1W.mjs} +3 -3
  64. package/dist/{encryption-JkeMPugf.mjs.map → encryption-DC0rsR1W.mjs.map} +1 -1
  65. package/dist/{encryption-w-Ehh9DW.cjs → encryption-vS3Qzw73.cjs} +3 -3
  66. package/dist/{encryption-w-Ehh9DW.cjs.map → encryption-vS3Qzw73.cjs.map} +1 -1
  67. package/dist/{engine-CmozkHxq.mjs → engine-BOO5TWZd.mjs} +4 -4
  68. package/dist/{engine-CmozkHxq.mjs.map → engine-BOO5TWZd.mjs.map} +1 -1
  69. package/dist/{engine-zpWBMsQq.cjs → engine-C0N2d1i5.cjs} +4 -4
  70. package/dist/{engine-zpWBMsQq.cjs.map → engine-C0N2d1i5.cjs.map} +1 -1
  71. package/dist/{github-BNngHoId.mjs → github-CEaFDL6t.mjs} +6 -6
  72. package/dist/github-CEaFDL6t.mjs.map +1 -0
  73. package/dist/{github-BGdJ-Lnm.cjs → github-ClkdCOL9.cjs} +6 -6
  74. package/dist/github-ClkdCOL9.cjs.map +1 -0
  75. package/dist/{index-vMidfqhU.d.cts → index-Ccu0f_2m.d.cts} +2 -2
  76. package/dist/{index-B-1lLGzy.d.mts.map → index-Ccu0f_2m.d.cts.map} +1 -1
  77. package/dist/{index-B-1lLGzy.d.mts → index-DOxmDKqv.d.mts} +2 -2
  78. package/dist/{index-vMidfqhU.d.cts.map → index-DOxmDKqv.d.mts.map} +1 -1
  79. package/dist/index.cjs +79 -50
  80. package/dist/index.cjs.map +1 -1
  81. package/dist/index.mjs +79 -50
  82. package/dist/index.mjs.map +1 -1
  83. package/dist/migrate-BRbYtFXG.cjs +93 -0
  84. package/dist/migrate-BRbYtFXG.cjs.map +1 -0
  85. package/dist/migrate-D3NAT7Ns.mjs +93 -0
  86. package/dist/migrate-D3NAT7Ns.mjs.map +1 -0
  87. package/dist/{migrate-CgjlYeun.cjs → migrate-D5_-ylI1.cjs} +3 -3
  88. package/dist/{migrate-CgjlYeun.cjs.map → migrate-D5_-ylI1.cjs.map} +1 -1
  89. package/dist/{migrate-BLL1RTAj.mjs → migrate-DrO2p9Rl.mjs} +3 -3
  90. package/dist/{migrate-BLL1RTAj.mjs.map → migrate-DrO2p9Rl.mjs.map} +1 -1
  91. package/dist/openapi.cjs +16 -6
  92. package/dist/openapi.cjs.map +1 -1
  93. package/dist/openapi.d.cts +1 -1
  94. package/dist/openapi.d.cts.map +1 -1
  95. package/dist/openapi.d.mts +1 -1
  96. package/dist/openapi.d.mts.map +1 -1
  97. package/dist/openapi.mjs +16 -6
  98. package/dist/openapi.mjs.map +1 -1
  99. package/dist/reconcile/public.d.cts +1 -1
  100. package/dist/reconcile/public.d.mts +1 -1
  101. package/dist/{resolve-DZNx7rLy.mjs → resolve-C1muFos5.mjs} +3 -3
  102. package/dist/{resolve-DZNx7rLy.mjs.map → resolve-C1muFos5.mjs.map} +1 -1
  103. package/dist/{resolve-fevXn-wZ.cjs → resolve-Fa1Ii0BK.cjs} +3 -3
  104. package/dist/{resolve-fevXn-wZ.cjs.map → resolve-Fa1Ii0BK.cjs.map} +1 -1
  105. package/dist/{rollback-Dw-FW3X2.cjs → rollback-C9N5lKVf.cjs} +5 -5
  106. package/dist/{rollback-Dw-FW3X2.cjs.map → rollback-C9N5lKVf.cjs.map} +1 -1
  107. package/dist/{rollback-CLi5Pln_.mjs → rollback-DeQzbRqM.mjs} +5 -5
  108. package/dist/{rollback-CLi5Pln_.mjs.map → rollback-DeQzbRqM.mjs.map} +1 -1
  109. package/dist/{runtime-BzZD5HHi.d.cts → runtime-BSvzPqXW.d.mts} +2 -2
  110. package/dist/{runtime-BzZD5HHi.d.cts.map → runtime-BSvzPqXW.d.mts.map} +1 -1
  111. package/dist/{runtime-Cm6J6L7n.d.mts → runtime-Cm7QA53H.d.cts} +2 -2
  112. package/dist/{runtime-Cm6J6L7n.d.mts.map → runtime-Cm7QA53H.d.cts.map} +1 -1
  113. package/dist/secretsManager-DUXW3fQt.cjs +70 -0
  114. package/dist/secretsManager-DUXW3fQt.cjs.map +1 -0
  115. package/dist/secretsManager-Ti0oZwsS.mjs +70 -0
  116. package/dist/secretsManager-Ti0oZwsS.mjs.map +1 -0
  117. package/dist/{sniffer-BmCvVyhq.mjs → sniffer-DR8AlRCk.mjs} +17 -17
  118. package/dist/sniffer-DR8AlRCk.mjs.map +1 -0
  119. package/dist/{sniffer-bMzrX4cO.cjs → sniffer-Y6GQOCXB.cjs} +17 -17
  120. package/dist/sniffer-Y6GQOCXB.cjs.map +1 -0
  121. package/dist/{state-kA4Fkufx.cjs → state-C2qi0iQw.cjs} +187 -24
  122. package/dist/state-C2qi0iQw.cjs.map +1 -0
  123. package/dist/{state-BrWIOce_.mjs → state-CUecOCNJ.mjs} +170 -25
  124. package/dist/state-CUecOCNJ.mjs.map +1 -0
  125. package/dist/target/public.cjs +1 -1
  126. package/dist/target/public.d.cts +2 -2
  127. package/dist/target/public.d.mts +2 -2
  128. package/dist/target/public.mjs +1 -1
  129. package/dist/{types-TzCChNrA.d.cts → types-BdptGBFS.d.cts} +59 -6
  130. package/dist/types-BdptGBFS.d.cts.map +1 -0
  131. package/dist/{types-Dp9lgx_S.d.mts → types-OxE0OAn2.d.mts} +59 -6
  132. package/dist/types-OxE0OAn2.d.mts.map +1 -0
  133. package/dist/workspace/index.cjs +1 -1
  134. package/dist/workspace/index.d.cts +2 -2
  135. package/dist/workspace/index.d.mts +2 -2
  136. package/dist/workspace/index.mjs +1 -1
  137. package/dist/{workspace-vdrcRI-m.cjs → workspace-DOm81oUo.cjs} +54 -1
  138. package/dist/workspace-DOm81oUo.cjs.map +1 -0
  139. package/dist/{workspace-C7NqCsQF.mjs → workspace-QUTqYmVy.mjs} +43 -2
  140. package/dist/workspace-QUTqYmVy.mjs.map +1 -0
  141. package/package.json +16 -15
  142. package/dist/aws-DkHdTV-p.cjs.map +0 -1
  143. package/dist/aws-DojzQnLd.mjs.map +0 -1
  144. package/dist/bundler-_8AEZhrs.cjs.map +0 -1
  145. package/dist/bundler-xjp5RwRS.mjs.map +0 -1
  146. package/dist/compose-DdH2JQJD.mjs.map +0 -1
  147. package/dist/compose-UKyv_1yU.cjs.map +0 -1
  148. package/dist/github-BGdJ-Lnm.cjs.map +0 -1
  149. package/dist/github-BNngHoId.mjs.map +0 -1
  150. package/dist/sniffer-BmCvVyhq.mjs.map +0 -1
  151. package/dist/sniffer-bMzrX4cO.cjs.map +0 -1
  152. package/dist/state-BrWIOce_.mjs.map +0 -1
  153. package/dist/state-kA4Fkufx.cjs.map +0 -1
  154. package/dist/types-Dp9lgx_S.d.mts.map +0 -1
  155. package/dist/types-TzCChNrA.d.cts.map +0 -1
  156. package/dist/workspace-C7NqCsQF.mjs.map +0 -1
  157. package/dist/workspace-vdrcRI-m.cjs.map +0 -1
@@ -1,6 +1,6 @@
1
- import { k as assertDeployedStage } from "./workspace-C7NqCsQF.mjs";
1
+ import { k as assertDeployedStage } from "./workspace-QUTqYmVy.mjs";
2
2
  import { loadWorkspaceConfig } from "./config.mjs";
3
- import { Ht as isRemoteStore, Kt as getKeyPath, Ut as secretsStoreFor, Yt as readKey, qt as keystoreProject } from "./state-BrWIOce_.mjs";
3
+ import { Gt as secretsStoreFor, Qt as readKey, Wt as isRemoteStore, Xt as keystoreProject, Yt as getKeyPath } from "./state-CUecOCNJ.mjs";
4
4
  import { execFileSync } from "node:child_process";
5
5
  import { AttachRolePolicyCommand, CreateOpenIDConnectProviderCommand, CreateRoleCommand, GetRoleCommand, IAMClient, ListOpenIDConnectProvidersCommand, UpdateAssumeRolePolicyCommand } from "@aws-sdk/client-iam";
6
6
  //#region src/deploy/github.ts
@@ -18,9 +18,9 @@ import { AttachRolePolicyCommand, CreateOpenIDConnectProviderCommand, CreateRole
18
18
  * GitHub it creates that environment and gives it what the generated deploy
19
19
  * workflow reads: `AWS_ROLE_ARN`, and — when the stage's secrets are kept in
20
20
  * the local file — its key as `GKM_SECRETS_KEY`. With `secrets.store` set to
21
- * SSM the deploy job pulls them with the role instead, so no key is handed to
22
- * GitHub, and this pushes the stage's local secrets to SSM in the same account,
23
- * with the same profile. Re-running it converges rather than duplicating.
21
+ * SSM or Secrets Manager the deploy job reads them with the role instead, so
22
+ * no key is handed to GitHub, and this checks the stage's store in the same
23
+ * account, with the same profile. Re-running it converges rather than duplicating.
24
24
  */
25
25
  const logger = console;
26
26
  const GITHUB_OIDC_HOST = "token.actions.githubusercontent.com";
@@ -210,4 +210,4 @@ var SsoSessionExpired = class extends Error {
210
210
  //#endregion
211
211
  export { deployGithubCommand };
212
212
 
213
- //# sourceMappingURL=github-BNngHoId.mjs.map
213
+ //# sourceMappingURL=github-CEaFDL6t.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-CEaFDL6t.mjs","names":[],"sources":["../src/deploy/github.ts"],"sourcesContent":["/**\n * `gkm deploy:github` — let GitHub Actions deploy one stage, with no keys.\n *\n * A stage usually lives in its own AWS account — staging in one, production in\n * another — so this runs once per stage, with that account's profile:\n *\n * gkm deploy:github --stage staging --profile acme-dev\n * gkm deploy:github --stage prod --profile acme-prod\n *\n * In the stage's account it makes sure GitHub's OIDC provider exists, and a\n * role that only this repository's `<stage>` environment can assume. On\n * GitHub it creates that environment and gives it what the generated deploy\n * workflow reads: `AWS_ROLE_ARN`, and — when the stage's secrets are kept in\n * the local file — its key as `GKM_SECRETS_KEY`. With `secrets.store` set to\n * SSM or Secrets Manager the deploy job reads them with the role instead, so\n * no key is handed to GitHub, and this checks the stage's store in the same\n * account, with the same profile. Re-running it converges rather than duplicating.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport {\n\tAttachRolePolicyCommand,\n\tCreateOpenIDConnectProviderCommand,\n\tCreateRoleCommand,\n\tGetRoleCommand,\n\tIAMClient,\n\ttype IAMClientConfig,\n\tListOpenIDConnectProvidersCommand,\n\tUpdateAssumeRolePolicyCommand,\n} from '@aws-sdk/client-iam';\nimport { loadWorkspaceConfig } from '../config.js';\nimport { getKeyPath, keystoreProject, readKey } from '../secrets/keystore.js';\nimport { isRemoteStore, secretsStoreFor } from '../secrets/store.js';\nimport { assertDeployedStage } from '../workspace/stages.js';\n\nconst logger = console;\n\nconst GITHUB_OIDC_HOST = 'token.actions.githubusercontent.com';\nconst AUDIENCE = 'sts.amazonaws.com';\n\n/**\n * What SST needs to create a stack is most of AWS, so this is the default —\n * said out loud in the output, and replaceable with `--policy-arn`.\n */\nexport const DEFAULT_POLICY_ARN = 'arn:aws:iam::aws:policy/AdministratorAccess';\n\nexport interface DeployGithubOptions {\n\tstage: string;\n\t/** The AWS profile for the stage's account. */\n\tprofile?: string;\n\t/** `owner/name`; defaults to the repository `gh` sees here. */\n\trepo?: string;\n\t/** The policy the deploy role gets. */\n\tpolicyArn?: string;\n\tdryRun?: boolean;\n}\n\n/** Runs `gh` with the given arguments and optional stdin, returning stdout. */\nexport type Gh = (args: string[], input?: string) => string;\n\nconst defaultGh: Gh = (args, input) =>\n\texecFileSync('gh', args, {\n\t\tencoding: 'utf-8',\n\t\t...(input === undefined\n\t\t\t? {}\n\t\t\t: { input, stdio: ['pipe', 'pipe', 'pipe'] as const }),\n\t}).trim();\n\n/** The role a stage deploys as: `<project>-github-<stage>`, within IAM's 64. */\nexport function roleName(project: string, stage: string): string {\n\treturn `${project}-github-${stage}`\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9+=,.@_-]/g, '-')\n\t\t.slice(0, 64);\n}\n\n/**\n * Who may assume the role: a workflow job running in this repository's\n * `<stage>` environment, and nothing else — not another branch's job, not\n * another environment's. That is what keeps a staging deploy from using the\n * production role.\n */\nexport function trustPolicy(\n\tproviderArn: string,\n\trepo: string,\n\tstage: string,\n): string {\n\treturn JSON.stringify({\n\t\tVersion: '2012-10-17',\n\t\tStatement: [\n\t\t\t{\n\t\t\t\tEffect: 'Allow',\n\t\t\t\tPrincipal: { Federated: providerArn },\n\t\t\t\tAction: 'sts:AssumeRoleWithWebIdentity',\n\t\t\t\tCondition: {\n\t\t\t\t\tStringEquals: {\n\t\t\t\t\t\t[`${GITHUB_OIDC_HOST}:aud`]: AUDIENCE,\n\t\t\t\t\t\t[`${GITHUB_OIDC_HOST}:sub`]: `repo:${repo}:environment:${stage}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t});\n}\n\n/** GitHub's OIDC provider in this account, created if it is not there. */\nexport async function ensureOidcProvider(iam: IAMClient): Promise<string> {\n\tconst { OpenIDConnectProviderList = [] } = await iam.send(\n\t\tnew ListOpenIDConnectProvidersCommand({}),\n\t);\n\tconst existing = OpenIDConnectProviderList.find((p) =>\n\t\tp.Arn?.endsWith(`oidc-provider/${GITHUB_OIDC_HOST}`),\n\t)?.Arn;\n\tif (existing) return existing;\n\n\tconst created = await iam.send(\n\t\tnew CreateOpenIDConnectProviderCommand({\n\t\t\tUrl: `https://${GITHUB_OIDC_HOST}`,\n\t\t\tClientIDList: [AUDIENCE],\n\t\t}),\n\t);\n\treturn created.OpenIDConnectProviderArn!;\n}\n\n/** The deploy role, created or brought back to this trust and policy. */\nexport async function ensureRole(\n\tiam: IAMClient,\n\tname: string,\n\ttrust: string,\n\tpolicyArn: string,\n): Promise<string> {\n\tlet arn: string;\n\ttry {\n\t\tconst { Role } = await iam.send(new GetRoleCommand({ RoleName: name }));\n\t\tawait iam.send(\n\t\t\tnew UpdateAssumeRolePolicyCommand({\n\t\t\t\tRoleName: name,\n\t\t\t\tPolicyDocument: trust,\n\t\t\t}),\n\t\t);\n\t\tarn = Role!.Arn!;\n\t} catch (error) {\n\t\tif ((error as { name?: string }).name !== 'NoSuchEntityException') {\n\t\t\tthrow error;\n\t\t}\n\t\tconst { Role } = await iam.send(\n\t\t\tnew CreateRoleCommand({\n\t\t\t\tRoleName: name,\n\t\t\t\tAssumeRolePolicyDocument: trust,\n\t\t\t\tDescription: 'Deploys from GitHub Actions (gkm deploy:github)',\n\t\t\t\t// SST deploys can run long; the default hour is tight.\n\t\t\t\tMaxSessionDuration: 3600 * 2,\n\t\t\t}),\n\t\t);\n\t\tarn = Role!.Arn!;\n\t}\n\n\t// Attaching an attached policy is a no-op, so this converges too.\n\tawait iam.send(\n\t\tnew AttachRolePolicyCommand({ RoleName: name, PolicyArn: policyArn }),\n\t);\n\treturn arn;\n}\n\n/**\n * An IAM client for the stage's account.\n *\n * `fromIni` for a named profile, deliberately: it resolves exactly that\n * profile — keys, assume-role, `credential_process` or SSO, whichever\n * ~/.aws/config says — and never falls back to AWS_* in the environment. The\n * provider chain checks the environment first, so exported staging keys would\n * quietly win over `--profile prod` and the production role would land in the\n * staging account.\n */\nexport async function iamFor(\n\tprofile?: string,\n\tendpoint?: string,\n): Promise<IAMClient> {\n\tconst config: IAMClientConfig = { region: 'us-east-1' };\n\tif (profile) {\n\t\tconst { fromIni } = await import('@aws-sdk/credential-providers');\n\t\tconfig.credentials = fromIni({ profile });\n\t}\n\tif (endpoint) {\n\t\tconfig.endpoint = endpoint;\n\t\tconfig.credentials = { accessKeyId: 'test', secretAccessKey: 'test' };\n\t}\n\treturn new IAMClient(config);\n}\n\nexport async function deployGithubCommand(\n\toptions: DeployGithubOptions,\n\tdeps: { iam?: IAMClient; gh?: Gh; cwd?: string } = {},\n): Promise<{ roleArn?: string; repo: string }> {\n\tconst gh = deps.gh ?? defaultGh;\n\tconst { workspace } = await loadWorkspaceConfig(deps.cwd);\n\tassertDeployedStage(workspace.stages, options.stage);\n\n\tconst repo =\n\t\toptions.repo ??\n\t\tgh(['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner']);\n\tconst role = roleName(workspace.name, options.stage);\n\tconst policyArn = options.policyArn ?? DEFAULT_POLICY_ARN;\n\t// Read through the keystore so a key still at the place keys used to be kept\n\t// is found, and copied to where it is kept now.\n\tconst key = await readKey(options.stage, keystoreProject(workspace));\n\tconst keyPath = getKeyPath(options.stage, keystoreProject(workspace));\n\tconst hasKey = key !== null;\n\t// A stage whose secrets are in a store is read from there by the deploy job,\n\t// with the role; it needs no key on GitHub.\n\tconst remote = isRemoteStore(workspace, options.stage);\n\t// Read from the stage's own store, with the same credentials the role is\n\t// created with: what the deploy job will find there.\n\tconst store = await secretsStoreFor(workspace, options.stage, {\n\t\t...(options.profile ? { profile: options.profile } : {}),\n\t});\n\tconst hasSecrets = remote && (await store.read(options.stage)) !== null;\n\tconst via = options.profile\n\t\t? `profile \"${options.profile}\"`\n\t\t: 'the default credentials';\n\n\tlogger.log(`\\n🔐 GitHub → AWS for stage \"${options.stage}\"\\n`);\n\tlogger.log(` Repository: ${repo}`);\n\tlogger.log(` AWS profile: ${options.profile ?? '(default credentials)'}`);\n\tlogger.log(` Role: ${role}`);\n\tlogger.log(\n\t\t` Policy: ${policyArn}${options.policyArn ? '' : ' (default; --policy-arn to narrow)'}`,\n\t);\n\tlogger.log(` Trusted by: repo:${repo}:environment:${options.stage} only`);\n\tif (remote) {\n\t\tlogger.log(\n\t\t\t` Secrets: ${hasSecrets ? `in the store (${store.name}), read with ${via}` : `none in the store yet — gkm secrets:set <KEY> '…' --stage ${options.stage}`}`,\n\t\t);\n\t} else {\n\t\tlogger.log(\n\t\t\t` Secrets key: ${hasKey ? keyPath : `none at ${keyPath} — run gkm secrets:init --stage ${options.stage} first`}`,\n\t\t);\n\t}\n\n\tif (options.dryRun) {\n\t\tlogger.log('\\n --dry-run: nothing changed.\\n');\n\t\treturn { repo };\n\t}\n\n\tconst iam = deps.iam ?? (await iamFor(options.profile));\n\tconst providerArn = await ensureOidcProvider(iam).catch((error) => {\n\t\t// The first AWS call is where an expired SSO login surfaces; the SDK's\n\t\t// message does not say which profile, and this command knows.\n\t\tif (/SSO session/i.test(String(error?.message)) && options.profile) {\n\t\t\tthrow new SsoSessionExpired(options.profile);\n\t\t}\n\t\tthrow error;\n\t});\n\tconst roleArn = await ensureRole(\n\t\tiam,\n\t\trole,\n\t\ttrustPolicy(providerArn, repo, options.stage),\n\t\tpolicyArn,\n\t);\n\tlogger.log(`\\n ✓ AWS: ${roleArn}`);\n\n\t// The environment the generated deploy workflow runs the stage in.\n\tgh(['api', '--method', 'PUT', `repos/${repo}/environments/${options.stage}`]);\n\tgh([\n\t\t'variable',\n\t\t'set',\n\t\t'AWS_ROLE_ARN',\n\t\t'--env',\n\t\toptions.stage,\n\t\t'--repo',\n\t\trepo,\n\t\t'--body',\n\t\troleArn,\n\t]);\n\tlogger.log(` ✓ GitHub: environment \"${options.stage}\", AWS_ROLE_ARN`);\n\n\tif (remote) {\n\t\t// Nothing to send: the deploy job reads the stage's store itself.\n\t\tif (!hasSecrets) {\n\t\t\tlogger.log(\n\t\t\t\t` ⚠ The \"${options.stage}\" store holds no secrets yet; set them with gkm secrets:set <KEY> '…' --stage ${options.stage}${options.profile ? ` (AWS_PROFILE=${options.profile})` : ''}.`,\n\t\t\t);\n\t\t}\n\t} else if (hasKey) {\n\t\t// Through stdin, so the key is never an argument a process list shows.\n\t\tgh(\n\t\t\t[\n\t\t\t\t'secret',\n\t\t\t\t'set',\n\t\t\t\t'GKM_SECRETS_KEY',\n\t\t\t\t'--env',\n\t\t\t\toptions.stage,\n\t\t\t\t'--repo',\n\t\t\t\trepo,\n\t\t\t],\n\t\t\tkey!,\n\t\t);\n\t\tlogger.log(' ✓ GitHub: GKM_SECRETS_KEY');\n\t} else {\n\t\tlogger.log(\n\t\t\t` ⚠ No secrets key for \"${options.stage}\"; run gkm secrets:init --stage ${options.stage}, then this again.`,\n\t\t);\n\t}\n\n\tlogger.log(\n\t\t`\\n Protect it: add required reviewers to the \"${options.stage}\" environment in the repository settings.\\n`,\n\t);\n\treturn { roleArn, repo };\n}\n\n/** The profile's SSO login has lapsed; the fix is one command away. */\nexport class SsoSessionExpired extends Error {\n\tconstructor(readonly profile: string) {\n\t\tsuper(\n\t\t\t`The SSO session for profile \"${profile}\" has expired or is invalid. Run: aws sso login --profile ${profile}`,\n\t\t);\n\t\tthis.name = 'SsoSessionExpired';\n\t}\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- const require_workspace = require("./workspace-vdrcRI-m.cjs");
1
+ const require_workspace = require("./workspace-DOm81oUo.cjs");
2
2
  const require_config = require("./config.cjs");
3
- const require_state = require("./state-kA4Fkufx.cjs");
3
+ const require_state = require("./state-C2qi0iQw.cjs");
4
4
  let node_child_process = require("node:child_process");
5
5
  let _aws_sdk_client_iam = require("@aws-sdk/client-iam");
6
6
  //#region src/deploy/github.ts
@@ -18,9 +18,9 @@ let _aws_sdk_client_iam = require("@aws-sdk/client-iam");
18
18
  * GitHub it creates that environment and gives it what the generated deploy
19
19
  * workflow reads: `AWS_ROLE_ARN`, and — when the stage's secrets are kept in
20
20
  * the local file — its key as `GKM_SECRETS_KEY`. With `secrets.store` set to
21
- * SSM the deploy job pulls them with the role instead, so no key is handed to
22
- * GitHub, and this pushes the stage's local secrets to SSM in the same account,
23
- * with the same profile. Re-running it converges rather than duplicating.
21
+ * SSM or Secrets Manager the deploy job reads them with the role instead, so
22
+ * no key is handed to GitHub, and this checks the stage's store in the same
23
+ * account, with the same profile. Re-running it converges rather than duplicating.
24
24
  */
25
25
  const logger = console;
26
26
  const GITHUB_OIDC_HOST = "token.actions.githubusercontent.com";
@@ -210,4 +210,4 @@ var SsoSessionExpired = class extends Error {
210
210
  //#endregion
211
211
  exports.deployGithubCommand = deployGithubCommand;
212
212
 
213
- //# sourceMappingURL=github-BGdJ-Lnm.cjs.map
213
+ //# sourceMappingURL=github-ClkdCOL9.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-ClkdCOL9.cjs","names":["execFileSync","ListOpenIDConnectProvidersCommand","CreateOpenIDConnectProviderCommand","GetRoleCommand","UpdateAssumeRolePolicyCommand","CreateRoleCommand","AttachRolePolicyCommand","IAMClient","loadWorkspaceConfig","readKey","keystoreProject","getKeyPath","isRemoteStore","secretsStoreFor"],"sources":["../src/deploy/github.ts"],"sourcesContent":["/**\n * `gkm deploy:github` — let GitHub Actions deploy one stage, with no keys.\n *\n * A stage usually lives in its own AWS account — staging in one, production in\n * another — so this runs once per stage, with that account's profile:\n *\n * gkm deploy:github --stage staging --profile acme-dev\n * gkm deploy:github --stage prod --profile acme-prod\n *\n * In the stage's account it makes sure GitHub's OIDC provider exists, and a\n * role that only this repository's `<stage>` environment can assume. On\n * GitHub it creates that environment and gives it what the generated deploy\n * workflow reads: `AWS_ROLE_ARN`, and — when the stage's secrets are kept in\n * the local file — its key as `GKM_SECRETS_KEY`. With `secrets.store` set to\n * SSM or Secrets Manager the deploy job reads them with the role instead, so\n * no key is handed to GitHub, and this checks the stage's store in the same\n * account, with the same profile. Re-running it converges rather than duplicating.\n */\n\nimport { execFileSync } from 'node:child_process';\nimport {\n\tAttachRolePolicyCommand,\n\tCreateOpenIDConnectProviderCommand,\n\tCreateRoleCommand,\n\tGetRoleCommand,\n\tIAMClient,\n\ttype IAMClientConfig,\n\tListOpenIDConnectProvidersCommand,\n\tUpdateAssumeRolePolicyCommand,\n} from '@aws-sdk/client-iam';\nimport { loadWorkspaceConfig } from '../config.js';\nimport { getKeyPath, keystoreProject, readKey } from '../secrets/keystore.js';\nimport { isRemoteStore, secretsStoreFor } from '../secrets/store.js';\nimport { assertDeployedStage } from '../workspace/stages.js';\n\nconst logger = console;\n\nconst GITHUB_OIDC_HOST = 'token.actions.githubusercontent.com';\nconst AUDIENCE = 'sts.amazonaws.com';\n\n/**\n * What SST needs to create a stack is most of AWS, so this is the default —\n * said out loud in the output, and replaceable with `--policy-arn`.\n */\nexport const DEFAULT_POLICY_ARN = 'arn:aws:iam::aws:policy/AdministratorAccess';\n\nexport interface DeployGithubOptions {\n\tstage: string;\n\t/** The AWS profile for the stage's account. */\n\tprofile?: string;\n\t/** `owner/name`; defaults to the repository `gh` sees here. */\n\trepo?: string;\n\t/** The policy the deploy role gets. */\n\tpolicyArn?: string;\n\tdryRun?: boolean;\n}\n\n/** Runs `gh` with the given arguments and optional stdin, returning stdout. */\nexport type Gh = (args: string[], input?: string) => string;\n\nconst defaultGh: Gh = (args, input) =>\n\texecFileSync('gh', args, {\n\t\tencoding: 'utf-8',\n\t\t...(input === undefined\n\t\t\t? {}\n\t\t\t: { input, stdio: ['pipe', 'pipe', 'pipe'] as const }),\n\t}).trim();\n\n/** The role a stage deploys as: `<project>-github-<stage>`, within IAM's 64. */\nexport function roleName(project: string, stage: string): string {\n\treturn `${project}-github-${stage}`\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9+=,.@_-]/g, '-')\n\t\t.slice(0, 64);\n}\n\n/**\n * Who may assume the role: a workflow job running in this repository's\n * `<stage>` environment, and nothing else — not another branch's job, not\n * another environment's. That is what keeps a staging deploy from using the\n * production role.\n */\nexport function trustPolicy(\n\tproviderArn: string,\n\trepo: string,\n\tstage: string,\n): string {\n\treturn JSON.stringify({\n\t\tVersion: '2012-10-17',\n\t\tStatement: [\n\t\t\t{\n\t\t\t\tEffect: 'Allow',\n\t\t\t\tPrincipal: { Federated: providerArn },\n\t\t\t\tAction: 'sts:AssumeRoleWithWebIdentity',\n\t\t\t\tCondition: {\n\t\t\t\t\tStringEquals: {\n\t\t\t\t\t\t[`${GITHUB_OIDC_HOST}:aud`]: AUDIENCE,\n\t\t\t\t\t\t[`${GITHUB_OIDC_HOST}:sub`]: `repo:${repo}:environment:${stage}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t});\n}\n\n/** GitHub's OIDC provider in this account, created if it is not there. */\nexport async function ensureOidcProvider(iam: IAMClient): Promise<string> {\n\tconst { OpenIDConnectProviderList = [] } = await iam.send(\n\t\tnew ListOpenIDConnectProvidersCommand({}),\n\t);\n\tconst existing = OpenIDConnectProviderList.find((p) =>\n\t\tp.Arn?.endsWith(`oidc-provider/${GITHUB_OIDC_HOST}`),\n\t)?.Arn;\n\tif (existing) return existing;\n\n\tconst created = await iam.send(\n\t\tnew CreateOpenIDConnectProviderCommand({\n\t\t\tUrl: `https://${GITHUB_OIDC_HOST}`,\n\t\t\tClientIDList: [AUDIENCE],\n\t\t}),\n\t);\n\treturn created.OpenIDConnectProviderArn!;\n}\n\n/** The deploy role, created or brought back to this trust and policy. */\nexport async function ensureRole(\n\tiam: IAMClient,\n\tname: string,\n\ttrust: string,\n\tpolicyArn: string,\n): Promise<string> {\n\tlet arn: string;\n\ttry {\n\t\tconst { Role } = await iam.send(new GetRoleCommand({ RoleName: name }));\n\t\tawait iam.send(\n\t\t\tnew UpdateAssumeRolePolicyCommand({\n\t\t\t\tRoleName: name,\n\t\t\t\tPolicyDocument: trust,\n\t\t\t}),\n\t\t);\n\t\tarn = Role!.Arn!;\n\t} catch (error) {\n\t\tif ((error as { name?: string }).name !== 'NoSuchEntityException') {\n\t\t\tthrow error;\n\t\t}\n\t\tconst { Role } = await iam.send(\n\t\t\tnew CreateRoleCommand({\n\t\t\t\tRoleName: name,\n\t\t\t\tAssumeRolePolicyDocument: trust,\n\t\t\t\tDescription: 'Deploys from GitHub Actions (gkm deploy:github)',\n\t\t\t\t// SST deploys can run long; the default hour is tight.\n\t\t\t\tMaxSessionDuration: 3600 * 2,\n\t\t\t}),\n\t\t);\n\t\tarn = Role!.Arn!;\n\t}\n\n\t// Attaching an attached policy is a no-op, so this converges too.\n\tawait iam.send(\n\t\tnew AttachRolePolicyCommand({ RoleName: name, PolicyArn: policyArn }),\n\t);\n\treturn arn;\n}\n\n/**\n * An IAM client for the stage's account.\n *\n * `fromIni` for a named profile, deliberately: it resolves exactly that\n * profile — keys, assume-role, `credential_process` or SSO, whichever\n * ~/.aws/config says — and never falls back to AWS_* in the environment. The\n * provider chain checks the environment first, so exported staging keys would\n * quietly win over `--profile prod` and the production role would land in the\n * staging account.\n */\nexport async function iamFor(\n\tprofile?: string,\n\tendpoint?: string,\n): Promise<IAMClient> {\n\tconst config: IAMClientConfig = { region: 'us-east-1' };\n\tif (profile) {\n\t\tconst { fromIni } = await import('@aws-sdk/credential-providers');\n\t\tconfig.credentials = fromIni({ profile });\n\t}\n\tif (endpoint) {\n\t\tconfig.endpoint = endpoint;\n\t\tconfig.credentials = { accessKeyId: 'test', secretAccessKey: 'test' };\n\t}\n\treturn new IAMClient(config);\n}\n\nexport async function deployGithubCommand(\n\toptions: DeployGithubOptions,\n\tdeps: { iam?: IAMClient; gh?: Gh; cwd?: string } = {},\n): Promise<{ roleArn?: string; repo: string }> {\n\tconst gh = deps.gh ?? defaultGh;\n\tconst { workspace } = await loadWorkspaceConfig(deps.cwd);\n\tassertDeployedStage(workspace.stages, options.stage);\n\n\tconst repo =\n\t\toptions.repo ??\n\t\tgh(['repo', 'view', '--json', 'nameWithOwner', '-q', '.nameWithOwner']);\n\tconst role = roleName(workspace.name, options.stage);\n\tconst policyArn = options.policyArn ?? DEFAULT_POLICY_ARN;\n\t// Read through the keystore so a key still at the place keys used to be kept\n\t// is found, and copied to where it is kept now.\n\tconst key = await readKey(options.stage, keystoreProject(workspace));\n\tconst keyPath = getKeyPath(options.stage, keystoreProject(workspace));\n\tconst hasKey = key !== null;\n\t// A stage whose secrets are in a store is read from there by the deploy job,\n\t// with the role; it needs no key on GitHub.\n\tconst remote = isRemoteStore(workspace, options.stage);\n\t// Read from the stage's own store, with the same credentials the role is\n\t// created with: what the deploy job will find there.\n\tconst store = await secretsStoreFor(workspace, options.stage, {\n\t\t...(options.profile ? { profile: options.profile } : {}),\n\t});\n\tconst hasSecrets = remote && (await store.read(options.stage)) !== null;\n\tconst via = options.profile\n\t\t? `profile \"${options.profile}\"`\n\t\t: 'the default credentials';\n\n\tlogger.log(`\\n🔐 GitHub → AWS for stage \"${options.stage}\"\\n`);\n\tlogger.log(` Repository: ${repo}`);\n\tlogger.log(` AWS profile: ${options.profile ?? '(default credentials)'}`);\n\tlogger.log(` Role: ${role}`);\n\tlogger.log(\n\t\t` Policy: ${policyArn}${options.policyArn ? '' : ' (default; --policy-arn to narrow)'}`,\n\t);\n\tlogger.log(` Trusted by: repo:${repo}:environment:${options.stage} only`);\n\tif (remote) {\n\t\tlogger.log(\n\t\t\t` Secrets: ${hasSecrets ? `in the store (${store.name}), read with ${via}` : `none in the store yet — gkm secrets:set <KEY> '…' --stage ${options.stage}`}`,\n\t\t);\n\t} else {\n\t\tlogger.log(\n\t\t\t` Secrets key: ${hasKey ? keyPath : `none at ${keyPath} — run gkm secrets:init --stage ${options.stage} first`}`,\n\t\t);\n\t}\n\n\tif (options.dryRun) {\n\t\tlogger.log('\\n --dry-run: nothing changed.\\n');\n\t\treturn { repo };\n\t}\n\n\tconst iam = deps.iam ?? (await iamFor(options.profile));\n\tconst providerArn = await ensureOidcProvider(iam).catch((error) => {\n\t\t// The first AWS call is where an expired SSO login surfaces; the SDK's\n\t\t// message does not say which profile, and this command knows.\n\t\tif (/SSO session/i.test(String(error?.message)) && options.profile) {\n\t\t\tthrow new SsoSessionExpired(options.profile);\n\t\t}\n\t\tthrow error;\n\t});\n\tconst roleArn = await ensureRole(\n\t\tiam,\n\t\trole,\n\t\ttrustPolicy(providerArn, repo, options.stage),\n\t\tpolicyArn,\n\t);\n\tlogger.log(`\\n ✓ AWS: ${roleArn}`);\n\n\t// The environment the generated deploy workflow runs the stage in.\n\tgh(['api', '--method', 'PUT', `repos/${repo}/environments/${options.stage}`]);\n\tgh([\n\t\t'variable',\n\t\t'set',\n\t\t'AWS_ROLE_ARN',\n\t\t'--env',\n\t\toptions.stage,\n\t\t'--repo',\n\t\trepo,\n\t\t'--body',\n\t\troleArn,\n\t]);\n\tlogger.log(` ✓ GitHub: environment \"${options.stage}\", AWS_ROLE_ARN`);\n\n\tif (remote) {\n\t\t// Nothing to send: the deploy job reads the stage's store itself.\n\t\tif (!hasSecrets) {\n\t\t\tlogger.log(\n\t\t\t\t` ⚠ The \"${options.stage}\" store holds no secrets yet; set them with gkm secrets:set <KEY> '…' --stage ${options.stage}${options.profile ? ` (AWS_PROFILE=${options.profile})` : ''}.`,\n\t\t\t);\n\t\t}\n\t} else if (hasKey) {\n\t\t// Through stdin, so the key is never an argument a process list shows.\n\t\tgh(\n\t\t\t[\n\t\t\t\t'secret',\n\t\t\t\t'set',\n\t\t\t\t'GKM_SECRETS_KEY',\n\t\t\t\t'--env',\n\t\t\t\toptions.stage,\n\t\t\t\t'--repo',\n\t\t\t\trepo,\n\t\t\t],\n\t\t\tkey!,\n\t\t);\n\t\tlogger.log(' ✓ GitHub: GKM_SECRETS_KEY');\n\t} else {\n\t\tlogger.log(\n\t\t\t` ⚠ No secrets key for \"${options.stage}\"; run gkm secrets:init --stage ${options.stage}, then this again.`,\n\t\t);\n\t}\n\n\tlogger.log(\n\t\t`\\n Protect it: add required reviewers to the \"${options.stage}\" environment in the repository settings.\\n`,\n\t);\n\treturn { roleArn, repo };\n}\n\n/** The profile's SSO login has lapsed; the fix is one command away. */\nexport class SsoSessionExpired extends Error {\n\tconstructor(readonly profile: string) {\n\t\tsuper(\n\t\t\t`The SSO session for profile \"${profile}\" has expired or is invalid. Run: aws sso login --profile ${profile}`,\n\t\t);\n\t\tthis.name = 'SsoSessionExpired';\n\t}\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { E as WorkspaceInput, S as NormalizedWorkspace, T as WorkspaceConfig, a as Routes, k as Framework, l as AppsRecord, r as GkmConfig, v as InferredWorkspaceConfig, y as LoadedConfig } from "./types-TzCChNrA.cjs";
1
+ import { E as WorkspaceInput, S as NormalizedWorkspace, T as WorkspaceConfig, a as Routes, k as Framework, l as AppsRecord, r as GkmConfig, v as InferredWorkspaceConfig, y as LoadedConfig } from "./types-BdptGBFS.cjs";
2
2
  //#region src/workspace/publicEnv.d.ts
3
3
  /**
4
4
  * All public env-var prefixes the toolbox understands.
@@ -166,4 +166,4 @@ declare function getEndpointForStage(dokployConfig: {
166
166
  } | undefined, stage: string): string | undefined;
167
167
  //#endregion
168
168
  export { constructPatterns as a, getAppGkmConfig as c, processConfig as d, workspaceConstructGlobs as f, stripPublicPrefix as g, getPublicEnvPrefix as h, assertNoMovedDeployKeys as i, getEndpointForStage as l, PUBLIC_ENV_PREFIXES as m, allConstructGlobs as n, defineWorkspace as o, wrapSingleAppAsWorkspace as p, appConstructGlobs as r, getAppBuildOrder as s, DokployRegistryMoved as t, normalizeWorkspace as u };
169
- //# sourceMappingURL=index-vMidfqhU.d.cts.map
169
+ //# sourceMappingURL=index-Ccu0f_2m.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-B-1lLGzy.d.mts","names":[],"sources":["../src/workspace/publicEnv.ts","../src/workspace/index.ts"],"mappings":";;;;;;;;;cASa;;;;;;;;;;;;;;;iBAoBG,mBAAmB,YAAY;;;;;iBAoB/B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC6ElB,sBAAsB,cAAc,YACnD,QAAQ,eAAe,SACrB,wBAAwB;;;;iBAgCX,mBACf,QAAQ,iBACR,cACE;;;;;iBAgDa,yBACf,QAAQ,WACR,cACE;;;;;;;;;;;;cA8DU,6BAA6B;WACpB;EAArB,YAAqB;;;iBAUN,wBAAwB;iBAOxB,cACf,QAAQ,YAAY,iBACpB,cACE;;;;;;;iBA+Ba,wBACf,WAAW;;;;;;;;;;;;iBAkBI,kBACf,WAAW,qBACX;;;;;;;iBAsBe,kBAAkB,WAAW;;iBAa7B,kBAAkB,QAAQ;;;;;iBAS1B,gBACf,WAAW,qBACX,kBACE;;;;;iBAgCa,iBAAiB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoD5B,oBACf;EACK;EAAmB,YAAY;eAEpC"}
1
+ {"version":3,"file":"index-Ccu0f_2m.d.cts","names":[],"sources":["../src/workspace/publicEnv.ts","../src/workspace/index.ts"],"mappings":";;;;;;;;;cASa;;;;;;;;;;;;;;;iBAoBG,mBAAmB,YAAY;;;;;iBAoB/B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC8ElB,sBAAsB,cAAc,YACnD,QAAQ,eAAe,SACrB,wBAAwB;;;;iBAiCX,mBACf,QAAQ,iBACR,cACE;;;;;iBAgDa,yBACf,QAAQ,WACR,cACE;;;;;;;;;;;;cA8DU,6BAA6B;WACpB;EAArB,YAAqB;;;iBAUN,wBAAwB;iBAOxB,cACf,QAAQ,YAAY,iBACpB,cACE;;;;;;;iBAgCa,wBACf,WAAW;;;;;;;;;;;;iBAkBI,kBACf,WAAW,qBACX;;;;;;;iBAsBe,kBAAkB,WAAW;;iBAa7B,kBAAkB,QAAQ;;;;;iBAS1B,gBACf,WAAW,qBACX,kBACE;;;;;iBAgCa,iBAAiB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoD5B,oBACf;EACK;EAAmB,YAAY;eAEpC"}
@@ -1,4 +1,4 @@
1
- import { E as WorkspaceInput, S as NormalizedWorkspace, T as WorkspaceConfig, a as Routes, k as Framework, l as AppsRecord, r as GkmConfig, v as InferredWorkspaceConfig, y as LoadedConfig } from "./types-Dp9lgx_S.mjs";
1
+ import { E as WorkspaceInput, S as NormalizedWorkspace, T as WorkspaceConfig, a as Routes, k as Framework, l as AppsRecord, r as GkmConfig, v as InferredWorkspaceConfig, y as LoadedConfig } from "./types-OxE0OAn2.mjs";
2
2
  //#region src/workspace/publicEnv.d.ts
3
3
  /**
4
4
  * All public env-var prefixes the toolbox understands.
@@ -166,4 +166,4 @@ declare function getEndpointForStage(dokployConfig: {
166
166
  } | undefined, stage: string): string | undefined;
167
167
  //#endregion
168
168
  export { constructPatterns as a, getAppGkmConfig as c, processConfig as d, workspaceConstructGlobs as f, stripPublicPrefix as g, getPublicEnvPrefix as h, assertNoMovedDeployKeys as i, getEndpointForStage as l, PUBLIC_ENV_PREFIXES as m, allConstructGlobs as n, defineWorkspace as o, wrapSingleAppAsWorkspace as p, appConstructGlobs as r, getAppBuildOrder as s, DokployRegistryMoved as t, normalizeWorkspace as u };
169
- //# sourceMappingURL=index-B-1lLGzy.d.mts.map
169
+ //# sourceMappingURL=index-DOxmDKqv.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-vMidfqhU.d.cts","names":[],"sources":["../src/workspace/publicEnv.ts","../src/workspace/index.ts"],"mappings":";;;;;;;;;cASa;;;;;;;;;;;;;;;iBAoBG,mBAAmB,YAAY;;;;;iBAoB/B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC6ElB,sBAAsB,cAAc,YACnD,QAAQ,eAAe,SACrB,wBAAwB;;;;iBAgCX,mBACf,QAAQ,iBACR,cACE;;;;;iBAgDa,yBACf,QAAQ,WACR,cACE;;;;;;;;;;;;cA8DU,6BAA6B;WACpB;EAArB,YAAqB;;;iBAUN,wBAAwB;iBAOxB,cACf,QAAQ,YAAY,iBACpB,cACE;;;;;;;iBA+Ba,wBACf,WAAW;;;;;;;;;;;;iBAkBI,kBACf,WAAW,qBACX;;;;;;;iBAsBe,kBAAkB,WAAW;;iBAa7B,kBAAkB,QAAQ;;;;;iBAS1B,gBACf,WAAW,qBACX,kBACE;;;;;iBAgCa,iBAAiB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoD5B,oBACf;EACK;EAAmB,YAAY;eAEpC"}
1
+ {"version":3,"file":"index-DOxmDKqv.d.mts","names":[],"sources":["../src/workspace/publicEnv.ts","../src/workspace/index.ts"],"mappings":";;;;;;;;;cASa;;;;;;;;;;;;;;;iBAoBG,mBAAmB,YAAY;;;;;iBAoB/B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC8ElB,sBAAsB,cAAc,YACnD,QAAQ,eAAe,SACrB,wBAAwB;;;;iBAiCX,mBACf,QAAQ,iBACR,cACE;;;;;iBAgDa,yBACf,QAAQ,WACR,cACE;;;;;;;;;;;;cA8DU,6BAA6B;WACpB;EAArB,YAAqB;;;iBAUN,wBAAwB;iBAOxB,cACf,QAAQ,YAAY,iBACpB,cACE;;;;;;;iBAgCa,wBACf,WAAW;;;;;;;;;;;;iBAkBI,kBACf,WAAW,qBACX;;;;;;;iBAsBe,kBAAkB,WAAW;;iBAa7B,kBAAkB,QAAQ;;;;;iBAS1B,gBACf,WAAW,qBACX,kBACE;;;;;iBAgCa,iBAAiB,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoD5B,oBACf;EACK;EAAmB,YAAY;eAEpC"}
package/dist/index.cjs CHANGED
@@ -5,20 +5,20 @@ const require_run = require("./run-fVZ-rLnc.cjs");
5
5
  const require_credentials = require("./credentials-BVs7mrtw.cjs");
6
6
  const require_discover = require("./discover-D1It5r_h.cjs");
7
7
  const require_derive = require("./derive-DAbo49sm.cjs");
8
- const require_workspace = require("./workspace-vdrcRI-m.cjs");
8
+ const require_workspace = require("./workspace-DOm81oUo.cjs");
9
9
  const require_config = require("./config.cjs");
10
- const require_state = require("./state-kA4Fkufx.cjs");
10
+ const require_state = require("./state-C2qi0iQw.cjs");
11
11
  const require_EndpointGenerator = require("./EndpointGenerator-CP6sBvQV.cjs");
12
- const require_sniffer = require("./sniffer-bMzrX4cO.cjs");
13
12
  const require_openapi = require("./openapi.cjs");
14
13
  const require_SubscriberGenerator = require("./SubscriberGenerator-CajwOa5W.cjs");
15
14
  const require_appPorts = require("./appPorts-Cu79hJF6.cjs");
16
15
  const require_drivers = require("./drivers-BdvtCKc7.cjs");
17
16
  const require_emit = require("./emit-Dmc1nvdS.cjs");
18
- const require_deploy = require("./deploy-XUZoA1us.cjs");
19
- const require_compose = require("./compose-UKyv_1yU.cjs");
17
+ const require_sniffer = require("./sniffer-Y6GQOCXB.cjs");
18
+ const require_deploy = require("./deploy-CT3R9de9.cjs");
19
+ const require_compose = require("./compose-h_6oNnHC.cjs");
20
20
  const require_credentialSchemas = require("./credentialSchemas-DCR4Wd1W.cjs");
21
- const require_LocalStateStore = require("./LocalStateStore-zQGZ9b4J.cjs");
21
+ const require_LocalStateStore = require("./LocalStateStore-B0NCde8Z.cjs");
22
22
  const require_utils = require("./utils-D2Nk1Nv2.cjs");
23
23
  const require_ready = require("./ready-BB9xS4S9.cjs");
24
24
  let node_path = require("node:path");
@@ -53,7 +53,7 @@ crypto = require_rolldown_runtime.__toESM(crypto, 1);
53
53
  let _geekmidas_constructs_functions = require("@geekmidas/constructs/functions");
54
54
  let _geekmidas_constructs_topic = require("@geekmidas/constructs/topic");
55
55
  //#region package.json
56
- var version = "10.0.0-alpha.75";
56
+ var version = "10.0.0-alpha.76";
57
57
  //#endregion
58
58
  //#region src/prompt.ts
59
59
  /**
@@ -136,7 +136,7 @@ const logger$8 = console;
136
136
  * Validate Dokploy token by making a test API call
137
137
  */
138
138
  async function validateDokployToken(endpoint, token) {
139
- const { DokployApi } = await Promise.resolve().then(() => require("./sniffer-bMzrX4cO.cjs")).then((n) => n.dokploy_api_exports);
139
+ const { DokployApi } = await Promise.resolve().then(() => require("./sniffer-Y6GQOCXB.cjs")).then((n) => n.dokploy_api_exports);
140
140
  return new DokployApi({
141
141
  baseUrl: endpoint,
142
142
  token
@@ -1533,10 +1533,10 @@ async function execCommand(commandArgs, options = {}) {
1533
1533
  if (!commandArgs[0]) throw new NoCommandSpecified();
1534
1534
  const defaultEnv = require_state.loadEnvFiles(".env");
1535
1535
  if (defaultEnv.loaded.length > 0) logger$6.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
1536
- const { credentials, secretsJsonPath, appName } = await require_state.prepareEntryCredentials({ cwd });
1536
+ const { credentials, secretsJsonPath, appName } = require_state.isImageBuild() ? await imageBuildEntry(cwd) : await require_state.prepareEntryCredentials({ cwd });
1537
1537
  if (appName) logger$6.log(`📦 App: ${appName}`);
1538
1538
  const secretCount = Object.keys(credentials).filter((k) => k !== "PORT").length;
1539
- if (secretCount > 0) logger$6.log(`🔐 Loaded ${secretCount} secret(s)`);
1539
+ if (secretCount > 0 && !require_state.isImageBuild()) logger$6.log(`🔐 Loaded ${secretCount} secret(s)`);
1540
1540
  const preloadDir = (0, node_path.join)(cwd, ".gkm");
1541
1541
  await (0, node_fs_promises.mkdir)(preloadDir, { recursive: true });
1542
1542
  const preloadPath = (0, node_path.join)(preloadDir, "credentials-preload.mjs");
@@ -1562,6 +1562,23 @@ async function execCommand(commandArgs, options = {}) {
1562
1562
  });
1563
1563
  if (exitCode !== 0) process.exit(exitCode);
1564
1564
  }
1565
+ /**
1566
+ * `gkm exec` inside an image build: the public values the Dockerfile's build
1567
+ * args set, written where the preload reads them. No workspace is loaded, no
1568
+ * secret read and no address resolved.
1569
+ */
1570
+ async function imageBuildEntry(cwd) {
1571
+ const credentials = require_state.imageBuildCredentials();
1572
+ logger$6.log(`🐳 Image build: ${Object.keys(credentials).length} public value(s) from the build args`);
1573
+ const dir = (0, node_path.join)(cwd, ".gkm");
1574
+ await (0, node_fs_promises.mkdir)(dir, { recursive: true });
1575
+ const secretsJsonPath = (0, node_path.join)(dir, "image-build-env.json");
1576
+ await (0, node_fs_promises.writeFile)(secretsJsonPath, JSON.stringify(credentials, null, 2));
1577
+ return {
1578
+ credentials,
1579
+ secretsJsonPath
1580
+ };
1581
+ }
1565
1582
  //#endregion
1566
1583
  //#region src/dev/index.ts
1567
1584
  const logger$5 = console;
@@ -2042,9 +2059,9 @@ async function workspaceDevCommand(configured, options) {
2042
2059
  for (const { id, port } of fakes) logger$5.log(`🎭 ${id} fake: http://localhost:${port}`);
2043
2060
  logger$5.log(options.migrate || options.seed ? "🗄️ Migrating the databases" : "🗄️ Checking for pending migrations");
2044
2061
  if (options.migrate || options.seed) {
2045
- const { prepareDevDatabases } = await Promise.resolve().then(() => require("./migrate-CgjlYeun.cjs"));
2062
+ const { prepareDevDatabases } = await Promise.resolve().then(() => require("./migrate-D5_-ylI1.cjs"));
2046
2063
  await prepareDevDatabases(workspace, reconciled.env, { seed: !!options.seed });
2047
- } else await Promise.resolve().then(() => require("./migrate-CgjlYeun.cjs")).then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
2064
+ } else await Promise.resolve().then(() => require("./migrate-D5_-ylI1.cjs")).then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
2048
2065
  logger$5.log(`⚠️ Could not check for pending migrations: ${error instanceof Error ? error.message : String(error)}`);
2049
2066
  });
2050
2067
  const appUrls = {};
@@ -3052,7 +3069,7 @@ async function buildApp(input) {
3052
3069
  if (production?.bundle && !input.skipBundle) {
3053
3070
  const outputDir = (0, node_path.join)(appRoot, ".gkm", "server");
3054
3071
  const entryPoint = await writeSurfaceServer(outputDir, production);
3055
- const { bundleServer } = await Promise.resolve().then(() => require("./bundler-_8AEZhrs.cjs"));
3072
+ const { bundleServer } = await Promise.resolve().then(() => require("./bundler-Cf6OgaOe.cjs"));
3056
3073
  await bundleServer({
3057
3074
  entryPoint,
3058
3075
  outputDir: (0, node_path.join)(outputDir, "dist"),
@@ -3176,7 +3193,7 @@ async function buildWorkers(input) {
3176
3193
  });
3177
3194
  logger$4.log(`Generated worker ${worker.id}: ${crons.length} crons, ${queues.length} queues, ${subscribers.length} subscribers`);
3178
3195
  if (!input.bundle) continue;
3179
- const { bundleServer } = await Promise.resolve().then(() => require("./bundler-_8AEZhrs.cjs"));
3196
+ const { bundleServer } = await Promise.resolve().then(() => require("./bundler-Cf6OgaOe.cjs"));
3180
3197
  const outfile = require_state.workerBundleName(worker.id);
3181
3198
  await bundleServer({
3182
3199
  entryPoint,
@@ -3246,7 +3263,7 @@ async function buildForTarget(target, context, appRoot, workspaceRoot, endpointG
3246
3263
  let masterKey;
3247
3264
  if (context.production?.bundle && !skipBundle) {
3248
3265
  logger$4.log(`\n📦 Bundling production server...`);
3249
- const { bundleServer } = await Promise.resolve().then(() => require("./bundler-_8AEZhrs.cjs"));
3266
+ const { bundleServer } = await Promise.resolve().then(() => require("./bundler-Cf6OgaOe.cjs"));
3250
3267
  const allConstructs = [
3251
3268
  ...endpoints.map((e) => e.construct),
3252
3269
  ...functions.map((f) => f.construct),
@@ -4970,25 +4987,25 @@ function loadPackageJson() {
4970
4987
  * Run: pnpm --filter @geekmidas/cli sync-versions
4971
4988
  */
4972
4989
  const GEEKMIDAS_VERSIONS = {
4973
- "@geekmidas/audit": "~10.0.0-alpha.75",
4974
- "@geekmidas/auth": "~10.0.0-alpha.75",
4975
- "@geekmidas/cache": "~10.0.0-alpha.75",
4976
- "@geekmidas/client": "~10.0.0-alpha.75",
4977
- "@geekmidas/cloud": "~10.0.0-alpha.75",
4978
- "@geekmidas/constructs": "~10.0.0-alpha.75",
4979
- "@geekmidas/db": "~10.0.0-alpha.75",
4980
- "@geekmidas/emailkit": "~10.0.0-alpha.75",
4981
- "@geekmidas/envkit": "~10.0.0-alpha.75",
4982
- "@geekmidas/errors": "~10.0.0-alpha.75",
4983
- "@geekmidas/events": "~10.0.0-alpha.75",
4984
- "@geekmidas/logger": "~10.0.0-alpha.75",
4985
- "@geekmidas/manifest": "~10.0.0-alpha.75",
4986
- "@geekmidas/rate-limit": "~10.0.0-alpha.75",
4987
- "@geekmidas/schema": "~10.0.0-alpha.75",
4988
- "@geekmidas/services": "~10.0.0-alpha.75",
4989
- "@geekmidas/storage": "~10.0.0-alpha.75",
4990
- "@geekmidas/telescope": "~10.0.0-alpha.75",
4991
- "@geekmidas/testkit": "~10.0.0-alpha.75",
4990
+ "@geekmidas/audit": "~10.0.0-alpha.76",
4991
+ "@geekmidas/auth": "~10.0.0-alpha.76",
4992
+ "@geekmidas/cache": "~10.0.0-alpha.76",
4993
+ "@geekmidas/client": "~10.0.0-alpha.76",
4994
+ "@geekmidas/cloud": "~10.0.0-alpha.76",
4995
+ "@geekmidas/constructs": "~10.0.0-alpha.76",
4996
+ "@geekmidas/db": "~10.0.0-alpha.76",
4997
+ "@geekmidas/emailkit": "~10.0.0-alpha.76",
4998
+ "@geekmidas/envkit": "~10.0.0-alpha.76",
4999
+ "@geekmidas/errors": "~10.0.0-alpha.76",
5000
+ "@geekmidas/events": "~10.0.0-alpha.76",
5001
+ "@geekmidas/logger": "~10.0.0-alpha.76",
5002
+ "@geekmidas/manifest": "~10.0.0-alpha.76",
5003
+ "@geekmidas/rate-limit": "~10.0.0-alpha.76",
5004
+ "@geekmidas/schema": "~10.0.0-alpha.76",
5005
+ "@geekmidas/services": "~10.0.0-alpha.76",
5006
+ "@geekmidas/storage": "~10.0.0-alpha.76",
5007
+ "@geekmidas/telescope": "~10.0.0-alpha.76",
5008
+ "@geekmidas/testkit": "~10.0.0-alpha.76",
4992
5009
  "@geekmidas/cli": `~${loadPackageJson().version}`
4993
5010
  };
4994
5011
  //#endregion
@@ -7046,6 +7063,7 @@ function secretsStore(options) {
7046
7063
  return `
7047
7064
  // Deployed stages keep their secrets in SSM, in the account each stage
7048
7065
  // deploys to: \`gkm secrets:set <KEY> '…' --stage <stage>\` writes there.
7066
+ // Past 8 KB a stage needs { provider: 'secrets-manager', region } instead.
7049
7067
  store: { provider: 'ssm', region: '${options.region}' },`;
7050
7068
  }
7051
7069
  /**
@@ -10141,8 +10159,8 @@ ${dbPasswordEntries.map(([key, value]) => `${key}=${value}`).join("\n")}
10141
10159
  //#region src/secrets/index.ts
10142
10160
  const logger$2 = console;
10143
10161
  /**
10144
- * The store the stage named on the command line keeps its secrets in — SSM in
10145
- * its account, for a deployed stage kept there. Outside any workspace nothing
10162
+ * The store the stage named on the command line keeps its secrets in — SSM or
10163
+ * Secrets Manager in its account, for a deployed stage kept there. Outside any workspace nothing
10146
10164
  * names a store, so it is the file.
10147
10165
  */
10148
10166
  async function storeFor(stage) {
@@ -10378,7 +10396,7 @@ const logger$1 = console;
10378
10396
  *
10379
10397
  * Orchestrates:
10380
10398
  * 1. Load workspace config
10381
- * 2. Resolve secrets (local → SSM → generate fresh)
10399
+ * 2. Resolve secrets (local → the stage's store → generate fresh)
10382
10400
  * 3. Write docker/.env from secrets
10383
10401
  * 4. Start Docker services
10384
10402
  */
@@ -10546,7 +10564,7 @@ function reconcileSecrets(secrets, workspace, containers = []) {
10546
10564
  /**
10547
10565
  * Build a fresh StageSecrets object for a workspace: service credentials,
10548
10566
  * connection URLs, and custom secrets. Pure — does not write to disk or touch
10549
- * SSM. Service passwords are freshly randomized, so the result must be the same
10567
+ * any store. Service passwords are freshly randomized, so the result must be the same
10550
10568
  * one used to start the matching Docker containers.
10551
10569
  * @internal Exported for reuse by `gkm test` auto-setup.
10552
10570
  */
@@ -10779,7 +10797,7 @@ function testDatabases(reconciled) {
10779
10797
  * starts without the reference data the app needs.
10780
10798
  */
10781
10799
  async function migrateTestStage(workspace, env) {
10782
- const { migrateAndSeed } = await Promise.resolve().then(() => require("./migrate-CgjlYeun.cjs"));
10800
+ const { migrateAndSeed } = await Promise.resolve().then(() => require("./migrate-D5_-ylI1.cjs"));
10783
10801
  const { discover } = await Promise.resolve().then(() => require("./discover-D1It5r_h.cjs")).then((n) => n.discover_exports);
10784
10802
  const sources = {};
10785
10803
  const manifest = await discover({
@@ -11212,7 +11230,7 @@ program.command("migrate").description("Apply each database construct's migratio
11212
11230
  try {
11213
11231
  const globalOptions = program.opts();
11214
11232
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11215
- const { migrateCommand } = await Promise.resolve().then(() => require("./migrate-CgjlYeun.cjs"));
11233
+ const { migrateCommand } = await Promise.resolve().then(() => require("./migrate-D5_-ylI1.cjs"));
11216
11234
  await migrateCommand({
11217
11235
  ...options,
11218
11236
  ...construct ? { construct } : {}
@@ -11226,7 +11244,7 @@ program.command("seed").description("Migrate, then run each database construct's
11226
11244
  try {
11227
11245
  const globalOptions = program.opts();
11228
11246
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11229
- const { seedCommand } = await Promise.resolve().then(() => require("./migrate-CgjlYeun.cjs"));
11247
+ const { seedCommand } = await Promise.resolve().then(() => require("./migrate-D5_-ylI1.cjs"));
11230
11248
  await seedCommand({
11231
11249
  ...options,
11232
11250
  ...construct ? { construct } : {}
@@ -11240,7 +11258,7 @@ program.command("migration").description("Write a construct's next migration: an
11240
11258
  try {
11241
11259
  const globalOptions = program.opts();
11242
11260
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11243
- const { migrationCommand } = await Promise.resolve().then(() => require("./migrate-CgjlYeun.cjs"));
11261
+ const { migrationCommand } = await Promise.resolve().then(() => require("./migrate-D5_-ylI1.cjs"));
11244
11262
  await migrationCommand({
11245
11263
  construct,
11246
11264
  ...name ? { name } : {}
@@ -11334,7 +11352,7 @@ program.command("secrets:add").description("Build the keys a stage must be given
11334
11352
  try {
11335
11353
  const globalOptions = program.opts();
11336
11354
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11337
- const { secretsAddCommand } = await Promise.resolve().then(() => require("./add-CHBin8TF.cjs"));
11355
+ const { secretsAddCommand } = await Promise.resolve().then(() => require("./add-j2yI3cbS.cjs"));
11338
11356
  await secretsAddCommand(options);
11339
11357
  } catch (error) {
11340
11358
  console.error(formatError(error));
@@ -11345,7 +11363,7 @@ program.command("encryption:rotate").description("Add a new current key to an En
11345
11363
  try {
11346
11364
  const globalOptions = program.opts();
11347
11365
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11348
- const { encryptionRotateCommand } = await Promise.resolve().then(() => require("./encryption-w-Ehh9DW.cjs"));
11366
+ const { encryptionRotateCommand } = await Promise.resolve().then(() => require("./encryption-vS3Qzw73.cjs"));
11349
11367
  await encryptionRotateCommand(construct, options);
11350
11368
  } catch (error) {
11351
11369
  console.error(formatError(error));
@@ -11356,7 +11374,7 @@ program.command("encryption:retire").description("Remove an old key from an Encr
11356
11374
  try {
11357
11375
  const globalOptions = program.opts();
11358
11376
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11359
- const { encryptionRetireCommand } = await Promise.resolve().then(() => require("./encryption-w-Ehh9DW.cjs"));
11377
+ const { encryptionRetireCommand } = await Promise.resolve().then(() => require("./encryption-vS3Qzw73.cjs"));
11360
11378
  await encryptionRetireCommand(construct, key, options);
11361
11379
  } catch (error) {
11362
11380
  console.error(formatError(error));
@@ -11399,7 +11417,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
11399
11417
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11400
11418
  const { loadWorkspaceConfig } = await Promise.resolve().then(() => require("./config.cjs"));
11401
11419
  const { reconcileMissingSecrets } = await Promise.resolve().then(() => require("./reconcile-CuCQBa5-.cjs"));
11402
- const { secretsStoreFor } = await Promise.resolve().then(() => require("./state-kA4Fkufx.cjs")).then((n) => n.store_exports);
11420
+ const { secretsStoreFor } = await Promise.resolve().then(() => require("./state-C2qi0iQw.cjs")).then((n) => n.store_exports);
11403
11421
  const { workspace } = await loadWorkspaceConfig();
11404
11422
  const stage = options.stage ?? workspace.stages.local;
11405
11423
  const store = await secretsStoreFor(workspace, stage);
@@ -11408,7 +11426,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
11408
11426
  console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
11409
11427
  process.exit(1);
11410
11428
  }
11411
- const { derivedContainers } = await Promise.resolve().then(() => require("./state-kA4Fkufx.cjs")).then((n) => n.workspace_exports);
11429
+ const { derivedContainers } = await Promise.resolve().then(() => require("./state-C2qi0iQw.cjs")).then((n) => n.workspace_exports);
11412
11430
  const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
11413
11431
  if (!result) {
11414
11432
  console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
@@ -11422,8 +11440,19 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
11422
11440
  process.exit(1);
11423
11441
  }
11424
11442
  });
11443
+ program.command("secrets:migrate").description("Copy a deployed stage's secrets from the configured store to another (file, ssm, secrets-manager)").requiredOption("--stage <stage>", "A deployed stage").requiredOption("--to <provider>", "file, ssm or secrets-manager").option("--region <region>", "The target's AWS region (default: the configured store's)").option("--profile <profile>", "AWS profile for the stage's account").option("--force", "Replace a stage the target already holds").action(async (options) => {
11444
+ try {
11445
+ const globalOptions = program.opts();
11446
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11447
+ const { secretsMigrateCommand } = await Promise.resolve().then(() => require("./migrate-BRbYtFXG.cjs"));
11448
+ await secretsMigrateCommand(options);
11449
+ } catch (error) {
11450
+ console.error(formatError(error));
11451
+ process.exit(1);
11452
+ }
11453
+ });
11425
11454
  program.command("deploy").description("Deploy a stage through its target").option("--target <name>", "Deploy target: dokploy, compose, sst, or one named in deploy.targets (default: deploy.default)").option("--provider <provider>", "[DEPRECATED] Use --target instead").requiredOption("--stage <stage>", "Deployment stage (e.g., production, staging)").option("--tag <tag>", "Image tag (default: stage-timestamp; compose: the commit). Compose pulls a given tag").option("--skip-push", "Skip pushing image to registry").option("--skip-build", "Skip build step (use existing build)").option("--json", "Write events as JSON lines instead of progress; never prompts").option("--dry-run", "Show what would be created or reused; change, build and push nothing").option("--atomic", "If the release fails, roll back every app it released, not only the failed ones").option("--allow-dev-services <list>", "Server targets: run MinIO and/or Mailpit (minio,mailpit) for mail and buckets the stage's secrets don't configure. Not production-grade").action(async (options) => {
11426
- const { deployCli } = await Promise.resolve().then(() => require("./cli-B4ktxAsM.cjs"));
11455
+ const { deployCli } = await Promise.resolve().then(() => require("./cli-CNanUB7a.cjs"));
11427
11456
  const globalOptions = program.opts();
11428
11457
  const code = await deployCli({
11429
11458
  cwd: (0, node_path.resolve)(globalOptions.cwd ?? process.cwd()),
@@ -11440,7 +11469,7 @@ program.command("deploy").description("Deploy a stage through its target").optio
11440
11469
  });
11441
11470
  program.command("deploy:rollback").description("Put a stage's app back on its previous release (Dokploy): one app with --app, every app with --atomic").requiredOption("--stage <stage>", "A deployed stage").option("--app <app>", "The app to roll back").option("--atomic", "Roll back every app that has an earlier release").action(async (options) => {
11442
11471
  try {
11443
- const { rollbackStage } = await Promise.resolve().then(() => require("./rollback-Dw-FW3X2.cjs")).then((n) => n.rollback_exports);
11472
+ const { rollbackStage } = await Promise.resolve().then(() => require("./rollback-C9N5lKVf.cjs")).then((n) => n.rollback_exports);
11444
11473
  const { terminalCredentials } = await Promise.resolve().then(() => require("./terminal-BL5E0xbR.cjs"));
11445
11474
  const globalOptions = program.opts();
11446
11475
  await rollbackStage({
@@ -11476,7 +11505,7 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
11476
11505
  try {
11477
11506
  const globalOptions = program.opts();
11478
11507
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
11479
- const { deployGithubCommand } = await Promise.resolve().then(() => require("./github-BGdJ-Lnm.cjs"));
11508
+ const { deployGithubCommand } = await Promise.resolve().then(() => require("./github-ClkdCOL9.cjs"));
11480
11509
  await deployGithubCommand(options);
11481
11510
  } catch (error) {
11482
11511
  console.error(formatError(error));