@fjall/deploy-core 0.89.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/aws/AwsProvider.d.ts +39 -0
  3. package/dist/src/aws/AwsProvider.js +1 -0
  4. package/dist/src/aws/SimpleAwsProvider.d.ts +22 -0
  5. package/dist/src/aws/SimpleAwsProvider.js +73 -0
  6. package/dist/src/aws/index.d.ts +4 -0
  7. package/dist/src/aws/index.js +3 -0
  8. package/dist/src/aws/organisations/accounts.d.ts +21 -0
  9. package/dist/src/aws/organisations/accounts.js +99 -0
  10. package/dist/src/aws/organisations/backup.d.ts +12 -0
  11. package/dist/src/aws/organisations/backup.js +28 -0
  12. package/dist/src/aws/organisations/costAllocation.d.ts +12 -0
  13. package/dist/src/aws/organisations/costAllocation.js +26 -0
  14. package/dist/src/aws/organisations/identityCentre.d.ts +8 -0
  15. package/dist/src/aws/organisations/identityCentre.js +19 -0
  16. package/dist/src/aws/organisations/index.d.ts +16 -0
  17. package/dist/src/aws/organisations/index.js +12 -0
  18. package/dist/src/aws/organisations/ipam.d.ts +7 -0
  19. package/dist/src/aws/organisations/ipam.js +18 -0
  20. package/dist/src/aws/organisations/organisation.d.ts +12 -0
  21. package/dist/src/aws/organisations/organisation.js +94 -0
  22. package/dist/src/aws/organisations/organisationalUnits.d.ts +19 -0
  23. package/dist/src/aws/organisations/organisationalUnits.js +125 -0
  24. package/dist/src/aws/organisations/policies.d.ts +7 -0
  25. package/dist/src/aws/organisations/policies.js +36 -0
  26. package/dist/src/aws/organisations/ram.d.ts +7 -0
  27. package/dist/src/aws/organisations/ram.js +15 -0
  28. package/dist/src/aws/organisations/serviceAccess.d.ts +7 -0
  29. package/dist/src/aws/organisations/serviceAccess.js +38 -0
  30. package/dist/src/aws/organisations/trustedAccess.d.ts +7 -0
  31. package/dist/src/aws/organisations/trustedAccess.js +15 -0
  32. package/dist/src/aws/organisations/types.d.ts +29 -0
  33. package/dist/src/aws/organisations/types.js +16 -0
  34. package/dist/src/aws/utils/CloudFormationFailureAnalyser.d.ts +32 -0
  35. package/dist/src/aws/utils/CloudFormationFailureAnalyser.js +228 -0
  36. package/dist/src/aws/utils/cloudformationEvents.d.ts +98 -0
  37. package/dist/src/aws/utils/cloudformationEvents.js +596 -0
  38. package/dist/src/aws/utils/errors.d.ts +26 -0
  39. package/dist/src/aws/utils/errors.js +59 -0
  40. package/dist/src/aws/utils/regions.d.ts +1 -0
  41. package/dist/src/aws/utils/regions.js +1 -0
  42. package/dist/src/aws/utils/stackStatus.d.ts +23 -0
  43. package/dist/src/aws/utils/stackStatus.js +90 -0
  44. package/dist/src/index.d.ts +35 -0
  45. package/dist/src/index.js +45 -0
  46. package/dist/src/orchestration/applicationDeploy.d.ts +11 -0
  47. package/dist/src/orchestration/applicationDeploy.js +327 -0
  48. package/dist/src/orchestration/contextHelpers.d.ts +9 -0
  49. package/dist/src/orchestration/contextHelpers.js +14 -0
  50. package/dist/src/orchestration/deploy.d.ts +10 -0
  51. package/dist/src/orchestration/deploy.js +42 -0
  52. package/dist/src/orchestration/detectionPipeline.d.ts +23 -0
  53. package/dist/src/orchestration/detectionPipeline.js +65 -0
  54. package/dist/src/orchestration/dockerInterface.d.ts +56 -0
  55. package/dist/src/orchestration/dockerInterface.js +1 -0
  56. package/dist/src/orchestration/domainInterface.d.ts +37 -0
  57. package/dist/src/orchestration/domainInterface.js +1 -0
  58. package/dist/src/orchestration/index.d.ts +8 -0
  59. package/dist/src/orchestration/index.js +3 -0
  60. package/dist/src/orchestration/organisationDeploy.d.ts +16 -0
  61. package/dist/src/orchestration/organisationDeploy.js +382 -0
  62. package/dist/src/orchestration/organisationSetup.d.ts +42 -0
  63. package/dist/src/orchestration/organisationSetup.js +227 -0
  64. package/dist/src/orchestration/resolveOperation.d.ts +10 -0
  65. package/dist/src/orchestration/resolveOperation.js +53 -0
  66. package/dist/src/orchestration/serviceFactory.d.ts +15 -0
  67. package/dist/src/orchestration/serviceFactory.js +16 -0
  68. package/dist/src/services/application/ApplicationStackService.d.ts +93 -0
  69. package/dist/src/services/application/ApplicationStackService.js +436 -0
  70. package/dist/src/services/application/index.d.ts +1 -0
  71. package/dist/src/services/application/index.js +1 -0
  72. package/dist/src/services/infrastructure/CdkArgumentBuilder.d.ts +12 -0
  73. package/dist/src/services/infrastructure/CdkArgumentBuilder.js +67 -0
  74. package/dist/src/services/infrastructure/CdkCommandRunner.d.ts +30 -0
  75. package/dist/src/services/infrastructure/CdkCommandRunner.js +241 -0
  76. package/dist/src/services/infrastructure/CdkErrorFormatter.d.ts +4 -0
  77. package/dist/src/services/infrastructure/CdkErrorFormatter.js +194 -0
  78. package/dist/src/services/infrastructure/CdkEventMonitoring.d.ts +19 -0
  79. package/dist/src/services/infrastructure/CdkEventMonitoring.js +41 -0
  80. package/dist/src/services/infrastructure/CdkOutputAnalyser.d.ts +43 -0
  81. package/dist/src/services/infrastructure/CdkOutputAnalyser.js +125 -0
  82. package/dist/src/services/infrastructure/CdkOutputParser.d.ts +8 -0
  83. package/dist/src/services/infrastructure/CdkOutputParser.js +33 -0
  84. package/dist/src/services/infrastructure/CdkProcessManager.d.ts +20 -0
  85. package/dist/src/services/infrastructure/CdkProcessManager.js +244 -0
  86. package/dist/src/services/infrastructure/CdkService.d.ts +71 -0
  87. package/dist/src/services/infrastructure/CdkService.js +254 -0
  88. package/dist/src/services/infrastructure/CloudFormationService.d.ts +79 -0
  89. package/dist/src/services/infrastructure/CloudFormationService.js +249 -0
  90. package/dist/src/services/infrastructure/index.d.ts +8 -0
  91. package/dist/src/services/infrastructure/index.js +7 -0
  92. package/dist/src/services/supporting/CdkContextBuilder.d.ts +49 -0
  93. package/dist/src/services/supporting/CdkContextBuilder.js +44 -0
  94. package/dist/src/services/supporting/TemplateHashService.d.ts +67 -0
  95. package/dist/src/services/supporting/TemplateHashService.js +152 -0
  96. package/dist/src/services/supporting/helpers.d.ts +46 -0
  97. package/dist/src/services/supporting/helpers.js +81 -0
  98. package/dist/src/services/supporting/index.d.ts +3 -0
  99. package/dist/src/services/supporting/index.js +3 -0
  100. package/dist/src/types/FjallState.d.ts +50 -0
  101. package/dist/src/types/FjallState.js +118 -0
  102. package/dist/src/types/ProgressEvent.d.ts +35 -0
  103. package/dist/src/types/ProgressEvent.js +48 -0
  104. package/dist/src/types/apiClient.d.ts +34 -0
  105. package/dist/src/types/apiClient.js +1 -0
  106. package/dist/src/types/application/ApplicationServiceTypes.d.ts +56 -0
  107. package/dist/src/types/application/ApplicationServiceTypes.js +30 -0
  108. package/dist/src/types/application/index.d.ts +1 -0
  109. package/dist/src/types/application/index.js +1 -0
  110. package/dist/src/types/callbacks.d.ts +36 -0
  111. package/dist/src/types/callbacks.js +1 -0
  112. package/dist/src/types/constants.d.ts +6 -0
  113. package/dist/src/types/constants.js +6 -0
  114. package/dist/src/types/credentials.d.ts +30 -0
  115. package/dist/src/types/credentials.js +1 -0
  116. package/dist/src/types/deployment/DeploymentServiceTypes.d.ts +23 -0
  117. package/dist/src/types/deployment/DeploymentServiceTypes.js +1 -0
  118. package/dist/src/types/deployment/DeploymentTypes.d.ts +29 -0
  119. package/dist/src/types/deployment/DeploymentTypes.js +1 -0
  120. package/dist/src/types/deployment/cloudformation.d.ts +14 -0
  121. package/dist/src/types/deployment/cloudformation.js +1 -0
  122. package/dist/src/types/deployment/index.d.ts +5 -0
  123. package/dist/src/types/deployment/index.js +1 -0
  124. package/dist/src/types/deployment/parallel.d.ts +46 -0
  125. package/dist/src/types/deployment/parallel.js +10 -0
  126. package/dist/src/types/errors/CdkError.d.ts +14 -0
  127. package/dist/src/types/errors/CdkError.js +20 -0
  128. package/dist/src/types/errors/ServiceError.d.ts +86 -0
  129. package/dist/src/types/errors/ServiceError.js +119 -0
  130. package/dist/src/types/events.d.ts +40 -0
  131. package/dist/src/types/events.js +5 -0
  132. package/dist/src/types/index.d.ts +20 -0
  133. package/dist/src/types/index.js +9 -0
  134. package/dist/src/types/operations.d.ts +193 -0
  135. package/dist/src/types/operations.js +285 -0
  136. package/dist/src/types/orgConfig.d.ts +28 -0
  137. package/dist/src/types/orgConfig.js +11 -0
  138. package/dist/src/types/params.d.ts +74 -0
  139. package/dist/src/types/params.js +1 -0
  140. package/dist/src/types/patternDetection.d.ts +43 -0
  141. package/dist/src/types/patternDetection.js +92 -0
  142. package/dist/src/types/validation.d.ts +12 -0
  143. package/dist/src/types/validation.js +1 -0
  144. package/dist/src/util/fsHelpers.d.ts +4 -0
  145. package/dist/src/util/fsHelpers.js +16 -0
  146. package/dist/src/util/index.d.ts +3 -0
  147. package/dist/src/util/index.js +3 -0
  148. package/dist/src/util/securityHelpers.d.ts +31 -0
  149. package/dist/src/util/securityHelpers.js +124 -0
  150. package/dist/src/util/singleton.d.ts +2 -0
  151. package/dist/src/util/singleton.js +9 -0
  152. package/dist/src/util/sleep.d.ts +4 -0
  153. package/dist/src/util/sleep.js +4 -0
  154. package/package.json +42 -0
@@ -0,0 +1,285 @@
1
+ import { isOpenNextPattern } from "./patternDetection.js";
2
+ import { toPascalCase } from "@fjall/util";
3
+ /**
4
+ * Application infrastructure stacks
5
+ */
6
+ export const APPLICATION_STACKS = {
7
+ NETWORK: "Network",
8
+ DATABASE: "Database",
9
+ STORAGE: "Storage",
10
+ COMPUTE: "Compute",
11
+ CDN: "Cdn",
12
+ MESSAGING: "Messaging"
13
+ };
14
+ /**
15
+ * Organisation infrastructure types
16
+ * Note: These are deployment types, not stacks - each maps to a single CDK stack
17
+ */
18
+ export const ORGANISATION_TYPES = {
19
+ ORGANISATION: "organisation",
20
+ PLATFORM: "platform",
21
+ ACCOUNT: "account"
22
+ };
23
+ /**
24
+ * Type guards for safe type narrowing
25
+ */
26
+ export function isApplicationOperation(op) {
27
+ return op.kind === "application";
28
+ }
29
+ export function isOrganisationOperation(op) {
30
+ return op.kind === "organisation";
31
+ }
32
+ /**
33
+ * Stack ordering for application deployments
34
+ */
35
+ export const APPLICATION_DEPLOY_ORDER = [
36
+ APPLICATION_STACKS.NETWORK,
37
+ APPLICATION_STACKS.DATABASE,
38
+ APPLICATION_STACKS.COMPUTE
39
+ ];
40
+ export const APPLICATION_DESTROY_ORDER = [
41
+ APPLICATION_STACKS.COMPUTE,
42
+ APPLICATION_STACKS.DATABASE,
43
+ APPLICATION_STACKS.NETWORK
44
+ ];
45
+ /**
46
+ * Stack ordering for OpenNext (Next.js/Payload) deployments
47
+ * These patterns require additional infrastructure: S3, DynamoDB, SQS, CloudFront
48
+ */
49
+ export const OPENNEXT_DEPLOY_ORDER = [
50
+ APPLICATION_STACKS.NETWORK,
51
+ APPLICATION_STACKS.STORAGE,
52
+ APPLICATION_STACKS.MESSAGING,
53
+ APPLICATION_STACKS.DATABASE,
54
+ APPLICATION_STACKS.COMPUTE,
55
+ APPLICATION_STACKS.CDN
56
+ ];
57
+ /**
58
+ * Stack ordering for OpenNext destroy operations (reverse of deploy order)
59
+ * CDN must be destroyed first as it depends on Compute, then work backwards
60
+ */
61
+ export const OPENNEXT_DESTROY_ORDER = [
62
+ APPLICATION_STACKS.CDN,
63
+ APPLICATION_STACKS.COMPUTE,
64
+ APPLICATION_STACKS.DATABASE,
65
+ APPLICATION_STACKS.MESSAGING,
66
+ APPLICATION_STACKS.STORAGE,
67
+ APPLICATION_STACKS.NETWORK
68
+ ];
69
+ /**
70
+ * Parallel deployment groups for concurrent stack deployment
71
+ * Stacks within each phase can be deployed in parallel.
72
+ *
73
+ * Dependency structure:
74
+ * - Phase 1: Network (required by all other stacks)
75
+ * - Phase 2: Storage, Messaging, Database (independent of each other, only need Network)
76
+ * - Phase 3: Compute (needs Database outputs)
77
+ * - Phase 4: CDN (needs Compute outputs)
78
+ */
79
+ export const PARALLEL_DEPLOY_GROUPS = {
80
+ PHASE_1: {
81
+ phase: 1,
82
+ stacks: [APPLICATION_STACKS.NETWORK],
83
+ description: "Network infrastructure"
84
+ },
85
+ PHASE_2: {
86
+ phase: 2,
87
+ stacks: [
88
+ APPLICATION_STACKS.STORAGE,
89
+ APPLICATION_STACKS.MESSAGING,
90
+ APPLICATION_STACKS.DATABASE
91
+ ],
92
+ description: "Storage and database resources (parallel)"
93
+ },
94
+ PHASE_3: {
95
+ phase: 3,
96
+ stacks: [APPLICATION_STACKS.COMPUTE],
97
+ description: "Compute resources"
98
+ },
99
+ PHASE_4: {
100
+ phase: 4,
101
+ stacks: [APPLICATION_STACKS.CDN],
102
+ description: "CDN distribution"
103
+ }
104
+ };
105
+ /**
106
+ * Parallel deployment groups for OpenNext (Next.js/Payload) deployments
107
+ * Optimised to run BUILD in parallel with infrastructure stacks.
108
+ */
109
+ export const OPENNEXT_PARALLEL_GROUPS = {
110
+ /** Regular Next.js: BUILD + all Phase 2 stacks in parallel */
111
+ NEXTJS_PARALLEL: {
112
+ stacks: [
113
+ APPLICATION_STACKS.STORAGE,
114
+ APPLICATION_STACKS.MESSAGING,
115
+ APPLICATION_STACKS.DATABASE
116
+ ],
117
+ includeBuild: true,
118
+ description: "Build + Storage/Messaging/Database (parallel)"
119
+ },
120
+ /** Payload: BUILD + remaining stacks (after Database + migrations) */
121
+ PAYLOAD_PARALLEL: {
122
+ stacks: [APPLICATION_STACKS.STORAGE, APPLICATION_STACKS.MESSAGING],
123
+ includeBuild: true,
124
+ description: "Build + Storage/Messaging (parallel)"
125
+ }
126
+ };
127
+ /**
128
+ * Get all parallel deploy groups as an ordered array
129
+ */
130
+ export function getParallelDeployGroups() {
131
+ return [
132
+ PARALLEL_DEPLOY_GROUPS.PHASE_1,
133
+ PARALLEL_DEPLOY_GROUPS.PHASE_2,
134
+ PARALLEL_DEPLOY_GROUPS.PHASE_3,
135
+ PARALLEL_DEPLOY_GROUPS.PHASE_4
136
+ ];
137
+ }
138
+ /**
139
+ * Parallel destroy groups for OpenNext destroy operations.
140
+ * Reverse of deploy order to respect dependencies.
141
+ */
142
+ export const PARALLEL_DESTROY_GROUPS = {
143
+ PHASE_1: {
144
+ phase: 1,
145
+ stacks: [APPLICATION_STACKS.CDN],
146
+ description: "CDN distribution"
147
+ },
148
+ PHASE_2: {
149
+ phase: 2,
150
+ stacks: [APPLICATION_STACKS.COMPUTE],
151
+ description: "Compute resources"
152
+ },
153
+ PHASE_3: {
154
+ phase: 3,
155
+ stacks: [
156
+ APPLICATION_STACKS.DATABASE,
157
+ APPLICATION_STACKS.MESSAGING,
158
+ APPLICATION_STACKS.STORAGE
159
+ ],
160
+ description: "Database, messaging, and storage (parallel)"
161
+ },
162
+ PHASE_4: {
163
+ phase: 4,
164
+ stacks: [APPLICATION_STACKS.NETWORK],
165
+ description: "Network infrastructure"
166
+ }
167
+ };
168
+ /**
169
+ * Get all parallel destroy groups as an ordered array
170
+ */
171
+ export function getParallelDestroyGroups() {
172
+ return [
173
+ PARALLEL_DESTROY_GROUPS.PHASE_1,
174
+ PARALLEL_DESTROY_GROUPS.PHASE_2,
175
+ PARALLEL_DESTROY_GROUPS.PHASE_3,
176
+ PARALLEL_DESTROY_GROUPS.PHASE_4
177
+ ];
178
+ }
179
+ /**
180
+ * Deploy tier priority — lower number deploys first, higher destroys first.
181
+ * Used for dynamic ordering based on manifest-detected resources.
182
+ */
183
+ const STACK_DEPLOY_TIER = {
184
+ Network: 1,
185
+ Storage: 2,
186
+ Messaging: 2,
187
+ Database: 2,
188
+ Compute: 3,
189
+ Cdn: 4
190
+ };
191
+ /**
192
+ * Get deployment order based on application configuration.
193
+ *
194
+ * Strategies:
195
+ * 1. OpenNext (pattern = "payload" or "nextjs"): Predefined order (build orchestration)
196
+ * 2. Dynamic: Include only detected stacks, ordered by tier
197
+ * 3. Fallback: Standard order (no manifest available)
198
+ */
199
+ export function getApplicationDeployOrder(options) {
200
+ const { pattern, resources } = options ?? {};
201
+ if (isOpenNextPattern(pattern)) {
202
+ return OPENNEXT_DEPLOY_ORDER;
203
+ }
204
+ if (resources) {
205
+ return buildOrderFromResources(resources, "asc");
206
+ }
207
+ return APPLICATION_DEPLOY_ORDER;
208
+ }
209
+ /**
210
+ * Get destroy order based on application configuration.
211
+ * Destroy order respects dependencies (reverse of deploy order).
212
+ */
213
+ export function getApplicationDestroyOrder(options) {
214
+ const { pattern, resources } = options ?? {};
215
+ if (isOpenNextPattern(pattern)) {
216
+ return OPENNEXT_DESTROY_ORDER;
217
+ }
218
+ if (resources) {
219
+ return buildOrderFromResources(resources, "desc");
220
+ }
221
+ return APPLICATION_DESTROY_ORDER;
222
+ }
223
+ /**
224
+ * Build a stack order from resource flags, sorted by tier priority.
225
+ */
226
+ function buildOrderFromResources(resources, direction) {
227
+ const stacks = [];
228
+ if (resources.hasNetwork)
229
+ stacks.push(APPLICATION_STACKS.NETWORK);
230
+ if (resources.hasStorage)
231
+ stacks.push(APPLICATION_STACKS.STORAGE);
232
+ if (resources.hasMessaging)
233
+ stacks.push(APPLICATION_STACKS.MESSAGING);
234
+ if (resources.hasDatabase)
235
+ stacks.push(APPLICATION_STACKS.DATABASE);
236
+ if (resources.hasCompute)
237
+ stacks.push(APPLICATION_STACKS.COMPUTE);
238
+ if (resources.hasCdn)
239
+ stacks.push(APPLICATION_STACKS.CDN);
240
+ return stacks.sort((a, b) => {
241
+ const diff = STACK_DEPLOY_TIER[a] - STACK_DEPLOY_TIER[b];
242
+ return direction === "asc" ? diff : -diff;
243
+ });
244
+ }
245
+ /**
246
+ * Helper functions for stack operations
247
+ */
248
+ export { toPascalCase };
249
+ export function getApplicationStackName(appName, stack) {
250
+ return `${toPascalCase(appName)}${stack}`;
251
+ }
252
+ export function getOrganisationStackName(type) {
253
+ switch (type) {
254
+ case "organisation":
255
+ return "Organisation";
256
+ case "platform":
257
+ return "Platform";
258
+ case "account":
259
+ return "Account";
260
+ default: {
261
+ const _exhaustive = type;
262
+ throw new Error(`Unsupported organisation type: ${String(_exhaustive)}`);
263
+ }
264
+ }
265
+ }
266
+ /**
267
+ * Type guard for ApplicationStack
268
+ */
269
+ export function isApplicationStack(value) {
270
+ return Object.values(APPLICATION_STACKS).includes(value);
271
+ }
272
+ /**
273
+ * Step name generators for UI display
274
+ */
275
+ export function getApplicationStepName(stack, action) {
276
+ const verb = action === "deploy" ? "Deploying" : "Destroying";
277
+ return `${verb} ${stack.toLowerCase()} infrastructure`;
278
+ }
279
+ /**
280
+ * Step ID generators for tracking
281
+ */
282
+ export function getApplicationStepId(stack, action) {
283
+ const suffix = action === "destroy" ? "-destroy" : "";
284
+ return `${stack.toLowerCase()}${suffix}`;
285
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Organisation-level configuration.
3
+ *
4
+ * This config is injected by the caller, not read from disk:
5
+ * - CLI: fetches from GET /api/organisation-config (cached locally with TTL)
6
+ * - Worker: reads from DB (Organization + ConnectedAwsAccount models)
7
+ *
8
+ * Passed to CDK via -c orgConfig=<json> context at synthesis time.
9
+ * See: investigations/2026-03-16-config-split-investigation.md
10
+ */
11
+ export interface OrgConfig {
12
+ providerAccounts: ProviderAccount[];
13
+ primaryRegion?: string;
14
+ secondaryRegions?: string[];
15
+ disasterRecoveryRegion?: string;
16
+ rootOidcRoleArn?: string;
17
+ ssoSessions?: Record<string, SSOSession>;
18
+ }
19
+ export interface ProviderAccount {
20
+ id: string;
21
+ name: string;
22
+ environment: string;
23
+ managed?: boolean;
24
+ }
25
+ export interface SSOSession {
26
+ ssoRegion: string;
27
+ ssoStartUrl: string;
28
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Organisation-level configuration.
3
+ *
4
+ * This config is injected by the caller, not read from disk:
5
+ * - CLI: fetches from GET /api/organisation-config (cached locally with TTL)
6
+ * - Worker: reads from DB (Organization + ConnectedAwsAccount models)
7
+ *
8
+ * Passed to CDK via -c orgConfig=<json> context at synthesis time.
9
+ * See: investigations/2026-03-16-config-split-investigation.md
10
+ */
11
+ export {};
@@ -0,0 +1,74 @@
1
+ import type { Result } from "@fjall/generator";
2
+ import type { AwsCredentials, DeployIdentity } from "./credentials.js";
3
+ import type { DeployCallbacks } from "./callbacks.js";
4
+ import type { ApiClientInterface } from "./apiClient.js";
5
+ import type { OrgConfig } from "./orgConfig.js";
6
+ import type { DockerProvider } from "../orchestration/dockerInterface.js";
7
+ import type { DomainDeployProvider } from "../orchestration/domainInterface.js";
8
+ export interface DeployParams {
9
+ /** Deployment target name (e.g., "my-app", "organisation", "platform", "account-prod") */
10
+ target: string;
11
+ /** Absolute path to the repository root containing fjall-config.json */
12
+ workingDirectory: string;
13
+ /** AWS credentials for the deployment. deploy-core never resolves these itself. */
14
+ awsCredentials: AwsCredentials;
15
+ /** Typed callbacks for progress events. CLI and worker implement differently. */
16
+ callbacks: DeployCallbacks;
17
+ /** Deployment options */
18
+ options?: DeployOptions;
19
+ /**
20
+ * Org-level config (accounts, regions, OIDC).
21
+ * CLI: fetches from GET /api/organisation-config (cached locally with TTL).
22
+ * Worker: reads from DB (Organization + ConnectedAwsAccount models).
23
+ * Passed to CDK via -c orgConfig=<json> context.
24
+ * See: investigations/2026-03-16-config-split-investigation.md
25
+ */
26
+ orgConfig?: OrgConfig;
27
+ /**
28
+ * Pre-fetched identity for org deployments.
29
+ * CLI: omit this, provide apiClient instead (fetches from API).
30
+ * Worker: provide this from DB, omit apiClient.
31
+ */
32
+ identity?: DeployIdentity;
33
+ /**
34
+ * Optional API client for non-critical operations (app registration,
35
+ * account verification, config push). Worker omits this — those
36
+ * operations are handled by the webapp directly.
37
+ */
38
+ apiClient?: ApiClientInterface;
39
+ /**
40
+ * Optional Docker provider for building and pushing container images.
41
+ * CLI and worker provide their own implementations.
42
+ * If omitted, Docker operations are skipped.
43
+ */
44
+ dockerProvider?: DockerProvider;
45
+ /**
46
+ * Optional domain deployment provider for organisation cascade.
47
+ * CLI provides an implementation backed by DomainService + zone files.
48
+ * Worker omits this (domains managed via CLI only for now).
49
+ * If omitted, the domains cascade phase is skipped.
50
+ */
51
+ domainProvider?: DomainDeployProvider;
52
+ }
53
+ export interface DeployOptions {
54
+ skipConfirmation?: boolean;
55
+ force?: boolean;
56
+ cascade?: boolean;
57
+ skipBuild?: boolean;
58
+ verbose?: boolean;
59
+ infraOnly?: boolean;
60
+ deployOnly?: boolean;
61
+ passThroughCDK?: boolean;
62
+ environment?: string;
63
+ }
64
+ export type DeploymentType = "application" | "organisation";
65
+ export interface DeployResult {
66
+ target: string;
67
+ deploymentType: DeploymentType;
68
+ /** Stack outputs (website URL, OIDC role ARN, etc.) */
69
+ outputs?: Record<string, string>;
70
+ /** Duration in milliseconds */
71
+ durationMs?: number;
72
+ }
73
+ /** Re-export Result from generator for consumers. */
74
+ export type { Result };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Pattern detection types and functions.
3
+ *
4
+ * Contains both pure predicates used by operations.ts and
5
+ * filesystem-based detection functions used by orchestration services.
6
+ */
7
+ import type { PatternType } from "@fjall/generator";
8
+ declare const OPENNEXT_PATTERNS_ARRAY: readonly ["payload", "nextjs"];
9
+ export type OpenNextPattern = (typeof OPENNEXT_PATTERNS_ARRAY)[number];
10
+ export declare const OPENNEXT_PATTERNS: Set<string>;
11
+ export declare function isOpenNextPattern(pattern: string | undefined | null): pattern is OpenNextPattern;
12
+ export interface AppResourceFlags {
13
+ hasNetwork: boolean;
14
+ hasCompute: boolean;
15
+ hasDatabase: boolean;
16
+ hasStorage: boolean;
17
+ hasMessaging: boolean;
18
+ hasCdn: boolean;
19
+ }
20
+ /** Derive resource flags from manifest stack names (authoritative, post-synth) */
21
+ export declare function deriveResourcesFromManifestStacks(stackNames: string[]): AppResourceFlags;
22
+ /**
23
+ * Detect the application pattern (Payload, Next.js, or none) from infrastructure.ts.
24
+ *
25
+ * Pattern detection is based on the IaC file (infrastructure.ts), NOT on
26
+ * project files like package.json. This ensures accurate detection even
27
+ * when multiple apps coexist in the same project directory.
28
+ *
29
+ * @param appPath - The fjall app path (e.g., "fjall/app8" or absolute path)
30
+ */
31
+ export declare function detectPattern(appPath: string): {
32
+ pattern: PatternType | null;
33
+ hasDatabase: boolean;
34
+ };
35
+ /**
36
+ * Detect if infrastructure.ts contains a Payload CMS pattern.
37
+ */
38
+ export declare function detectPayloadPattern(appPath: string): boolean;
39
+ /**
40
+ * Detect if infrastructure.ts contains a database resource.
41
+ */
42
+ export declare function detectDatabase(appPath: string): boolean;
43
+ export {};
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Pattern detection types and functions.
3
+ *
4
+ * Contains both pure predicates used by operations.ts and
5
+ * filesystem-based detection functions used by orchestration services.
6
+ */
7
+ import { existsSync, readFileSync } from "fs";
8
+ import { join } from "path";
9
+ import { logger, getErrorMessage } from "@fjall/util";
10
+ import { APPLICATION_STACKS } from "./operations.js";
11
+ import { INFRASTRUCTURE_FILENAME } from "./constants.js";
12
+ const OPENNEXT_PATTERNS_ARRAY = ["payload", "nextjs"];
13
+ export const OPENNEXT_PATTERNS = new Set(OPENNEXT_PATTERNS_ARRAY);
14
+ export function isOpenNextPattern(pattern) {
15
+ return (pattern !== undefined && pattern !== null && OPENNEXT_PATTERNS.has(pattern));
16
+ }
17
+ /** Derive resource flags from manifest stack names (authoritative, post-synth) */
18
+ export function deriveResourcesFromManifestStacks(stackNames) {
19
+ const has = (suffix) => stackNames.some((s) => s.endsWith(suffix));
20
+ return {
21
+ hasNetwork: has(APPLICATION_STACKS.NETWORK),
22
+ hasCompute: has(APPLICATION_STACKS.COMPUTE),
23
+ hasDatabase: has(APPLICATION_STACKS.DATABASE),
24
+ hasStorage: has(APPLICATION_STACKS.STORAGE),
25
+ hasMessaging: has(APPLICATION_STACKS.MESSAGING),
26
+ hasCdn: has(APPLICATION_STACKS.CDN)
27
+ };
28
+ }
29
+ /**
30
+ * Read infrastructure.ts content from an app path.
31
+ * Returns null if file doesn't exist or can't be read.
32
+ */
33
+ function readInfrastructureContent(appPath) {
34
+ try {
35
+ const filePath = join(appPath, INFRASTRUCTURE_FILENAME);
36
+ if (!existsSync(filePath))
37
+ return null;
38
+ return readFileSync(filePath, "utf-8");
39
+ }
40
+ catch (error) {
41
+ logger.debug("patternDetection", "Failed to read infrastructure file", {
42
+ appPath,
43
+ error: getErrorMessage(error)
44
+ });
45
+ return null;
46
+ }
47
+ }
48
+ /**
49
+ * Detect the application pattern (Payload, Next.js, or none) from infrastructure.ts.
50
+ *
51
+ * Pattern detection is based on the IaC file (infrastructure.ts), NOT on
52
+ * project files like package.json. This ensures accurate detection even
53
+ * when multiple apps coexist in the same project directory.
54
+ *
55
+ * @param appPath - The fjall app path (e.g., "fjall/app8" or absolute path)
56
+ */
57
+ export function detectPattern(appPath) {
58
+ const content = readInfrastructureContent(appPath);
59
+ if (!content) {
60
+ return { pattern: null, hasDatabase: false };
61
+ }
62
+ if (content.includes("PatternFactory")) {
63
+ if (content.includes('type: "payload"')) {
64
+ return { pattern: "payload", hasDatabase: true };
65
+ }
66
+ if (content.includes('type: "nextjs"')) {
67
+ const hasDatabase = content.includes("DatabaseFactory.build(") ||
68
+ content.includes("database:");
69
+ return { pattern: "nextjs", hasDatabase };
70
+ }
71
+ }
72
+ const hasDatabase = content.includes("DatabaseFactory.build(");
73
+ return { pattern: null, hasDatabase };
74
+ }
75
+ /**
76
+ * Detect if infrastructure.ts contains a Payload CMS pattern.
77
+ */
78
+ export function detectPayloadPattern(appPath) {
79
+ const content = readInfrastructureContent(appPath);
80
+ if (!content)
81
+ return false;
82
+ return (content.includes("PatternFactory") && content.includes('type: "payload"'));
83
+ }
84
+ /**
85
+ * Detect if infrastructure.ts contains a database resource.
86
+ */
87
+ export function detectDatabase(appPath) {
88
+ const content = readInfrastructureContent(appPath);
89
+ if (!content)
90
+ return false;
91
+ return content.includes("DatabaseFactory.build(");
92
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Result of a validation operation
3
+ * Used for form validation, input validation, etc.
4
+ */
5
+ export interface ValidationResult {
6
+ /** Whether the validation passed */
7
+ valid: boolean;
8
+ /** Error messages if validation failed */
9
+ errors: string[];
10
+ /** Warning messages (non-blocking) */
11
+ warnings?: string[];
12
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Async check for file existence. Replaces blocking existsSync().
3
+ */
4
+ export declare function fileExists(filePath: string): Promise<boolean>;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Async file system helpers.
3
+ */
4
+ import { access, constants } from "fs/promises";
5
+ /**
6
+ * Async check for file existence. Replaces blocking existsSync().
7
+ */
8
+ export async function fileExists(filePath) {
9
+ try {
10
+ await access(filePath, constants.F_OK);
11
+ return true;
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ export { DANGEROUS_ENV_VARS, filterDangerousEnvVars, maskSensitiveOutput, parseShellArgs } from "./securityHelpers.js";
2
+ export { sleep } from "./sleep.js";
3
+ export { singleton } from "./singleton.js";
@@ -0,0 +1,3 @@
1
+ export { DANGEROUS_ENV_VARS, filterDangerousEnvVars, maskSensitiveOutput, parseShellArgs } from "./securityHelpers.js";
2
+ export { sleep } from "./sleep.js";
3
+ export { singleton } from "./singleton.js";
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Security helpers for spawn operations
3
+ *
4
+ * Provides environment variable filtering and credential masking
5
+ * to prevent command injection and credential leakage.
6
+ */
7
+ /**
8
+ * Environment variables that MUST NOT be passed from user input to spawned processes.
9
+ * These can be exploited for:
10
+ * - Code execution hijacking (PATH, NODE_OPTIONS)
11
+ * - Dynamic linker injection (LD_PRELOAD, DYLD_INSERT_LIBRARIES)
12
+ * - Interpreter code injection (PYTHONPATH, RUBYLIB)
13
+ * - Credential/identity hijacking (HOME, AWS_CONFIG_FILE)
14
+ * - Shell injection (BASH_ENV, ENV)
15
+ */
16
+ export declare const DANGEROUS_ENV_VARS: Set<string>;
17
+ /**
18
+ * Filter dangerous environment variables from a record.
19
+ * Returns a new object with only safe environment variables.
20
+ */
21
+ export declare function filterDangerousEnvVars(env: Record<string, string | undefined>): Record<string, string | undefined>;
22
+ /**
23
+ * Mask sensitive information in output strings to prevent credential leakage.
24
+ * Patterns: postgres://user:pass@host, password=xxx, secret=xxx, apikey=xxx
25
+ */
26
+ export declare function maskSensitiveOutput(output: string): string;
27
+ /**
28
+ * Parse a shell command string into an array of arguments.
29
+ * Handles single quotes, double quotes, and escaped characters.
30
+ */
31
+ export declare function parseShellArgs(command: string): string[];