@ankhorage/infra 6.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/cli/commands/destroy.d.ts.map +1 -1
  4. package/dist/cli/commands/destroy.js +1 -0
  5. package/dist/cli/commands/destroy.js.map +1 -1
  6. package/dist/cli/utils/prepareInfraCommandOperationAsync.d.ts.map +1 -1
  7. package/dist/cli/utils/prepareInfraCommandOperationAsync.js +4 -1
  8. package/dist/cli/utils/prepareInfraCommandOperationAsync.js.map +1 -1
  9. package/dist/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.d.ts.map +1 -1
  10. package/dist/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.js +33 -10
  11. package/dist/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.js.map +1 -1
  12. package/dist/features/environment-lifecycle/adapters/outbound/createProjectInfraCredentialPort.d.ts +11 -0
  13. package/dist/features/environment-lifecycle/adapters/outbound/createProjectInfraCredentialPort.d.ts.map +1 -0
  14. package/dist/features/environment-lifecycle/adapters/outbound/createProjectInfraCredentialPort.js +125 -0
  15. package/dist/features/environment-lifecycle/adapters/outbound/createProjectInfraCredentialPort.js.map +1 -0
  16. package/dist/features/environment-lifecycle/adapters/outbound/removeStoredInfraCredentialsAsync.d.ts +4 -0
  17. package/dist/features/environment-lifecycle/adapters/outbound/removeStoredInfraCredentialsAsync.d.ts.map +1 -0
  18. package/dist/features/environment-lifecycle/adapters/outbound/removeStoredInfraCredentialsAsync.js +9 -0
  19. package/dist/features/environment-lifecycle/adapters/outbound/removeStoredInfraCredentialsAsync.js.map +1 -0
  20. package/dist/features/environment-lifecycle/application/use-cases/prepareInfraServicesAsync.d.ts +4 -0
  21. package/dist/features/environment-lifecycle/application/use-cases/prepareInfraServicesAsync.d.ts.map +1 -0
  22. package/dist/features/environment-lifecycle/application/use-cases/prepareInfraServicesAsync.js +15 -0
  23. package/dist/features/environment-lifecycle/application/use-cases/prepareInfraServicesAsync.js.map +1 -0
  24. package/dist/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.d.ts +1 -1
  25. package/dist/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.d.ts.map +1 -1
  26. package/dist/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.js +10 -5
  27. package/dist/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.js.map +1 -1
  28. package/dist/features/environment-lifecycle/composition/createInfraCommandServices.d.ts.map +1 -1
  29. package/dist/features/environment-lifecycle/composition/createInfraCommandServices.js +9 -3
  30. package/dist/features/environment-lifecycle/composition/createInfraCommandServices.js.map +1 -1
  31. package/dist/features/environment-lifecycle/composition/createProjectInfraLifecycle.d.ts.map +1 -1
  32. package/dist/features/environment-lifecycle/composition/createProjectInfraLifecycle.js +28 -2
  33. package/dist/features/environment-lifecycle/composition/createProjectInfraLifecycle.js.map +1 -1
  34. package/dist/features/environment-lifecycle/utils/resolveInfraEnvironmentStateDirectory.d.ts +4 -0
  35. package/dist/features/environment-lifecycle/utils/resolveInfraEnvironmentStateDirectory.d.ts.map +1 -0
  36. package/dist/features/environment-lifecycle/utils/resolveInfraEnvironmentStateDirectory.js +11 -0
  37. package/dist/features/environment-lifecycle/utils/resolveInfraEnvironmentStateDirectory.js.map +1 -0
  38. package/dist/features/environment-lifecycle/utils/resolveInfraStatePath.d.ts +1 -1
  39. package/dist/features/environment-lifecycle/utils/resolveInfraStatePath.d.ts.map +1 -1
  40. package/dist/features/environment-lifecycle/utils/resolveInfraStatePath.js +2 -6
  41. package/dist/features/environment-lifecycle/utils/resolveInfraStatePath.js.map +1 -1
  42. package/dist/types/infraCli.d.ts +7 -1
  43. package/dist/types/infraCli.d.ts.map +1 -1
  44. package/dist/types/infraCli.js.map +1 -1
  45. package/package.json +3 -2
  46. package/src/cli/commands/destroy.ts +1 -0
  47. package/src/cli/utils/prepareInfraCommandOperationAsync.ts +4 -1
  48. package/src/environmentCredentialPort.test.ts +62 -0
  49. package/src/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.ts +55 -18
  50. package/src/features/environment-lifecycle/adapters/outbound/createProjectInfraCredentialPort.ts +182 -0
  51. package/src/features/environment-lifecycle/adapters/outbound/removeStoredInfraCredentialsAsync.ts +18 -0
  52. package/src/features/environment-lifecycle/application/use-cases/prepareInfraServicesAsync.ts +23 -0
  53. package/src/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.ts +8 -4
  54. package/src/features/environment-lifecycle/composition/createInfraCommandServices.ts +9 -3
  55. package/src/features/environment-lifecycle/composition/createProjectInfraLifecycle.ts +33 -4
  56. package/src/features/environment-lifecycle/utils/resolveInfraEnvironmentStateDirectory.ts +16 -0
  57. package/src/features/environment-lifecycle/utils/resolveInfraStatePath.ts +3 -6
  58. package/src/infraUp.test.ts +31 -3
  59. package/src/prepareInfraServices.test.ts +50 -0
  60. package/src/projectCredentialLifecycle.test.ts +161 -0
  61. package/src/projectCredentialStore.test.ts +151 -0
  62. package/src/types/infraCli.ts +11 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ankhorage/infra
2
2
 
3
+ ## 7.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - afc7347: Persist provider-generated control-plane credential bundles inside Infra-owned project/environment state, reuse them across fresh processes, and remove them only with complete environment destruction.
8
+
9
+ ## 7.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - 1778b96: Add provider-neutral service preparation before workload materialization and extend trusted control-plane credential hosts with optional lookup and explicit persistence so providers can prepare bootstrap state without runtime-specific coupling. Read-only lifecycle operations remain side-effect free.
14
+
3
15
  ## 6.0.0
4
16
 
5
17
  ### Major Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # INFRA
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v5.1.4](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v6.0.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Executable infra provider and standalone CLI for Ankhorage project workflows.
9
9
 
@@ -1 +1 @@
1
- {"version":3,"file":"destroy.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/destroy.ts"],"names":[],"mappings":"AAUA,+FAA+F;AAC/F,eAAO,MAAM,OAAO;;;;;;;;CAuCuB,CAAC"}
1
+ {"version":3,"file":"destroy.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/destroy.ts"],"names":[],"mappings":"AAUA,+FAA+F;AAC/F,eAAO,MAAM,OAAO;;;;;;;;CAwCuB,CAAC"}
@@ -27,6 +27,7 @@ export const destroy = {
27
27
  await services.writeArtifacts(operation.project.projectPath, [], operation.state?.ledger);
28
28
  if (result.value.ledger === null) {
29
29
  await services.removeState(operation.project.projectPath, environment);
30
+ await services.removeCredentials(operation.project.projectPath, environment);
30
31
  }
31
32
  else {
32
33
  await services.writeState(operation.project.projectPath, {
@@ -1 +1 @@
1
- {"version":3,"file":"destroy.js","sourceRoot":"","sources":["../../../src/cli/commands/destroy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAClG,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE,+FAA+F;AAC/F,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,cAAc,EAAE,SAAS;IACzB,IAAI,EAAE,CAAC,SAAS,CAAC;IACjB,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACjC,OAAO,EAAE,6DAA6D;IACtE,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ;QACzB,MAAM,SAAS,GAAG,MAAM,iCAAiC,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnF,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACtE,MAAM,YAAY,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,IAAI,WAAW,EAAE,CAAC;QACrE,IAAI,OAAO,CAAC,SAAS,CAAC,YAAY,KAAK,YAAY,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,oCAAoC,YAAY,GAAG,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,cAAc,GAAiC;YACnD,GAAG,SAAS,CAAC,SAAS;YACtB,WAAW;YACX,YAAY,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,EAAE;YACrE,WAAW,EAAE,uBAAuB,CAClC,SAAS,CAAC,KAAK,EAAE,MAAM,EACvB,OAAO,CAAC,SAAS,CAAC,eAAe,CAClC;SACF,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,cAAc,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;QACzF,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1F,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACjC,MAAM,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE;gBACvD,aAAa,EAAE,CAAC;gBAChB,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;aAC5B,CAAC,CAAC;QACL,CAAC;QACD,oBAAoB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE;YAC9D,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW;YACrC,iBAAiB,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,CAAC;SAC9D,CAAC,CAAC;QACH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzB,CAAC;CACwC,CAAC;AAE5C,mEAAmE;AACnE,SAAS,kBAAkB,CAAC,KAAmC;IAC7D,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC5F,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import type { AppEnvironmentId } from '@ankhorage/contracts/environments';\n\nimport { INFRA_CAPABILITIES } from '../../constants.js';\nimport type { InfraCommandDefinition } from '../../types/infraCli.js';\nimport type { InfraDestroyOperationRequest } from '../../types/infraOrchestration.js';\nimport { prepareInfraCommandOperationAsync } from '../utils/prepareInfraCommandOperationAsync.js';\nimport { requireInfraSuccess } from '../utils/requireInfraSuccess.js';\nimport { resolveInfraPersistence } from '../utils/resolveInfraPersistence.js';\nimport { writeInfraStructured } from '../utils/writeInfraStructured.js';\n\n/*** Define exact-scope destruction behind environment and persistent-resource confirmation. */\nexport const destroy = {\n standaloneName: 'destroy',\n path: ['destroy'],\n capability: INFRA_CAPABILITIES[7],\n summary: 'Destroy exact owned resources behind explicit confirmation.',\n async run(request, services) {\n const operation = await prepareInfraCommandOperationAsync(request, services, true);\n const environment = requireEnvironment(request.arguments.environment);\n const confirmation = `${operation.project.projectId}:${environment}`;\n if (request.arguments.confirmation !== confirmation) {\n throw new Error(`Infra destroy requires --confirm ${confirmation}.`);\n }\n const destroyRequest: InfraDestroyOperationRequest = {\n ...operation.operation,\n environment,\n confirmation: { projectId: operation.project.projectId, environment },\n persistence: resolveInfraPersistence(\n operation.state?.ledger,\n request.arguments.deleteResources,\n ),\n };\n const result = await services.operations.destroy(destroyRequest, operation.dependencies);\n requireInfraSuccess(result, request.context);\n await services.writeArtifacts(operation.project.projectPath, [], operation.state?.ledger);\n if (result.value.ledger === null) {\n await services.removeState(operation.project.projectPath, environment);\n } else {\n await services.writeState(operation.project.projectPath, {\n schemaVersion: 1,\n desired: operation.desired,\n ledger: result.value.ledger,\n });\n }\n writeInfraStructured(request.context, request.arguments.format, {\n environment: result.value.environment,\n retainedResources: result.value.ledger?.resources.length ?? 0,\n });\n return { exitCode: 0 };\n },\n} as const satisfies InfraCommandDefinition;\n\n/*** Require the explicit destroy environment after CLI parsing. */\nfunction requireEnvironment(value: AppEnvironmentId | undefined): AppEnvironmentId {\n if (value === undefined) throw new Error('Infra destroy requires an explicit environment.');\n return value;\n}\n"]}
1
+ {"version":3,"file":"destroy.js","sourceRoot":"","sources":["../../../src/cli/commands/destroy.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppEnvironmentId } from '@ankhorage/contracts/environments';\n\nimport { INFRA_CAPABILITIES } from '../../constants.js';\nimport type { InfraCommandDefinition } from '../../types/infraCli.js';\nimport type { InfraDestroyOperationRequest } from '../../types/infraOrchestration.js';\nimport { prepareInfraCommandOperationAsync } from '../utils/prepareInfraCommandOperationAsync.js';\nimport { requireInfraSuccess } from '../utils/requireInfraSuccess.js';\nimport { resolveInfraPersistence } from '../utils/resolveInfraPersistence.js';\nimport { writeInfraStructured } from '../utils/writeInfraStructured.js';\n\n/*** Define exact-scope destruction behind environment and persistent-resource confirmation. */\nexport const destroy = {\n standaloneName: 'destroy',\n path: ['destroy'],\n capability: INFRA_CAPABILITIES[7],\n summary: 'Destroy exact owned resources behind explicit confirmation.',\n async run(request, services) {\n const operation = await prepareInfraCommandOperationAsync(request, services, true);\n const environment = requireEnvironment(request.arguments.environment);\n const confirmation = `${operation.project.projectId}:${environment}`;\n if (request.arguments.confirmation !== confirmation) {\n throw new Error(`Infra destroy requires --confirm ${confirmation}.`);\n }\n const destroyRequest: InfraDestroyOperationRequest = {\n ...operation.operation,\n environment,\n confirmation: { projectId: operation.project.projectId, environment },\n persistence: resolveInfraPersistence(\n operation.state?.ledger,\n request.arguments.deleteResources,\n ),\n };\n const result = await services.operations.destroy(destroyRequest, operation.dependencies);\n requireInfraSuccess(result, request.context);\n await services.writeArtifacts(operation.project.projectPath, [], operation.state?.ledger);\n if (result.value.ledger === null) {\n await services.removeState(operation.project.projectPath, environment);\n await services.removeCredentials(operation.project.projectPath, environment);\n } else {\n await services.writeState(operation.project.projectPath, {\n schemaVersion: 1,\n desired: operation.desired,\n ledger: result.value.ledger,\n });\n }\n writeInfraStructured(request.context, request.arguments.format, {\n environment: result.value.environment,\n retainedResources: result.value.ledger?.resources.length ?? 0,\n });\n return { exitCode: 0 };\n },\n} as const satisfies InfraCommandDefinition;\n\n/*** Require the explicit destroy environment after CLI parsing. */\nfunction requireEnvironment(value: AppEnvironmentId | undefined): AppEnvironmentId {\n if (value === undefined) throw new Error('Infra destroy requires an explicit environment.');\n return value;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"prepareInfraCommandOperationAsync.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prepareInfraCommandOperationAsync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACpB,6BAA6B,EAC9B,MAAM,yBAAyB,CAAC;AAEjC,sGAAsG;AACtG,wBAAsB,iCAAiC,CACrD,OAAO,EAAE,sBAAsB,EAC/B,QAAQ,EAAE,oBAAoB,EAC9B,gBAAgB,UAAQ,GACvB,OAAO,CAAC,6BAA6B,CAAC,CA2BxC"}
1
+ {"version":3,"file":"prepareInfraCommandOperationAsync.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prepareInfraCommandOperationAsync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACpB,6BAA6B,EAC9B,MAAM,yBAAyB,CAAC;AAEjC,sGAAsG;AACtG,wBAAsB,iCAAiC,CACrD,OAAO,EAAE,sBAAsB,EAC/B,QAAQ,EAAE,oBAAoB,EAC9B,gBAAgB,UAAQ,GACvB,OAAO,CAAC,6BAA6B,CAAC,CA8BxC"}
@@ -24,7 +24,10 @@ export async function prepareInfraCommandOperationAsync(request, services, useSt
24
24
  ...(request.arguments.environment === undefined ? {} : { environment }),
25
25
  ...(state === null ? {} : { previous: state.ledger, previousDesired: state.desired }),
26
26
  },
27
- dependencies: services.createDependencies(request.context),
27
+ dependencies: services.createDependencies(request.context, {
28
+ projectPath: project.projectPath,
29
+ environment,
30
+ }),
28
31
  };
29
32
  }
30
33
  /*** Select one exact environment specification from the canonical manifest. */
@@ -1 +1 @@
1
- {"version":3,"file":"prepareInfraCommandOperationAsync.js","sourceRoot":"","sources":["../../../src/cli/utils/prepareInfraCommandOperationAsync.ts"],"names":[],"mappings":"AASA,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,OAA+B,EAC/B,QAA8B,EAC9B,gBAAgB,GAAG,KAAK;IAExB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC;QAC5C,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG;QACxB,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,KAAK,SAAS;YAC3C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;KAChD,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,WAAW,IAAI,OAAO,CAAC;IAC7D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACzE,MAAM,cAAc,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,gBAAgB,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;IACpF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,sBAAsB,WAAW,sBAAsB,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAClF,OAAO;QACL,OAAO;QACP,KAAK;QACL,OAAO;QACP,SAAS,EAAE;YACT,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ;YACR,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;YACvE,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;SACtF;QACD,YAAY,EAAE,QAAQ,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC;KAC3D,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,SAAS,kBAAkB,CACzB,QAAuB,EACvB,WAA6B;IAE7B,IAAI,WAAW,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC;IAChE,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC;IACpE,OAAO,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC;AAC1C,CAAC;AAED,oFAAoF;AACpF,SAAS,kBAAkB,CACzB,QAAuB,EACvB,WAA6B,EAC7B,OAA6B;IAE7B,OAAO;QACL,GAAG,QAAQ;QACX,YAAY,EAAE,EAAE,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE;KACnE,CAAC;AACJ,CAAC","sourcesContent":["import type { AppEnvironmentId } from '@ankhorage/contracts/environments';\nimport type { InfraEnvironmentSpec, InfraManifest } from '@ankhorage/contracts/infra';\n\nimport type {\n InfraCommandRunRequest,\n InfraCommandServices,\n PreparedInfraCommandOperation,\n} from '../../types/infraCli.js';\n\n/*** Resolve one command's project, desired environment, stored ownership and adapter dependencies. */\nexport async function prepareInfraCommandOperationAsync(\n request: InfraCommandRunRequest,\n services: InfraCommandServices,\n useStoredDesired = false,\n): Promise<PreparedInfraCommandOperation> {\n const project = await services.resolveProject({\n cwd: request.context.cwd,\n ...(request.arguments.projectId === undefined\n ? {}\n : { projectId: request.arguments.projectId }),\n });\n const environment = request.arguments.environment ?? 'local';\n const state = await services.readState(project.projectPath, environment);\n const currentDesired = environmentDesired(project.manifest.infra, environment);\n const desired = useStoredDesired && state !== null ? state.desired : currentDesired;\n if (desired === undefined) {\n throw new Error(`Infra environment \"${environment}\" is not configured.`);\n }\n const manifest = replaceEnvironment(project.manifest.infra, environment, desired);\n return {\n project,\n state,\n desired,\n operation: {\n projectId: project.projectId,\n manifest,\n ...(request.arguments.environment === undefined ? {} : { environment }),\n ...(state === null ? {} : { previous: state.ledger, previousDesired: state.desired }),\n },\n dependencies: services.createDependencies(request.context),\n };\n}\n\n/*** Select one exact environment specification from the canonical manifest. */\nfunction environmentDesired(\n manifest: InfraManifest,\n environment: AppEnvironmentId,\n): InfraEnvironmentSpec | undefined {\n if (environment === 'local') return manifest.environments.local;\n if (environment === 'preview') return manifest.environments.preview;\n return manifest.environments.production;\n}\n\n/*** Replace one environment while preserving the rest of the canonical manifest. */\nfunction replaceEnvironment(\n manifest: InfraManifest,\n environment: AppEnvironmentId,\n desired: InfraEnvironmentSpec,\n): InfraManifest {\n return {\n ...manifest,\n environments: { ...manifest.environments, [environment]: desired },\n };\n}\n"]}
1
+ {"version":3,"file":"prepareInfraCommandOperationAsync.js","sourceRoot":"","sources":["../../../src/cli/utils/prepareInfraCommandOperationAsync.ts"],"names":[],"mappings":"AASA,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,OAA+B,EAC/B,QAA8B,EAC9B,gBAAgB,GAAG,KAAK;IAExB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC;QAC5C,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG;QACxB,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,KAAK,SAAS;YAC3C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;KAChD,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,WAAW,IAAI,OAAO,CAAC;IAC7D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACzE,MAAM,cAAc,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,gBAAgB,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;IACpF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,sBAAsB,WAAW,sBAAsB,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAClF,OAAO;QACL,OAAO;QACP,KAAK;QACL,OAAO;QACP,SAAS,EAAE;YACT,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ;YACR,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;YACvE,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;SACtF;QACD,YAAY,EAAE,QAAQ,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE;YACzD,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,WAAW;SACZ,CAAC;KACH,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,SAAS,kBAAkB,CACzB,QAAuB,EACvB,WAA6B;IAE7B,IAAI,WAAW,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC;IAChE,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC;IACpE,OAAO,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC;AAC1C,CAAC;AAED,oFAAoF;AACpF,SAAS,kBAAkB,CACzB,QAAuB,EACvB,WAA6B,EAC7B,OAA6B;IAE7B,OAAO;QACL,GAAG,QAAQ;QACX,YAAY,EAAE,EAAE,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE;KACnE,CAAC;AACJ,CAAC","sourcesContent":["import type { AppEnvironmentId } from '@ankhorage/contracts/environments';\nimport type { InfraEnvironmentSpec, InfraManifest } from '@ankhorage/contracts/infra';\n\nimport type {\n InfraCommandRunRequest,\n InfraCommandServices,\n PreparedInfraCommandOperation,\n} from '../../types/infraCli.js';\n\n/*** Resolve one command's project, desired environment, stored ownership and adapter dependencies. */\nexport async function prepareInfraCommandOperationAsync(\n request: InfraCommandRunRequest,\n services: InfraCommandServices,\n useStoredDesired = false,\n): Promise<PreparedInfraCommandOperation> {\n const project = await services.resolveProject({\n cwd: request.context.cwd,\n ...(request.arguments.projectId === undefined\n ? {}\n : { projectId: request.arguments.projectId }),\n });\n const environment = request.arguments.environment ?? 'local';\n const state = await services.readState(project.projectPath, environment);\n const currentDesired = environmentDesired(project.manifest.infra, environment);\n const desired = useStoredDesired && state !== null ? state.desired : currentDesired;\n if (desired === undefined) {\n throw new Error(`Infra environment \"${environment}\" is not configured.`);\n }\n const manifest = replaceEnvironment(project.manifest.infra, environment, desired);\n return {\n project,\n state,\n desired,\n operation: {\n projectId: project.projectId,\n manifest,\n ...(request.arguments.environment === undefined ? {} : { environment }),\n ...(state === null ? {} : { previous: state.ledger, previousDesired: state.desired }),\n },\n dependencies: services.createDependencies(request.context, {\n projectPath: project.projectPath,\n environment,\n }),\n };\n}\n\n/*** Select one exact environment specification from the canonical manifest. */\nfunction environmentDesired(\n manifest: InfraManifest,\n environment: AppEnvironmentId,\n): InfraEnvironmentSpec | undefined {\n if (environment === 'local') return manifest.environments.local;\n if (environment === 'preview') return manifest.environments.preview;\n return manifest.environments.production;\n}\n\n/*** Replace one environment while preserving the rest of the canonical manifest. */\nfunction replaceEnvironment(\n manifest: InfraManifest,\n environment: AppEnvironmentId,\n desired: InfraEnvironmentSpec,\n): InfraManifest {\n return {\n ...manifest,\n environments: { ...manifest.environments, [environment]: desired },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"createEnvironmentInfraCredentialPort.d.ts","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAe,MAAM,4BAA4B,CAAC;AAKrF,sGAAsG;AACtG,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GACxD,qBAAqB,CAAC,aAAa,CAAC,CAiBtC"}
1
+ {"version":3,"file":"createEnvironmentInfraCredentialPort.d.ts","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qBAAqB,EAEtB,MAAM,4BAA4B,CAAC;AAKpC,sGAAsG;AACtG,wBAAgB,oCAAoC,CAClD,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GACxD,qBAAqB,CAAC,aAAa,CAAC,CA4BtC"}
@@ -3,23 +3,43 @@ import { normalizeInfraEnvironmentKey } from '../../utils/normalizeInfraEnvironm
3
3
  /*** Resolve execution-only control-plane credentials from exact-name or prefixed environment data. */
4
4
  export function createEnvironmentInfraCredentialPort(environment) {
5
5
  return {
6
+ findAsync(reference) {
7
+ return Promise.resolve(findCredential(environment, reference));
8
+ },
6
9
  resolveAsync(reference) {
7
- const prefixedName = `ANKH_INFRA_CREDENTIAL_${normalizeInfraEnvironmentKey(reference.name)}`;
8
- const rawValue = Reflect.get(environment, reference.name) ?? Reflect.get(environment, prefixedName);
9
- if (rawValue === undefined || rawValue.length === 0) {
10
- return Promise.resolve(createInfraFailure('infra-control-plane-credential-missing', `Control-plane credential ${reference.name} is unavailable. Set ${reference.name} or ${prefixedName}.`));
10
+ const found = findCredential(environment, reference);
11
+ if (!found.ok)
12
+ return Promise.resolve(found);
13
+ if (found.value !== null) {
14
+ return Promise.resolve({ ok: true, value: found.value, diagnostics: found.diagnostics });
11
15
  }
12
- return Promise.resolve(parseCredentialBundle(reference.name, rawValue));
16
+ const prefixedName = prefixedCredentialName(reference.name);
17
+ return Promise.resolve(createInfraFailure('infra-control-plane-credential-missing', `Control-plane credential ${reference.name} is unavailable. Set ${reference.name} or ${prefixedName}.`));
18
+ },
19
+ persistAsync(reference) {
20
+ return Promise.resolve(createInfraFailure('infra-control-plane-credential-persistence-unavailable', `Control-plane credential ${reference.name} cannot be persisted by the environment-only credential source.`));
13
21
  },
14
22
  };
15
23
  }
24
+ /*** Find and parse an optional credential bundle from the environment without treating absence as failure. */
25
+ function findCredential(environment, reference) {
26
+ const prefixedName = prefixedCredentialName(reference.name);
27
+ const rawValue = Reflect.get(environment, reference.name) ?? Reflect.get(environment, prefixedName);
28
+ if (rawValue === undefined || rawValue.length === 0) {
29
+ return { ok: true, value: null, diagnostics: [] };
30
+ }
31
+ return parseCredentialBundle(reference.name, rawValue);
32
+ }
33
+ /*** Build the canonical prefixed environment variable name for one credential reference. */
34
+ function prefixedCredentialName(name) {
35
+ return `ANKH_INFRA_CREDENTIAL_${normalizeInfraEnvironmentKey(name)}`;
36
+ }
16
37
  /*** Parse JSON credential bundles; token variables also support their conventional scalar form. */
17
38
  function parseCredentialBundle(name, rawValue) {
18
39
  try {
19
40
  const parsed = JSON.parse(rawValue);
20
- if (isRecord(parsed) && Object.values(parsed).every((value) => typeof value === 'string')) {
41
+ if (isStringRecord(parsed))
21
42
  return { ok: true, value: parsed, diagnostics: [] };
22
- }
23
43
  }
24
44
  catch {
25
45
  if (name.endsWith('_TOKEN')) {
@@ -28,8 +48,11 @@ function parseCredentialBundle(name, rawValue) {
28
48
  }
29
49
  return createInfraFailure('infra-control-plane-credential-invalid', `Control-plane credential ${name} must be a JSON object containing string fields.`);
30
50
  }
31
- /*** Narrow JSON credential bundles. */
32
- function isRecord(value) {
33
- return typeof value === 'object' && value !== null && !Array.isArray(value);
51
+ /*** Narrow credential bundle values to a string-only record. */
52
+ function isStringRecord(value) {
53
+ return (typeof value === 'object' &&
54
+ value !== null &&
55
+ !Array.isArray(value) &&
56
+ Object.values(value).every((entry) => typeof entry === 'string'));
34
57
  }
35
58
  //# sourceMappingURL=createEnvironmentInfraCredentialPort.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createEnvironmentInfraCredentialPort.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,6CAA6C,CAAC;AAE3F,sGAAsG;AACtG,MAAM,UAAU,oCAAoC,CAClD,WAAyD;IAEzD,OAAO;QACL,YAAY,CAAC,SAAS;YACpB,MAAM,YAAY,GAAG,yBAAyB,4BAA4B,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7F,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YACrF,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACpD,OAAO,OAAO,CAAC,OAAO,CACpB,kBAAkB,CAChB,wCAAwC,EACxC,4BAA4B,SAAS,CAAC,IAAI,wBAAwB,SAAS,CAAC,IAAI,OAAO,YAAY,GAAG,CACvG,CACF,CAAC;YACJ,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC;AACJ,CAAC;AAED,mGAAmG;AACnG,SAAS,qBAAqB,CAC5B,IAAY,EACZ,QAAgB;IAEhB,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;YAC1F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAA0C,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QAC1F,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACvF,CAAC;IACH,CAAC;IACD,OAAO,kBAAkB,CACvB,wCAAwC,EACxC,4BAA4B,IAAI,kDAAkD,CACnF,CAAC;AACJ,CAAC;AAED,uCAAuC;AACvC,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC","sourcesContent":["import type { InfraExecutionContext, InfraResult } from '@ankhorage/contracts/infra';\n\nimport { createInfraFailure } from '../../utils/createInfraFailure.js';\nimport { normalizeInfraEnvironmentKey } from '../../utils/normalizeInfraEnvironmentKey.js';\n\n/*** Resolve execution-only control-plane credentials from exact-name or prefixed environment data. */\nexport function createEnvironmentInfraCredentialPort(\n environment: Readonly<Record<string, string | undefined>>,\n): InfraExecutionContext['credentials'] {\n return {\n resolveAsync(reference) {\n const prefixedName = `ANKH_INFRA_CREDENTIAL_${normalizeInfraEnvironmentKey(reference.name)}`;\n const rawValue =\n Reflect.get(environment, reference.name) ?? Reflect.get(environment, prefixedName);\n if (rawValue === undefined || rawValue.length === 0) {\n return Promise.resolve(\n createInfraFailure(\n 'infra-control-plane-credential-missing',\n `Control-plane credential ${reference.name} is unavailable. Set ${reference.name} or ${prefixedName}.`,\n ),\n );\n }\n return Promise.resolve(parseCredentialBundle(reference.name, rawValue));\n },\n };\n}\n\n/*** Parse JSON credential bundles; token variables also support their conventional scalar form. */\nfunction parseCredentialBundle(\n name: string,\n rawValue: string,\n): InfraResult<Readonly<Record<string, string>>> {\n try {\n const parsed: unknown = JSON.parse(rawValue);\n if (isRecord(parsed) && Object.values(parsed).every((value) => typeof value === 'string')) {\n return { ok: true, value: parsed as Readonly<Record<string, string>>, diagnostics: [] };\n }\n } catch {\n if (name.endsWith('_TOKEN')) {\n return { ok: true, value: { token: rawValue, apiToken: rawValue }, diagnostics: [] };\n }\n }\n return createInfraFailure(\n 'infra-control-plane-credential-invalid',\n `Control-plane credential ${name} must be a JSON object containing string fields.`,\n );\n}\n\n/*** Narrow JSON credential bundles. */\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"]}
1
+ {"version":3,"file":"createEnvironmentInfraCredentialPort.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/createEnvironmentInfraCredentialPort.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n InfraControlPlaneCredentialRef,\n InfraExecutionContext,\n InfraResult,\n} from '@ankhorage/contracts/infra';\n\nimport { createInfraFailure } from '../../utils/createInfraFailure.js';\nimport { normalizeInfraEnvironmentKey } from '../../utils/normalizeInfraEnvironmentKey.js';\n\n/*** Resolve execution-only control-plane credentials from exact-name or prefixed environment data. */\nexport function createEnvironmentInfraCredentialPort(\n environment: Readonly<Record<string, string | undefined>>,\n): InfraExecutionContext['credentials'] {\n return {\n findAsync(reference) {\n return Promise.resolve(findCredential(environment, reference));\n },\n resolveAsync(reference) {\n const found = findCredential(environment, reference);\n if (!found.ok) return Promise.resolve(found);\n if (found.value !== null) {\n return Promise.resolve({ ok: true, value: found.value, diagnostics: found.diagnostics });\n }\n const prefixedName = prefixedCredentialName(reference.name);\n return Promise.resolve(\n createInfraFailure(\n 'infra-control-plane-credential-missing',\n `Control-plane credential ${reference.name} is unavailable. Set ${reference.name} or ${prefixedName}.`,\n ),\n );\n },\n persistAsync(reference) {\n return Promise.resolve(\n createInfraFailure(\n 'infra-control-plane-credential-persistence-unavailable',\n `Control-plane credential ${reference.name} cannot be persisted by the environment-only credential source.`,\n ),\n );\n },\n };\n}\n\n/*** Find and parse an optional credential bundle from the environment without treating absence as failure. */\nfunction findCredential(\n environment: Readonly<Record<string, string | undefined>>,\n reference: InfraControlPlaneCredentialRef,\n): InfraResult<Readonly<Record<string, string>> | null> {\n const prefixedName = prefixedCredentialName(reference.name);\n const rawValue =\n Reflect.get(environment, reference.name) ?? Reflect.get(environment, prefixedName);\n if (rawValue === undefined || rawValue.length === 0) {\n return { ok: true, value: null, diagnostics: [] };\n }\n return parseCredentialBundle(reference.name, rawValue);\n}\n\n/*** Build the canonical prefixed environment variable name for one credential reference. */\nfunction prefixedCredentialName(name: string): string {\n return `ANKH_INFRA_CREDENTIAL_${normalizeInfraEnvironmentKey(name)}`;\n}\n\n/*** Parse JSON credential bundles; token variables also support their conventional scalar form. */\nfunction parseCredentialBundle(\n name: string,\n rawValue: string,\n): InfraResult<Readonly<Record<string, string>>> {\n try {\n const parsed: unknown = JSON.parse(rawValue);\n if (isStringRecord(parsed)) return { ok: true, value: parsed, diagnostics: [] };\n } catch {\n if (name.endsWith('_TOKEN')) {\n return { ok: true, value: { token: rawValue, apiToken: rawValue }, diagnostics: [] };\n }\n }\n return createInfraFailure(\n 'infra-control-plane-credential-invalid',\n `Control-plane credential ${name} must be a JSON object containing string fields.`,\n );\n}\n\n/*** Narrow credential bundle values to a string-only record. */\nfunction isStringRecord(value: unknown): value is Readonly<Record<string, string>> {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every((entry) => typeof entry === 'string')\n );\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import type { AppEnvironmentId } from '@ankhorage/contracts/environments';
2
+ import type { InfraCredentialPort } from '@ankhorage/contracts/infra';
3
+ /*** Resolve explicit environment overrides before durable project-local bootstrap credentials. */
4
+ export declare function createProjectInfraCredentialPort(options: ProjectInfraCredentialPortOptions): InfraCredentialPort;
5
+ interface ProjectInfraCredentialPortOptions {
6
+ readonly projectPath: string;
7
+ readonly environment: AppEnvironmentId;
8
+ readonly processEnvironment: Readonly<Record<string, string | undefined>>;
9
+ }
10
+ export {};
11
+ //# sourceMappingURL=createProjectInfraCredentialPort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createProjectInfraCredentialPort.d.ts","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/createProjectInfraCredentialPort.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAEV,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAQpC,kGAAkG;AAClG,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,mBAAmB,CAsBrB;AAED,UAAU,iCAAiC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAC;IACvC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAC3E"}
@@ -0,0 +1,125 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { isRecord, isRecordOf } from '@ankhorage/utility/object';
5
+ import { createInfraFailure } from '../../utils/createInfraFailure.js';
6
+ import { normalizeInfraEnvironmentKey } from '../../utils/normalizeInfraEnvironmentKey.js';
7
+ import { resolveInfraEnvironmentStateDirectory } from '../../utils/resolveInfraEnvironmentStateDirectory.js';
8
+ import { createEnvironmentInfraCredentialPort } from './createEnvironmentInfraCredentialPort.js';
9
+ /*** Resolve explicit environment overrides before durable project-local bootstrap credentials. */
10
+ export function createProjectInfraCredentialPort(options) {
11
+ const environmentPort = createEnvironmentInfraCredentialPort(options.processEnvironment);
12
+ return {
13
+ findAsync: (reference) => findProjectCredentialAsync(options, environmentPort, reference),
14
+ async resolveAsync(reference) {
15
+ const found = await findProjectCredentialAsync(options, environmentPort, reference);
16
+ if (!found.ok)
17
+ return found;
18
+ if (found.value !== null) {
19
+ return { ok: true, value: found.value, diagnostics: found.diagnostics };
20
+ }
21
+ return missingCredential(reference.name);
22
+ },
23
+ async persistAsync(reference, values) {
24
+ if (!isStringRecord(values)) {
25
+ return createInfraFailure('infra-control-plane-credential-invalid', `Control-plane credential ${reference.name} must contain only string fields.`);
26
+ }
27
+ return writeStoredCredentialAsync(options, reference, values);
28
+ },
29
+ };
30
+ }
31
+ /*** Resolve environment precedence before falling through to project-local state. */
32
+ async function findProjectCredentialAsync(options, environmentPort, reference) {
33
+ const overridden = await environmentPort.findAsync(reference);
34
+ if (!overridden.ok || overridden.value !== null)
35
+ return overridden;
36
+ return readStoredCredentialAsync(options, reference);
37
+ }
38
+ /*** Read one exact credential bundle without enumerating or exposing sibling credentials. */
39
+ async function readStoredCredentialAsync(options, reference) {
40
+ const credentialPath = resolveCredentialPath(options, reference.name);
41
+ try {
42
+ const parsed = JSON.parse(await fs.readFile(credentialPath, 'utf8'));
43
+ if (!isStoredCredentialBundle(parsed) || parsed.name !== reference.name) {
44
+ return invalidCredentialStore(reference.name);
45
+ }
46
+ return { ok: true, value: parsed.values, diagnostics: [] };
47
+ }
48
+ catch (error) {
49
+ if (isMissingFile(error))
50
+ return { ok: true, value: null, diagnostics: [] };
51
+ if (error instanceof SyntaxError)
52
+ return invalidCredentialStore(reference.name);
53
+ return createInfraFailure('infra-control-plane-credential-store-read-failed', `Control-plane credential ${reference.name} could not be read from project state.`);
54
+ }
55
+ }
56
+ /*** Persist one opaque bundle atomically with restrictive local-host permissions. */
57
+ async function writeStoredCredentialAsync(options, reference, values) {
58
+ const credentialPath = resolveCredentialPath(options, reference.name);
59
+ const directory = path.dirname(credentialPath);
60
+ const temporaryPath = `${credentialPath}.${process.pid}.${randomUUID()}.tmp`;
61
+ const stored = { schemaVersion: 1, name: reference.name, values };
62
+ try {
63
+ await fs.mkdir(directory, { recursive: true, mode: 0o700 });
64
+ await restrictPermissionsAsync(directory, 0o700);
65
+ await fs.writeFile(temporaryPath, `${JSON.stringify(stored, null, 2)}\n`, {
66
+ encoding: 'utf8',
67
+ mode: 0o600,
68
+ flag: 'wx',
69
+ });
70
+ await fs.rename(temporaryPath, credentialPath);
71
+ await restrictPermissionsAsync(credentialPath, 0o600);
72
+ return { ok: true, value: null, diagnostics: [] };
73
+ }
74
+ catch {
75
+ await removeTemporaryCredentialAsync(temporaryPath);
76
+ return createInfraFailure('infra-control-plane-credential-store-write-failed', `Control-plane credential ${reference.name} could not be persisted to project state.`);
77
+ }
78
+ }
79
+ /*** Remove an abandoned unique temporary credential file without masking the original write failure. */
80
+ async function removeTemporaryCredentialAsync(temporaryPath) {
81
+ try {
82
+ await fs.rm(temporaryPath, { force: true });
83
+ }
84
+ catch {
85
+ return;
86
+ }
87
+ }
88
+ /*** Resolve one credential to an opaque hash-named file inside its project/environment scope. */
89
+ function resolveCredentialPath(options, name) {
90
+ const digest = createHash('sha256').update(name).digest('hex');
91
+ return path.join(resolveInfraEnvironmentStateDirectory(options.projectPath, options.environment), 'credentials', `${digest}.json`);
92
+ }
93
+ /*** Apply owner-only permissions where the host platform supports POSIX file modes. */
94
+ async function restrictPermissionsAsync(targetPath, mode) {
95
+ if (process.platform !== 'win32')
96
+ await fs.chmod(targetPath, mode);
97
+ }
98
+ /*** Create the canonical missing-credential diagnostic after every trusted source was checked. */
99
+ function missingCredential(name) {
100
+ const prefixedName = `ANKH_INFRA_CREDENTIAL_${normalizeInfraEnvironmentKey(name)}`;
101
+ return createInfraFailure('infra-control-plane-credential-missing', `Control-plane credential ${name} is unavailable. Set ${name} or ${prefixedName}.`);
102
+ }
103
+ /*** Reject malformed persisted state without exposing or replacing any stored value. */
104
+ function invalidCredentialStore(name) {
105
+ return createInfraFailure('infra-control-plane-credential-store-invalid', `Stored control-plane credential ${name} has an invalid project-state shape.`);
106
+ }
107
+ /*** Recognize the private stored credential record. */
108
+ function isStoredCredentialBundle(value) {
109
+ if (!isRecord(value))
110
+ return false;
111
+ return (value.schemaVersion === 1 && typeof value.name === 'string' && isStringRecord(value.values));
112
+ }
113
+ /*** Recognize string-only opaque provider credential bundles. */
114
+ function isStringRecord(value) {
115
+ return isRecordOf(value, isString);
116
+ }
117
+ /*** Narrow one unknown value to a string. */
118
+ function isString(value) {
119
+ return typeof value === 'string';
120
+ }
121
+ /*** Recognize only the filesystem's absent-file failure. */
122
+ function isMissingFile(error) {
123
+ return isRecord(error) && error.code === 'ENOENT';
124
+ }
125
+ //# sourceMappingURL=createProjectInfraCredentialPort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createProjectInfraCredentialPort.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/createProjectInfraCredentialPort.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\n\nimport type { AppEnvironmentId } from '@ankhorage/contracts/environments';\nimport type {\n InfraControlPlaneCredentialRef,\n InfraCredentialPort,\n InfraResult,\n} from '@ankhorage/contracts/infra';\nimport { isRecord, isRecordOf } from '@ankhorage/utility/object';\n\nimport { createInfraFailure } from '../../utils/createInfraFailure.js';\nimport { normalizeInfraEnvironmentKey } from '../../utils/normalizeInfraEnvironmentKey.js';\nimport { resolveInfraEnvironmentStateDirectory } from '../../utils/resolveInfraEnvironmentStateDirectory.js';\nimport { createEnvironmentInfraCredentialPort } from './createEnvironmentInfraCredentialPort.js';\n\n/*** Resolve explicit environment overrides before durable project-local bootstrap credentials. */\nexport function createProjectInfraCredentialPort(\n options: ProjectInfraCredentialPortOptions,\n): InfraCredentialPort {\n const environmentPort = createEnvironmentInfraCredentialPort(options.processEnvironment);\n return {\n findAsync: (reference) => findProjectCredentialAsync(options, environmentPort, reference),\n async resolveAsync(reference) {\n const found = await findProjectCredentialAsync(options, environmentPort, reference);\n if (!found.ok) return found;\n if (found.value !== null) {\n return { ok: true, value: found.value, diagnostics: found.diagnostics };\n }\n return missingCredential(reference.name);\n },\n async persistAsync(reference, values) {\n if (!isStringRecord(values)) {\n return createInfraFailure(\n 'infra-control-plane-credential-invalid',\n `Control-plane credential ${reference.name} must contain only string fields.`,\n );\n }\n return writeStoredCredentialAsync(options, reference, values);\n },\n };\n}\n\ninterface ProjectInfraCredentialPortOptions {\n readonly projectPath: string;\n readonly environment: AppEnvironmentId;\n readonly processEnvironment: Readonly<Record<string, string | undefined>>;\n}\n\ninterface StoredCredentialBundle {\n readonly schemaVersion: 1;\n readonly name: string;\n readonly values: Readonly<Record<string, string>>;\n}\n\n/*** Resolve environment precedence before falling through to project-local state. */\nasync function findProjectCredentialAsync(\n options: ProjectInfraCredentialPortOptions,\n environmentPort: InfraCredentialPort,\n reference: InfraControlPlaneCredentialRef,\n): Promise<InfraResult<Readonly<Record<string, string>> | null>> {\n const overridden = await environmentPort.findAsync(reference);\n if (!overridden.ok || overridden.value !== null) return overridden;\n return readStoredCredentialAsync(options, reference);\n}\n\n/*** Read one exact credential bundle without enumerating or exposing sibling credentials. */\nasync function readStoredCredentialAsync(\n options: ProjectInfraCredentialPortOptions,\n reference: InfraControlPlaneCredentialRef,\n): Promise<InfraResult<Readonly<Record<string, string>> | null>> {\n const credentialPath = resolveCredentialPath(options, reference.name);\n try {\n const parsed: unknown = JSON.parse(await fs.readFile(credentialPath, 'utf8'));\n if (!isStoredCredentialBundle(parsed) || parsed.name !== reference.name) {\n return invalidCredentialStore(reference.name);\n }\n return { ok: true, value: parsed.values, diagnostics: [] };\n } catch (error) {\n if (isMissingFile(error)) return { ok: true, value: null, diagnostics: [] };\n if (error instanceof SyntaxError) return invalidCredentialStore(reference.name);\n return createInfraFailure(\n 'infra-control-plane-credential-store-read-failed',\n `Control-plane credential ${reference.name} could not be read from project state.`,\n );\n }\n}\n\n/*** Persist one opaque bundle atomically with restrictive local-host permissions. */\nasync function writeStoredCredentialAsync(\n options: ProjectInfraCredentialPortOptions,\n reference: InfraControlPlaneCredentialRef,\n values: Readonly<Record<string, string>>,\n): Promise<InfraResult<null>> {\n const credentialPath = resolveCredentialPath(options, reference.name);\n const directory = path.dirname(credentialPath);\n const temporaryPath = `${credentialPath}.${process.pid}.${randomUUID()}.tmp`;\n const stored: StoredCredentialBundle = { schemaVersion: 1, name: reference.name, values };\n try {\n await fs.mkdir(directory, { recursive: true, mode: 0o700 });\n await restrictPermissionsAsync(directory, 0o700);\n await fs.writeFile(temporaryPath, `${JSON.stringify(stored, null, 2)}\\n`, {\n encoding: 'utf8',\n mode: 0o600,\n flag: 'wx',\n });\n await fs.rename(temporaryPath, credentialPath);\n await restrictPermissionsAsync(credentialPath, 0o600);\n return { ok: true, value: null, diagnostics: [] };\n } catch {\n await removeTemporaryCredentialAsync(temporaryPath);\n return createInfraFailure(\n 'infra-control-plane-credential-store-write-failed',\n `Control-plane credential ${reference.name} could not be persisted to project state.`,\n );\n }\n}\n\n/*** Remove an abandoned unique temporary credential file without masking the original write failure. */\nasync function removeTemporaryCredentialAsync(temporaryPath: string): Promise<void> {\n try {\n await fs.rm(temporaryPath, { force: true });\n } catch {\n return;\n }\n}\n\n/*** Resolve one credential to an opaque hash-named file inside its project/environment scope. */\nfunction resolveCredentialPath(options: ProjectInfraCredentialPortOptions, name: string): string {\n const digest = createHash('sha256').update(name).digest('hex');\n return path.join(\n resolveInfraEnvironmentStateDirectory(options.projectPath, options.environment),\n 'credentials',\n `${digest}.json`,\n );\n}\n\n/*** Apply owner-only permissions where the host platform supports POSIX file modes. */\nasync function restrictPermissionsAsync(targetPath: string, mode: number): Promise<void> {\n if (process.platform !== 'win32') await fs.chmod(targetPath, mode);\n}\n\n/*** Create the canonical missing-credential diagnostic after every trusted source was checked. */\nfunction missingCredential(name: string): InfraResult<never> {\n const prefixedName = `ANKH_INFRA_CREDENTIAL_${normalizeInfraEnvironmentKey(name)}`;\n return createInfraFailure(\n 'infra-control-plane-credential-missing',\n `Control-plane credential ${name} is unavailable. Set ${name} or ${prefixedName}.`,\n );\n}\n\n/*** Reject malformed persisted state without exposing or replacing any stored value. */\nfunction invalidCredentialStore(name: string): InfraResult<never> {\n return createInfraFailure(\n 'infra-control-plane-credential-store-invalid',\n `Stored control-plane credential ${name} has an invalid project-state shape.`,\n );\n}\n\n/*** Recognize the private stored credential record. */\nfunction isStoredCredentialBundle(value: unknown): value is StoredCredentialBundle {\n if (!isRecord(value)) return false;\n return (\n value.schemaVersion === 1 && typeof value.name === 'string' && isStringRecord(value.values)\n );\n}\n\n/*** Recognize string-only opaque provider credential bundles. */\nfunction isStringRecord(value: unknown): value is Readonly<Record<string, string>> {\n return isRecordOf(value, isString);\n}\n\n/*** Narrow one unknown value to a string. */\nfunction isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\n/*** Recognize only the filesystem's absent-file failure. */\nfunction isMissingFile(error: unknown): boolean {\n return isRecord(error) && error.code === 'ENOENT';\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { AppEnvironmentId } from '@ankhorage/contracts/environments';
2
+ /*** Remove only persisted generated credential state for one explicit project environment. */
3
+ export declare function removeStoredInfraCredentialsAsync(projectPath: string, environment: AppEnvironmentId): Promise<void>;
4
+ //# sourceMappingURL=removeStoredInfraCredentialsAsync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeStoredInfraCredentialsAsync.d.ts","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/removeStoredInfraCredentialsAsync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAI1E,8FAA8F;AAC9F,wBAAsB,iCAAiC,CACrD,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,gBAAgB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -0,0 +1,9 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { resolveInfraEnvironmentStateDirectory } from '../../utils/resolveInfraEnvironmentStateDirectory.js';
4
+ /*** Remove only persisted generated credential state for one explicit project environment. */
5
+ export async function removeStoredInfraCredentialsAsync(projectPath, environment) {
6
+ const credentialDirectory = path.join(resolveInfraEnvironmentStateDirectory(projectPath, environment), 'credentials');
7
+ await fs.rm(credentialDirectory, { recursive: true, force: true });
8
+ }
9
+ //# sourceMappingURL=removeStoredInfraCredentialsAsync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeStoredInfraCredentialsAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/adapters/outbound/removeStoredInfraCredentialsAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,EAAE,qCAAqC,EAAE,MAAM,sDAAsD,CAAC;AAE7G,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,WAAmB,EACnB,WAA6B;IAE7B,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CACnC,qCAAqC,CAAC,WAAW,EAAE,WAAW,CAAC,EAC/D,aAAa,CACd,CAAC;IACF,MAAM,EAAE,CAAC,EAAE,CAAC,mBAAmB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\n\nimport type { AppEnvironmentId } from '@ankhorage/contracts/environments';\n\nimport { resolveInfraEnvironmentStateDirectory } from '../../utils/resolveInfraEnvironmentStateDirectory.js';\n\n/*** Remove only persisted generated credential state for one explicit project environment. */\nexport async function removeStoredInfraCredentialsAsync(\n projectPath: string,\n environment: AppEnvironmentId,\n): Promise<void> {\n const credentialDirectory = path.join(\n resolveInfraEnvironmentStateDirectory(projectPath, environment),\n 'credentials',\n );\n await fs.rm(credentialDirectory, { recursive: true, force: true });\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { InfraExecutionContext, InfraResult, InfraServiceAdapter } from '@ankhorage/contracts/infra';
2
+ /*** Run optional mutating service preparation before runtime workload materialization. */
3
+ export declare function prepareInfraServicesAsync(context: InfraExecutionContext, services: readonly InfraServiceAdapter[]): Promise<InfraResult<null>>;
4
+ //# sourceMappingURL=prepareInfraServicesAsync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepareInfraServicesAsync.d.ts","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/prepareInfraServicesAsync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACpB,MAAM,4BAA4B,CAAC;AAIpC,0FAA0F;AAC1F,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,EAAE,SAAS,mBAAmB,EAAE,GACvC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAS5B"}
@@ -0,0 +1,15 @@
1
+ import { appendInfraFailure } from '../../utils/appendInfraFailure.js';
2
+ /*** Run optional mutating service preparation before runtime workload materialization. */
3
+ export async function prepareInfraServicesAsync(context, services) {
4
+ const diagnostics = [];
5
+ for (const service of services) {
6
+ if (service.prepareAsync === undefined)
7
+ continue;
8
+ const prepared = await service.prepareAsync(context);
9
+ if (!prepared.ok)
10
+ return appendInfraFailure(diagnostics, prepared);
11
+ diagnostics.push(...prepared.diagnostics);
12
+ }
13
+ return { ok: true, value: null, diagnostics };
14
+ }
15
+ //# sourceMappingURL=prepareInfraServicesAsync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepareInfraServicesAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/prepareInfraServicesAsync.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAEvE,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,OAA8B,EAC9B,QAAwC;IAExC,MAAM,WAAW,GAAsB,EAAE,CAAC;IAC1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;YAAE,SAAS;QACjD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACnE,WAAW,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAChD,CAAC","sourcesContent":["import type {\n InfraDiagnostic,\n InfraExecutionContext,\n InfraResult,\n InfraServiceAdapter,\n} from '@ankhorage/contracts/infra';\n\nimport { appendInfraFailure } from '../../utils/appendInfraFailure.js';\n\n/*** Run optional mutating service preparation before runtime workload materialization. */\nexport async function prepareInfraServicesAsync(\n context: InfraExecutionContext,\n services: readonly InfraServiceAdapter[],\n): Promise<InfraResult<null>> {\n const diagnostics: InfraDiagnostic[] = [];\n for (const service of services) {\n if (service.prepareAsync === undefined) continue;\n const prepared = await service.prepareAsync(context);\n if (!prepared.ok) return appendInfraFailure(diagnostics, prepared);\n diagnostics.push(...prepared.diagnostics);\n }\n return { ok: true, value: null, diagnostics };\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  import type { InfraOrchestrationDependencies, InfraUpOperationResult, InfraUpRequest } from '../../../../types/infraOrchestration.js';
2
- /*** Validate and reconcile compute, contributed workloads, runtime and services in dependency order. */
2
+ /*** Validate and reconcile compute, service preparation, workloads, runtime and services in order. */
3
3
  export declare function upInfraEnvironmentAsync(request: InfraUpRequest, dependencies: InfraOrchestrationDependencies): Promise<InfraUpOperationResult>;
4
4
  //# sourceMappingURL=upInfraEnvironmentAsync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"upInfraEnvironmentAsync.d.ts","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,8BAA8B,EAC9B,sBAAsB,EACtB,cAAc,EACf,MAAM,yCAAyC,CAAC;AAUjD,wGAAwG;AACxG,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,8BAA8B,GAC3C,OAAO,CAAC,sBAAsB,CAAC,CA0EjC"}
1
+ {"version":3,"file":"upInfraEnvironmentAsync.d.ts","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,8BAA8B,EAC9B,sBAAsB,EACtB,cAAc,EACf,MAAM,yCAAyC,CAAC;AAWjD,sGAAsG;AACtG,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,8BAA8B,GAC3C,OAAO,CAAC,sBAAsB,CAAC,CA6EjC"}
@@ -4,9 +4,10 @@ import { createInfraExecutionContext } from '../../utils/createInfraExecutionCon
4
4
  import { createInfraLedger } from '../../utils/createInfraLedger.js';
5
5
  import { mergeInfraOutputs } from '../../utils/mergeInfraOutputs.js';
6
6
  import { collectInfraWorkloadsAsync } from './collectInfraWorkloadsAsync.js';
7
+ import { prepareInfraServicesAsync } from './prepareInfraServicesAsync.js';
7
8
  import { resolveInfraAdaptersAsync } from './resolveInfraAdaptersAsync.js';
8
9
  import { validateInfraAdaptersAsync } from './validateInfraAdaptersAsync.js';
9
- /*** Validate and reconcile compute, contributed workloads, runtime and services in dependency order. */
10
+ /*** Validate and reconcile compute, service preparation, workloads, runtime and services in order. */
10
11
  export async function upInfraEnvironmentAsync(request, dependencies) {
11
12
  const environment = resolveInfraEnvironment({
12
13
  manifest: request.manifest,
@@ -25,14 +26,18 @@ export async function upInfraEnvironmentAsync(request, dependencies) {
25
26
  if (!validation.ok)
26
27
  return appendInfraFailure(diagnostics, validation);
27
28
  diagnostics.push(...validation.diagnostics);
28
- const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);
29
- if (!workloads.ok)
30
- return appendInfraFailure(diagnostics, workloads);
31
- diagnostics.push(...workloads.diagnostics);
32
29
  const compute = await adapters.value.compute.ensureAsync(context, environment.value.desired.deployment.compute);
33
30
  if (!compute.ok)
34
31
  return appendInfraFailure(diagnostics, compute);
35
32
  diagnostics.push(...compute.diagnostics);
33
+ const preparation = await prepareInfraServicesAsync(context, adapters.value.services);
34
+ if (!preparation.ok)
35
+ return appendInfraFailure(diagnostics, preparation);
36
+ diagnostics.push(...preparation.diagnostics);
37
+ const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);
38
+ if (!workloads.ok)
39
+ return appendInfraFailure(diagnostics, workloads);
40
+ diagnostics.push(...workloads.diagnostics);
36
41
  const runtimeDesired = {
37
42
  selection: environment.value.desired.deployment.runtime,
38
43
  targets: compute.value.targets,
@@ -1 +1 @@
1
- {"version":3,"file":"upInfraEnvironmentAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n InfraDiagnostic,\n InfraExecutionContext,\n InfraOutput,\n InfraOwnedResource,\n InfraResult,\n InfraServiceAdapter,\n} from '@ankhorage/contracts/infra';\n\nimport type {\n InfraOrchestrationDependencies,\n InfraUpOperationResult,\n InfraUpRequest,\n} from '../../../../types/infraOrchestration.js';\nimport { resolveInfraEnvironment } from '../../domain/resolveInfraEnvironment.js';\nimport { appendInfraFailure } from '../../utils/appendInfraFailure.js';\nimport { createInfraExecutionContext } from '../../utils/createInfraExecutionContext.js';\nimport { createInfraLedger } from '../../utils/createInfraLedger.js';\nimport { mergeInfraOutputs } from '../../utils/mergeInfraOutputs.js';\nimport { collectInfraWorkloadsAsync } from './collectInfraWorkloadsAsync.js';\nimport { resolveInfraAdaptersAsync } from './resolveInfraAdaptersAsync.js';\nimport { validateInfraAdaptersAsync } from './validateInfraAdaptersAsync.js';\n\n/*** Validate and reconcile compute, contributed workloads, runtime and services in dependency order. */\nexport async function upInfraEnvironmentAsync(\n request: InfraUpRequest,\n dependencies: InfraOrchestrationDependencies,\n): Promise<InfraUpOperationResult> {\n const environment = resolveInfraEnvironment({\n manifest: request.manifest,\n environment: request.environment,\n operation: 'up',\n });\n if (!environment.ok) return environment;\n const diagnostics: InfraDiagnostic[] = [...environment.diagnostics];\n const adapters = await resolveInfraAdaptersAsync(\n environment.value.desired,\n dependencies.adapterResolver,\n );\n if (!adapters.ok) return appendInfraFailure(diagnostics, adapters);\n diagnostics.push(...adapters.diagnostics);\n const context = createInfraExecutionContext(request, environment.value, dependencies);\n const validation = await validateInfraAdaptersAsync(context, adapters.value);\n if (!validation.ok) return appendInfraFailure(diagnostics, validation);\n diagnostics.push(...validation.diagnostics);\n const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);\n if (!workloads.ok) return appendInfraFailure(diagnostics, workloads);\n diagnostics.push(...workloads.diagnostics);\n const compute = await adapters.value.compute.ensureAsync(\n context,\n environment.value.desired.deployment.compute,\n );\n if (!compute.ok) return appendInfraFailure(diagnostics, compute);\n diagnostics.push(...compute.diagnostics);\n const runtimeDesired = {\n selection: environment.value.desired.deployment.runtime,\n targets: compute.value.targets,\n workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],\n availableOutputs: mergeInfraOutputs(request.previous?.outputs ?? [], compute.value.outputs),\n };\n const runtimeValidation = await adapters.value.runtime.validateAsync(context, runtimeDesired);\n if (!runtimeValidation.ok) return appendInfraFailure(diagnostics, runtimeValidation);\n diagnostics.push(...runtimeValidation.diagnostics);\n const runtime = await adapters.value.runtime.ensureAsync(context, runtimeDesired);\n if (!runtime.ok) return appendInfraFailure(diagnostics, runtime);\n diagnostics.push(...runtime.diagnostics);\n const services = await reconcileServicesAsync(context, adapters.value.services, [\n ...compute.value.outputs,\n ...runtime.value.outputs,\n ]);\n if (!services.ok) return appendInfraFailure(diagnostics, services);\n diagnostics.push(...services.diagnostics);\n const resources = [\n ...compute.value.resources,\n ...runtime.value.resources,\n ...services.value.resources,\n ];\n const outputs = mergeInfraOutputs(\n compute.value.outputs,\n runtime.value.outputs,\n services.value.outputs,\n );\n const ledger = createInfraLedger({\n projectId: request.projectId,\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n previous: request.previous,\n });\n return {\n ok: true,\n value: {\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n ledger,\n },\n diagnostics,\n };\n}\n\n/*** Reconcile service-owned external state after its runtime workloads expose outputs. */\nasync function reconcileServicesAsync(\n context: InfraExecutionContext,\n services: readonly InfraServiceAdapter[],\n runtimeOutputs: readonly InfraOutput[],\n): Promise<\n InfraResult<{\n readonly resources: readonly InfraOwnedResource[];\n readonly outputs: readonly InfraOutput[];\n }>\n> {\n const resources: InfraOwnedResource[] = [];\n const outputs: InfraOutput[] = [];\n const diagnostics: InfraDiagnostic[] = [];\n for (const service of services) {\n const result = await service.reconcileAsync(context, runtimeOutputs);\n if (!result.ok) return appendInfraFailure(diagnostics, result);\n resources.push(...result.value.resources);\n outputs.push(...result.value.outputs);\n diagnostics.push(...result.diagnostics);\n }\n return { ok: true, value: { resources, outputs }, diagnostics };\n}\n"]}
1
+ {"version":3,"file":"upInfraEnvironmentAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n InfraDiagnostic,\n InfraExecutionContext,\n InfraOutput,\n InfraOwnedResource,\n InfraResult,\n InfraServiceAdapter,\n} from '@ankhorage/contracts/infra';\n\nimport type {\n InfraOrchestrationDependencies,\n InfraUpOperationResult,\n InfraUpRequest,\n} from '../../../../types/infraOrchestration.js';\nimport { resolveInfraEnvironment } from '../../domain/resolveInfraEnvironment.js';\nimport { appendInfraFailure } from '../../utils/appendInfraFailure.js';\nimport { createInfraExecutionContext } from '../../utils/createInfraExecutionContext.js';\nimport { createInfraLedger } from '../../utils/createInfraLedger.js';\nimport { mergeInfraOutputs } from '../../utils/mergeInfraOutputs.js';\nimport { collectInfraWorkloadsAsync } from './collectInfraWorkloadsAsync.js';\nimport { prepareInfraServicesAsync } from './prepareInfraServicesAsync.js';\nimport { resolveInfraAdaptersAsync } from './resolveInfraAdaptersAsync.js';\nimport { validateInfraAdaptersAsync } from './validateInfraAdaptersAsync.js';\n\n/*** Validate and reconcile compute, service preparation, workloads, runtime and services in order. */\nexport async function upInfraEnvironmentAsync(\n request: InfraUpRequest,\n dependencies: InfraOrchestrationDependencies,\n): Promise<InfraUpOperationResult> {\n const environment = resolveInfraEnvironment({\n manifest: request.manifest,\n environment: request.environment,\n operation: 'up',\n });\n if (!environment.ok) return environment;\n const diagnostics: InfraDiagnostic[] = [...environment.diagnostics];\n const adapters = await resolveInfraAdaptersAsync(\n environment.value.desired,\n dependencies.adapterResolver,\n );\n if (!adapters.ok) return appendInfraFailure(diagnostics, adapters);\n diagnostics.push(...adapters.diagnostics);\n const context = createInfraExecutionContext(request, environment.value, dependencies);\n const validation = await validateInfraAdaptersAsync(context, adapters.value);\n if (!validation.ok) return appendInfraFailure(diagnostics, validation);\n diagnostics.push(...validation.diagnostics);\n const compute = await adapters.value.compute.ensureAsync(\n context,\n environment.value.desired.deployment.compute,\n );\n if (!compute.ok) return appendInfraFailure(diagnostics, compute);\n diagnostics.push(...compute.diagnostics);\n const preparation = await prepareInfraServicesAsync(context, adapters.value.services);\n if (!preparation.ok) return appendInfraFailure(diagnostics, preparation);\n diagnostics.push(...preparation.diagnostics);\n const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);\n if (!workloads.ok) return appendInfraFailure(diagnostics, workloads);\n diagnostics.push(...workloads.diagnostics);\n const runtimeDesired = {\n selection: environment.value.desired.deployment.runtime,\n targets: compute.value.targets,\n workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],\n availableOutputs: mergeInfraOutputs(request.previous?.outputs ?? [], compute.value.outputs),\n };\n const runtimeValidation = await adapters.value.runtime.validateAsync(context, runtimeDesired);\n if (!runtimeValidation.ok) return appendInfraFailure(diagnostics, runtimeValidation);\n diagnostics.push(...runtimeValidation.diagnostics);\n const runtime = await adapters.value.runtime.ensureAsync(context, runtimeDesired);\n if (!runtime.ok) return appendInfraFailure(diagnostics, runtime);\n diagnostics.push(...runtime.diagnostics);\n const services = await reconcileServicesAsync(context, adapters.value.services, [\n ...compute.value.outputs,\n ...runtime.value.outputs,\n ]);\n if (!services.ok) return appendInfraFailure(diagnostics, services);\n diagnostics.push(...services.diagnostics);\n const resources = [\n ...compute.value.resources,\n ...runtime.value.resources,\n ...services.value.resources,\n ];\n const outputs = mergeInfraOutputs(\n compute.value.outputs,\n runtime.value.outputs,\n services.value.outputs,\n );\n const ledger = createInfraLedger({\n projectId: request.projectId,\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n previous: request.previous,\n });\n return {\n ok: true,\n value: {\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n ledger,\n },\n diagnostics,\n };\n}\n\n/*** Reconcile service-owned external state after its runtime workloads expose outputs. */\nasync function reconcileServicesAsync(\n context: InfraExecutionContext,\n services: readonly InfraServiceAdapter[],\n runtimeOutputs: readonly InfraOutput[],\n): Promise<\n InfraResult<{\n readonly resources: readonly InfraOwnedResource[];\n readonly outputs: readonly InfraOutput[];\n }>\n> {\n const resources: InfraOwnedResource[] = [];\n const outputs: InfraOutput[] = [];\n const diagnostics: InfraDiagnostic[] = [];\n for (const service of services) {\n const result = await service.reconcileAsync(context, runtimeOutputs);\n if (!result.ok) return appendInfraFailure(diagnostics, result);\n resources.push(...result.value.resources);\n outputs.push(...result.value.outputs);\n diagnostics.push(...result.diagnostics);\n }\n return { ok: true, value: { resources, outputs }, diagnostics };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"createInfraCommandServices.d.ts","sourceRoot":"","sources":["../../../../src/features/environment-lifecycle/composition/createInfraCommandServices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAkBvE,mGAAmG;AACnG,wBAAgB,0BAA0B,CACxC,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,oBAAoB,CAyBtB"}
1
+ {"version":3,"file":"createInfraCommandServices.d.ts","sourceRoot":"","sources":["../../../../src/features/environment-lifecycle/composition/createInfraCommandServices.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAmBvE,mGAAmG;AACnG,wBAAgB,0BAA0B,CACxC,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,oBAAoB,CA8BtB"}
@@ -1,7 +1,8 @@
1
- import { createEnvironmentInfraCredentialPort } from '../adapters/outbound/createEnvironmentInfraCredentialPort.js';
2
1
  import { createEnvironmentInfraSecretPort } from '../adapters/outbound/createEnvironmentInfraSecretPort.js';
3
2
  import { createNodeInfraAdapterPackageResolver } from '../adapters/outbound/createNodeInfraAdapterPackageResolver.js';
3
+ import { createProjectInfraCredentialPort } from '../adapters/outbound/createProjectInfraCredentialPort.js';
4
4
  import { readStoredInfraStateAsync } from '../adapters/outbound/readStoredInfraStateAsync.js';
5
+ import { removeStoredInfraCredentialsAsync } from '../adapters/outbound/removeStoredInfraCredentialsAsync.js';
5
6
  import { removeStoredInfraStateAsync } from '../adapters/outbound/removeStoredInfraStateAsync.js';
6
7
  import { resolveInfraProjectAsync } from '../adapters/outbound/resolveInfraProjectAsync.js';
7
8
  import { writeInfraGeneratedArtifactsAsync } from '../adapters/outbound/writeInfraGeneratedArtifactsAsync.js';
@@ -21,6 +22,7 @@ export function createInfraCommandServices(overrides = {}) {
21
22
  readState: overrides.readState ?? readStoredInfraStateAsync,
22
23
  writeState: overrides.writeState ?? writeStoredInfraStateAsync,
23
24
  removeState: overrides.removeState ?? removeStoredInfraStateAsync,
25
+ removeCredentials: overrides.removeCredentials ?? removeStoredInfraCredentialsAsync,
24
26
  writeArtifacts: overrides.writeArtifacts ?? writeInfraGeneratedArtifactsAsync,
25
27
  operations: overrides.operations ?? {
26
28
  validate: validateInfraEnvironmentAsync,
@@ -33,9 +35,13 @@ export function createInfraCommandServices(overrides = {}) {
33
35
  destroy: destroyInfraEnvironmentAsync,
34
36
  },
35
37
  createDependencies: overrides.createDependencies ??
36
- ((context) => ({
38
+ ((context, scope) => ({
37
39
  adapterResolver: createNodeInfraAdapterPackageResolver(),
38
- credentials: createEnvironmentInfraCredentialPort(context.env),
40
+ credentials: createProjectInfraCredentialPort({
41
+ projectPath: scope.projectPath,
42
+ environment: scope.environment,
43
+ processEnvironment: context.env,
44
+ }),
39
45
  secrets: createEnvironmentInfraSecretPort(context.env),
40
46
  })),
41
47
  };