@fjall/deploy-core 2.12.0 → 2.14.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 (126) hide show
  1. package/dist/.minified +1 -1
  2. package/dist/src/aws/cloudtrail/orgTrailDelivery.d.ts +44 -0
  3. package/dist/src/aws/cloudtrail/orgTrailDelivery.js +1 -0
  4. package/dist/src/aws/index.d.ts +6 -2
  5. package/dist/src/aws/index.js +1 -1
  6. package/dist/src/aws/organisations/accountGlobals.d.ts +40 -0
  7. package/dist/src/aws/organisations/accountGlobals.js +1 -0
  8. package/dist/src/aws/organisations/accounts.d.ts +3 -1
  9. package/dist/src/aws/organisations/accounts.js +1 -1
  10. package/dist/src/aws/organisations/backup.d.ts +2 -1
  11. package/dist/src/aws/organisations/backup.js +2 -2
  12. package/dist/src/aws/organisations/importedAccounts.d.ts +16 -0
  13. package/dist/src/aws/organisations/importedAccounts.js +1 -0
  14. package/dist/src/aws/organisations/index.d.ts +3 -1
  15. package/dist/src/aws/organisations/index.js +1 -1
  16. package/dist/src/aws/organisations/organisationalUnits.d.ts +1 -1
  17. package/dist/src/aws/organisations/policies.js +1 -1
  18. package/dist/src/aws/organisations/rootAccess.d.ts +27 -0
  19. package/dist/src/aws/organisations/rootAccess.js +3 -0
  20. package/dist/src/aws/organisations/serviceAccess.d.ts +6 -0
  21. package/dist/src/aws/organisations/serviceAccess.js +1 -1
  22. package/dist/src/aws/organisations/types.d.ts +18 -0
  23. package/dist/src/aws/organisations/types.js +1 -1
  24. package/dist/src/aws/sts/assumeRoot.d.ts +46 -0
  25. package/dist/src/aws/sts/assumeRoot.js +1 -0
  26. package/dist/src/aws/targetReadiness.d.ts +70 -0
  27. package/dist/src/aws/targetReadiness.js +1 -0
  28. package/dist/src/aws/targetSetAdvisory.d.ts +24 -0
  29. package/dist/src/aws/targetSetAdvisory.js +1 -0
  30. package/dist/src/events/index.d.ts +2 -0
  31. package/dist/src/events/index.js +1 -1
  32. package/dist/src/index.d.ts +18 -14
  33. package/dist/src/index.js +1 -1
  34. package/dist/src/orchestration/accountsConfig.d.ts +11 -0
  35. package/dist/src/orchestration/accountsConfig.js +1 -1
  36. package/dist/src/orchestration/applicationDeploy.js +1 -1
  37. package/dist/src/orchestration/applicationDestroy.js +1 -1
  38. package/dist/src/orchestration/cascadeDestroyHelpers.d.ts +12 -1
  39. package/dist/src/orchestration/cascadeDestroyHelpers.js +1 -1
  40. package/dist/src/orchestration/cascadeHelpers.d.ts +36 -5
  41. package/dist/src/orchestration/cascadeHelpers.js +1 -1
  42. package/dist/src/orchestration/contextHelpers.d.ts +20 -2
  43. package/dist/src/orchestration/contextHelpers.js +1 -1
  44. package/dist/src/orchestration/index.d.ts +13 -4
  45. package/dist/src/orchestration/index.js +1 -1
  46. package/dist/src/orchestration/organisationDeploy/cascadeExecution.d.ts +28 -0
  47. package/dist/src/orchestration/organisationDeploy/cascadeExecution.js +1 -0
  48. package/dist/src/orchestration/organisationDeploy/infraSteps.d.ts +40 -0
  49. package/dist/src/orchestration/organisationDeploy/infraSteps.js +1 -0
  50. package/dist/src/orchestration/organisationDeploy/orgCascadeDeploy.d.ts +8 -0
  51. package/dist/src/orchestration/organisationDeploy/orgCascadeDeploy.js +5 -0
  52. package/dist/src/orchestration/organisationDeploy/orgContext.d.ts +12 -0
  53. package/dist/src/orchestration/organisationDeploy/orgContext.js +1 -0
  54. package/dist/src/orchestration/organisationDeploy/resolveCascadeAccounts.d.ts +15 -0
  55. package/dist/src/orchestration/organisationDeploy/resolveCascadeAccounts.js +1 -0
  56. package/dist/src/orchestration/organisationDeploy/singleComponentDeploy.d.ts +11 -0
  57. package/dist/src/orchestration/organisationDeploy/singleComponentDeploy.js +1 -0
  58. package/dist/src/orchestration/organisationDeploy/trailReconciliation.d.ts +21 -0
  59. package/dist/src/orchestration/organisationDeploy/trailReconciliation.js +1 -0
  60. package/dist/src/orchestration/organisationDeploy.d.ts +1 -5
  61. package/dist/src/orchestration/organisationDeploy.js +1 -5
  62. package/dist/src/orchestration/organisationDestroy.d.ts +1 -1
  63. package/dist/src/orchestration/organisationDestroy.js +2 -2
  64. package/dist/src/orchestration/organisationSetup.d.ts +23 -3
  65. package/dist/src/orchestration/organisationSetup.js +1 -1
  66. package/dist/src/orchestration/reconcileProviderAccounts.js +1 -1
  67. package/dist/src/orchestration/stackCleanup/bucketOps.d.ts +54 -0
  68. package/dist/src/orchestration/stackCleanup/bucketOps.js +1 -0
  69. package/dist/src/orchestration/stackCleanup/failedStack.d.ts +34 -0
  70. package/dist/src/orchestration/stackCleanup/failedStack.js +1 -0
  71. package/dist/src/orchestration/stackCleanup/logging.d.ts +9 -0
  72. package/dist/src/orchestration/stackCleanup/logging.js +1 -0
  73. package/dist/src/orchestration/stackCleanup/messages.d.ts +16 -0
  74. package/dist/src/orchestration/stackCleanup/messages.js +1 -0
  75. package/dist/src/orchestration/stackCleanup/orphanSweep.d.ts +25 -0
  76. package/dist/src/orchestration/stackCleanup/orphanSweep.js +1 -0
  77. package/dist/src/orchestration/stackCleanup/preEmpty.d.ts +35 -0
  78. package/dist/src/orchestration/stackCleanup/preEmpty.js +1 -0
  79. package/dist/src/orchestration/stackCleanup/stackResources.d.ts +9 -0
  80. package/dist/src/orchestration/stackCleanup/stackResources.js +1 -0
  81. package/dist/src/orchestration/stackCleanup.d.ts +13 -33
  82. package/dist/src/orchestration/stackCleanup.js +1 -1
  83. package/dist/src/orchestration/trailMigration/memberTrailCleanup.d.ts +43 -0
  84. package/dist/src/orchestration/trailMigration/memberTrailCleanup.js +1 -0
  85. package/dist/src/orchestration/trailMigration/trailMigration.d.ts +64 -0
  86. package/dist/src/orchestration/trailMigration/trailMigration.js +1 -0
  87. package/dist/src/orchestration/unlock/scpRemediation.d.ts +15 -0
  88. package/dist/src/orchestration/unlock/scpRemediation.js +1 -0
  89. package/dist/src/orchestration/unlock/unlockBucket.d.ts +37 -0
  90. package/dist/src/orchestration/unlock/unlockBucket.js +1 -0
  91. package/dist/src/orchestration/unlock/unlockQueue.d.ts +43 -0
  92. package/dist/src/orchestration/unlock/unlockQueue.js +1 -0
  93. package/dist/src/services/application/ApplicationStackService.d.ts +9 -10
  94. package/dist/src/services/application/ApplicationStackService.js +1 -1
  95. package/dist/src/services/application/applicationStackHelpers.d.ts +13 -8
  96. package/dist/src/services/application/applicationStackHelpers.js +3 -3
  97. package/dist/src/services/infrastructure/CdkArgumentBuilder.js +1 -1
  98. package/dist/src/services/infrastructure/CdkServiceTypes.d.ts +1 -0
  99. package/dist/src/services/infrastructure/cdkServiceHelpers.js +1 -1
  100. package/dist/src/services/supporting/CdkContextBuilder.d.ts +1 -0
  101. package/dist/src/services/supporting/CdkContextBuilder.js +1 -1
  102. package/dist/src/steps/stepRegistry.js +1 -1
  103. package/dist/src/types/FjallState.d.ts +7 -0
  104. package/dist/src/types/FjallState.js +1 -1
  105. package/dist/src/types/callbackKeys.d.ts +1 -1
  106. package/dist/src/types/callbackKeys.js +1 -1
  107. package/dist/src/types/callbacks.d.ts +58 -3
  108. package/dist/src/types/callbacks.js +1 -0
  109. package/dist/src/types/deployment/DeploymentTypes.d.ts +1 -0
  110. package/dist/src/types/deploymentEventSchema.d.ts +28 -3
  111. package/dist/src/types/deploymentEventSchema.js +1 -1
  112. package/dist/src/types/events.d.ts +12 -0
  113. package/dist/src/types/events.js +1 -0
  114. package/dist/src/types/index.d.ts +7 -11
  115. package/dist/src/types/index.js +1 -1
  116. package/dist/src/types/orgConfig.d.ts +8 -2
  117. package/dist/src/types/params.d.ts +18 -0
  118. package/dist/src/types/patternDetection.d.ts +0 -25
  119. package/dist/src/types/patternDetection.js +1 -1
  120. package/dist/src/types/stepDefinitions.d.ts +2 -0
  121. package/dist/src/types/stepDefinitions.js +1 -1
  122. package/dist/src/util/index.d.ts +1 -0
  123. package/dist/src/util/index.js +1 -1
  124. package/dist/src/util/sleepAbortable.d.ts +8 -0
  125. package/dist/src/util/sleepAbortable.js +1 -0
  126. package/package.json +8 -4
@@ -24,6 +24,13 @@ export type FjallStateFile = z.infer<typeof FjallStateFileSchema>;
24
24
  * Get the state file path for an application
25
25
  */
26
26
  export declare function getStateFilePath(appPath: string): string;
27
+ /**
28
+ * Suffix form of a region for cascade artefact naming — shared by assembly
29
+ * dirs (`cdk.out.<accountId>.<suffix>`), per-account state files, and the
30
+ * Platform stack's IPAM output keys (`IpamPoolId<accountId><suffix>`). One
31
+ * derivation so producers and consumers of those names cannot drift.
32
+ */
33
+ export declare function regionSuffix(region: string): string;
27
34
  /**
28
35
  * Get the per-account state file path for a cascade target.
29
36
  *
@@ -1 +1 @@
1
- import{z as a}from"zod";import{randomBytes as u}from"crypto";import{readFile as d,writeFile as f,unlink as s,rename as m,mkdir as S}from"fs/promises";import{dirname as g,join as c}from"path";import{fileExists as h}from"@fjall/util/fsHelpers";import{logger as o}from"@fjall/util/logger";import{getErrorMessage as i,maskSensitiveOutput as y}from"@fjall/util";const F=a.object({hash:a.string(),deployedAt:a.string(),stackStatus:a.string().optional()}).strict(),w=a.object({version:a.literal(1),lastDeployedAt:a.string().optional(),templateHashes:a.record(a.string(),F),metadata:a.record(a.string(),a.unknown()).optional()}).strict(),x=".fjall-state.json";function l(t){return c(t,x)}function $(t,r,e){const n=e.replace(/-/g,"");return c(t,`.fjall-state.cascade-${r}-${n}.json`)}async function j(t){if(!await h(t))return null;try{const r=await d(t,"utf-8"),e=JSON.parse(r),n=w.safeParse(e);return n.success?n.data:null}catch(r){return o.debug("FjallState","Failed to read state file",{path:t,error:i(r)}),null}}async function E(t,r){const e=`${t}.${Date.now()}-${u(4).toString("hex")}.tmp`;await S(g(t),{recursive:!0});try{await f(e,JSON.stringify(r,null,2),"utf-8"),await m(e,t)}catch(n){try{await s(e)}catch(p){o.debug("FjallState","Temp file cleanup failed (non-fatal)",{path:e,error:i(p)})}throw n}}async function k(t){return j(l(t))}async function v(t,r){return E(l(t),r)}function I(){return{version:1,templateHashes:{}}}async function J(t){const r=l(t);try{await s(r)}catch(e){(typeof e=="object"&&e!==null&&"code"in e?e.code:void 0)!=="ENOENT"&&o.warn("FjallState","Failed to delete state file",{path:r,error:y(i(e))})}}function M(t,r,e,n){return{...t,lastDeployedAt:new Date().toISOString(),templateHashes:{...t.templateHashes,[r]:{hash:e,deployedAt:new Date().toISOString(),...n!==void 0&&{stackStatus:n}}}}}export{w as FjallStateFileSchema,I as createEmptyState,J as deleteStateFile,$ as getCascadeStateFilePath,l as getStateFilePath,k as readStateFile,j as readStateFileAt,M as updateTemplateHash,v as writeStateFile,E as writeStateFileAt};
1
+ import{z as a}from"zod";import{randomBytes as u}from"crypto";import{readFile as f,writeFile as d,unlink as s,rename as m,mkdir as S}from"fs/promises";import{dirname as g,join as c}from"path";import{fileExists as h}from"@fjall/util/fsHelpers";import{logger as o}from"@fjall/util/logger";import{getErrorMessage as i,maskSensitiveOutput as y}from"@fjall/util";const F=a.object({hash:a.string(),deployedAt:a.string(),stackStatus:a.string().optional()}).strict(),w=a.object({version:a.literal(1),lastDeployedAt:a.string().optional(),templateHashes:a.record(a.string(),F),metadata:a.record(a.string(),a.unknown()).optional()}).strict(),x=".fjall-state.json";function l(t){return c(t,x)}function j(t){return t.replace(/-/g,"")}function k(t,r,e){return c(t,`.fjall-state.cascade-${r}-${j(e)}.json`)}async function E(t){if(!await h(t))return null;try{const r=await f(t,"utf-8"),e=JSON.parse(r),n=w.safeParse(e);return n.success?n.data:null}catch(r){return o.debug("FjallState","Failed to read state file",{path:t,error:i(r)}),null}}async function A(t,r){const e=`${t}.${Date.now()}-${u(4).toString("hex")}.tmp`;await S(g(t),{recursive:!0});try{await d(e,JSON.stringify(r,null,2),"utf-8"),await m(e,t)}catch(n){try{await s(e)}catch(p){o.debug("FjallState","Temp file cleanup failed (non-fatal)",{path:e,error:i(p)})}throw n}}async function v(t){return E(l(t))}async function I(t,r){return A(l(t),r)}function J(){return{version:1,templateHashes:{}}}async function M(t){const r=l(t);try{await s(r)}catch(e){(typeof e=="object"&&e!==null&&"code"in e?e.code:void 0)!=="ENOENT"&&o.warn("FjallState","Failed to delete state file",{path:r,error:y(i(e))})}}function _(t,r,e,n){return{...t,lastDeployedAt:new Date().toISOString(),templateHashes:{...t.templateHashes,[r]:{hash:e,deployedAt:new Date().toISOString(),...n!==void 0&&{stackStatus:n}}}}}export{w as FjallStateFileSchema,J as createEmptyState,M as deleteStateFile,k as getCascadeStateFilePath,l as getStateFilePath,v as readStateFile,E as readStateFileAt,j as regionSuffix,_ as updateTemplateHash,I as writeStateFile,A as writeStateFileAt};
@@ -1,6 +1,6 @@
1
1
  import type { DeployCallbacks } from "./callbacks.js";
2
2
  /**
3
- * Every {@link DeployCallbacks} key (43 callbacks + the `verbose` flag),
3
+ * Every {@link DeployCallbacks} key (45 callbacks + the `verbose` flag),
4
4
  * derived from the type-checked {@link CALLBACK_KEY_PRESENCE} map so the list
5
5
  * can never silently diverge from the interface.
6
6
  */
@@ -1 +1 @@
1
- const e={onStepStart:!0,onStepComplete:!0,onProgress:!0,onLog:!0,onOutput:!0,onResourceProgress:!0,onParallelPhaseStart:!0,onParallelPhaseComplete:!0,onParallelStackResourceProgress:!0,onDockerProgress:!0,onBuildPushStart:!0,onBuildPushProgress:!0,onBuildPushComplete:!0,onTaskDefRegistered:!0,onECSUpdate:!0,onECSProgress:!0,onECSComplete:!0,onMigrationsStart:!0,onMigrationsComplete:!0,onCDKBootstrap:!0,onCdkOutput:!0,onCascadeStart:!0,onCascadeAccountsReconciled:!0,onOrgChangesDetected:!0,onCascadeMissingAccounts:!0,onCascadePhaseStart:!0,onCascadePhaseComplete:!0,onCascadeAccountStart:!0,onCascadeAccountPhaseChange:!0,onCascadeAccountResourceProgress:!0,onCascadeAccountComplete:!0,onCascadeComplete:!0,onCascadeLedger:!0,onStackCleanupProgress:!0,onDetectionComplete:!0,onDetectionPhaseChange:!0,onSSOUrl:!0,onAuthComplete:!0,onOpenNextBuildStart:!0,onOpenNextProgress:!0,onOpenNextBuildComplete:!0,onOpenNextBuildError:!0,onError:!0,verbose:!0},t=Object.keys(e);export{t as ALL_CALLBACK_KEYS};
1
+ const e={onStepStart:!0,onStepComplete:!0,onProgress:!0,onLog:!0,onOutput:!0,onResourceProgress:!0,onParallelPhaseStart:!0,onParallelPhaseComplete:!0,onParallelStackResourceProgress:!0,onDockerProgress:!0,onBuildPushStart:!0,onBuildPushProgress:!0,onBuildPushComplete:!0,onTaskDefRegistered:!0,onECSUpdate:!0,onECSProgress:!0,onECSComplete:!0,onMigrationsStart:!0,onMigrationsComplete:!0,onCDKBootstrap:!0,onCdkOutput:!0,onCascadeStart:!0,onCascadeAccountsReconciled:!0,onOrgChangesDetected:!0,onCascadeMissingAccounts:!0,onCascadePhaseStart:!0,onCascadePhaseComplete:!0,onCascadeAccountStart:!0,onCascadeAccountPhaseChange:!0,onCascadeAccountResourceProgress:!0,onCascadeAccountComplete:!0,onCascadeComplete:!0,onCascadeLedger:!0,onTrailMigrationPhase:!0,onTrailLifecycleChanged:!0,onStackCleanupProgress:!0,onDetectionComplete:!0,onDetectionPhaseChange:!0,onSSOUrl:!0,onAuthComplete:!0,onOpenNextBuildStart:!0,onOpenNextProgress:!0,onOpenNextBuildComplete:!0,onOpenNextBuildError:!0,onError:!0,verbose:!0},t=Object.keys(e);export{t as ALL_CALLBACK_KEYS};
@@ -1,7 +1,42 @@
1
- import type { ProgressEvent, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent } from "./events.js";
1
+ import type { ProgressEvent, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhaseEvent } from "./events.js";
2
+ import type { TrailLifecycleState } from "@fjall/util/config";
2
3
  import type { DetectionResult } from "./detection.js";
3
4
  import type { CascadeLedger } from "../orchestration/cascadeSummary.js";
4
5
  export type StepCompleteStatus = "completed" | "skipped" | "error";
6
+ /**
7
+ * Structured payload for the "quarantine-suspected" stack-cleanup phase:
8
+ * an AccessDenied empty pass on a DELETE_FAILED bucket, the earliest signal
9
+ * that the auto-delete deny policy stranded the bucket.
10
+ */
11
+ export interface StackCleanupQuarantineDetail {
12
+ /** Bucket whose empty pass was denied. */
13
+ bucketName: string;
14
+ /** Account the bucket lives in, when the caller knows it. */
15
+ accountId?: string;
16
+ }
17
+ /**
18
+ * Structured payload for the "retained-buckets" stack-cleanup phase: buckets
19
+ * the pre-empty pass left untouched (no pre-empty tag → Retain removal
20
+ * policy). Emitted once per stack when the retained set is non-empty, so
21
+ * operators hear by name which buckets survive the destroy (AC3.5).
22
+ */
23
+ export interface StackCleanupRetainedBucketsDetail {
24
+ /** Bucket names left in place; they survive the destroy by design. */
25
+ retainedBuckets: string[];
26
+ /**
27
+ * Pre-formatted, identifier-only operator copy (canonical source:
28
+ * formatRetainedBucketsMessage in orchestration/stackCleanup.ts). Adapters
29
+ * render this verbatim so the remediation wording has a single source.
30
+ */
31
+ message: string;
32
+ }
33
+ /**
34
+ * Narrow an onStackCleanupProgress detail to the quarantine payload.
35
+ * Accepts undefined so call sites drop their `detail !== undefined &&` prefix.
36
+ */
37
+ export declare function isQuarantineDetail(detail: StackCleanupQuarantineDetail | StackCleanupRetainedBucketsDetail | undefined): detail is StackCleanupQuarantineDetail;
38
+ /** Narrow an onStackCleanupProgress detail to the retained-buckets payload. */
39
+ export declare function isRetainedBucketsDetail(detail: StackCleanupQuarantineDetail | StackCleanupRetainedBucketsDetail | undefined): detail is StackCleanupRetainedBucketsDetail;
5
40
  /**
6
41
  * Unified callback interface for deployment progress.
7
42
  *
@@ -159,8 +194,28 @@ export interface DeployCallbacks {
159
194
  * summary from it; the webapp/worker ignores it and reads the scalar above.
160
195
  */
161
196
  onCascadeLedger?: (ledger: CascadeLedger) => void;
162
- /** @emittedBy engine — progress during failed-state stack cleanup (S3 emptying, deletion). */
163
- onStackCleanupProgress?: (stackName: string, phase: "emptying-bucket" | "deleting-stack" | "waiting" | "complete" | "error") => void;
197
+ /**
198
+ * @emittedBy engine per-account progress through the org-trail migration
199
+ * reconciler (delivery verification, storage decommission). `detail` is
200
+ * pre-masked by the engine.
201
+ */
202
+ onTrailMigrationPhase?: (event: TrailMigrationPhaseEvent) => void;
203
+ /**
204
+ * @emittedBy engine — fired when the reconciler advances an account's
205
+ * `trailLifecycle` (undefined → "draining" → "org"). Consumers persist the
206
+ * new state to their config store (CLI: org-config API push; worker:
207
+ * ConnectedAwsAccount update) — the engine holds no durable state itself.
208
+ */
209
+ onTrailLifecycleChanged?: (accountId: string, from: TrailLifecycleState | undefined, to: TrailLifecycleState) => void;
210
+ /**
211
+ * @emittedBy engine — progress during failed-state stack cleanup (S3
212
+ * emptying, deletion) and the pre-destroy pre-empty pass. `detail` is only
213
+ * populated for two phases: "quarantine-suspected" (Phase 2's detection
214
+ * rule and `fjall unlock` consume that vocabulary, so the literal must not
215
+ * be renamed) and "retained-buckets" (the production-retained set, named
216
+ * so operators delete deliberately).
217
+ */
218
+ onStackCleanupProgress?: (stackName: string, phase: "emptying-bucket" | "deleting-stack" | "waiting" | "complete" | "error" | "quarantine-suspected" | "retained-buckets", detail?: StackCleanupQuarantineDetail | StackCleanupRetainedBucketsDetail) => void;
164
219
  /**
165
220
  * @emittedBy engine — fired after the detection pipeline completes with full analysis results.
166
221
  * May be async — engine awaits the return value so callers can run post-detection
@@ -0,0 +1 @@
1
+ function n(e){return e!==void 0&&"bucketName"in e}function t(e){return e!==void 0&&"retainedBuckets"in e}export{n as isQuarantineDetail,t as isRetainedBucketsDetail};
@@ -23,6 +23,7 @@ export interface DeploymentContext {
23
23
  fjallOrgId?: string;
24
24
  fjallOidcConfigured?: boolean;
25
25
  fjallAccountGlobalsConfigured?: boolean;
26
+ fjallAccountTrailState?: string;
26
27
  orgConfig?: string;
27
28
  fjallAdoptBackupVault?: boolean;
28
29
  resolvedSecretArns?: string;
@@ -15,23 +15,33 @@ export declare const DEPLOYMENT_EVENT_RESOURCE_CATEGORIES: readonly ["security",
15
15
  export type DeploymentEventResourceCategory = (typeof DEPLOYMENT_EVENT_RESOURCE_CATEGORIES)[number];
16
16
  export declare const CASCADE_PHASES: readonly ["platform", "domains", "accounts"];
17
17
  export declare const CASCADE_ACCOUNT_STATUSES: readonly ["started", "deploying", "completed", "failed"];
18
- export declare const DEPLOYMENT_EVENT_TYPES: readonly ["step", "resource", "docker", "ecs", "error", "complete", "cascade_phase", "cascade_account", "cascade_missing_accounts", "parallel_phase", "detection", "log"];
18
+ /**
19
+ * Field caps shared with producers that truncate before enqueueing (webapp
20
+ * `deploymentCallbackAdapter`). Defined beside the schema so its `.max()`
21
+ * and the producer's `.slice()` cannot drift apart — a producer cap above
22
+ * the schema cap makes the server reject the whole event.
23
+ */
24
+ export declare const DEPLOYMENT_EVENT_STATUS_REASON_MAX = 2048;
25
+ export declare const DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX = 4096;
26
+ export declare const DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX = 2048;
27
+ export declare const DEPLOYMENT_EVENT_TYPES: readonly ["step", "resource", "docker", "ecs", "error", "complete", "cascade_phase", "cascade_account", "cascade_missing_accounts", "parallel_phase", "detection", "trail_migration", "log"];
19
28
  export type DeploymentEventType = (typeof DEPLOYMENT_EVENT_TYPES)[number];
20
29
  export type DeploymentEventCascadePhase = (typeof CASCADE_PHASES)[number];
21
30
  export type DeploymentEventCascadeAccountStatus = (typeof CASCADE_ACCOUNT_STATUSES)[number];
22
31
  export declare const DeploymentEventSchema: z.ZodObject<{
23
32
  type: z.ZodEnum<{
24
33
  step: "step";
34
+ error: "error";
25
35
  resource: "resource";
26
36
  docker: "docker";
27
37
  ecs: "ecs";
28
- error: "error";
29
38
  complete: "complete";
30
39
  cascade_phase: "cascade_phase";
31
40
  cascade_account: "cascade_account";
32
41
  cascade_missing_accounts: "cascade_missing_accounts";
33
42
  parallel_phase: "parallel_phase";
34
43
  detection: "detection";
44
+ trail_migration: "trail_migration";
35
45
  log: "log";
36
46
  }>;
37
47
  timestamp: z.ZodString;
@@ -101,9 +111,9 @@ export declare const DeploymentEventSchema: z.ZodObject<{
101
111
  operationKey: z.ZodString;
102
112
  status: z.ZodEnum<{
103
113
  started: "started";
104
- deploying: "deploying";
105
114
  completed: "completed";
106
115
  failed: "failed";
116
+ deploying: "deploying";
107
117
  }>;
108
118
  error: z.ZodOptional<z.ZodString>;
109
119
  phase: z.ZodOptional<z.ZodEnum<{
@@ -147,6 +157,21 @@ export declare const DeploymentEventSchema: z.ZodObject<{
147
157
  }, z.core.$strict>;
148
158
  requiredSecrets: z.ZodOptional<z.ZodArray<z.ZodString>>;
149
159
  }, z.core.$strict>>;
160
+ trailMigration: z.ZodOptional<z.ZodObject<{
161
+ accountId: z.ZodString;
162
+ accountName: z.ZodString;
163
+ phase: z.ZodEnum<{
164
+ "verify-delivery": "verify-delivery";
165
+ decommission: "decommission";
166
+ }>;
167
+ status: z.ZodEnum<{
168
+ started: "started";
169
+ completed: "completed";
170
+ blocked: "blocked";
171
+ failed: "failed";
172
+ }>;
173
+ detail: z.ZodOptional<z.ZodString>;
174
+ }, z.core.$strict>>;
150
175
  log: z.ZodOptional<z.ZodObject<{
151
176
  message: z.ZodString;
152
177
  level: z.ZodEnum<{
@@ -1 +1 @@
1
- import{z as e}from"zod";const r=["security","network","compute","database","storage","monitoring","dns","identity","bootstrap","events","registry","backup"],n=["platform","domains","accounts"],c=["started","deploying","completed","failed"],i=["step","resource","docker","ecs","error","complete","cascade_phase","cascade_account","cascade_missing_accounts","parallel_phase","detection","log"],m={step:"step",resource:"resource",docker:"docker",ecs:"ecs",error:"error",complete:null,cascade_phase:"cascadePhase",cascade_account:"cascadeAccount",cascade_missing_accounts:"cascadeMissingAccounts",parallel_phase:"parallelPhase",detection:"detection",log:"log"},p=e.object({type:e.enum(i),timestamp:e.string().max(64),sequence:e.number().int().nonnegative().optional(),step:e.object({id:e.string().max(256),name:e.string().max(256),index:e.number(),total:e.number(),status:e.string().max(64)}).strict().optional(),resource:e.object({logicalId:e.string().max(256),resourceType:e.string().max(256),category:e.enum(r),group:e.string().max(128).optional(),constructPath:e.string().max(512).optional(),displayName:e.string().max(256),status:e.string().max(64),statusReason:e.string().max(2048).optional(),physicalId:e.string().max(2048).optional(),expectedDurationSeconds:e.number().optional(),stack:e.string().max(256).optional()}).strict().optional(),docker:e.object({message:e.string().max(2048),percentage:e.number().optional()}).strict().optional(),ecs:e.object({status:e.string().max(64),message:e.string().max(2048).optional(),percentage:e.number().optional()}).strict().optional(),error:e.object({message:e.string().max(4096),category:e.string().max(128).optional(),remediation:e.array(e.string().max(1024)).max(10).optional()}).strict().optional(),message:e.string().max(2048).optional(),cascadePhase:e.object({phase:e.enum(n),status:e.enum(["started","completed"])}).strict().optional(),cascadeAccount:e.object({accountId:e.string().max(32),region:e.string().max(32),operationKey:e.string().max(256),status:e.enum(c),error:e.string().max(2048).optional(),phase:e.enum(["bootstrap","synth","deploy","destroy"]).optional(),cascadePhase:e.enum(n).optional()}).strict().optional(),cascadeMissingAccounts:e.object({accountNames:e.array(e.string().max(256)).max(256)}).strict().optional(),parallelPhase:e.object({stacks:e.array(e.string().max(256)).max(20),status:e.enum(["started","completed"]),results:e.array(e.object({stack:e.string().max(256),success:e.boolean(),error:e.string().max(2048).optional()}).strict()).max(20).optional()}).strict().optional(),detection:e.object({pattern:e.string().max(128).nullable(),hasDockerfile:e.boolean(),hasDifferences:e.boolean(),resources:e.object({hasNetwork:e.boolean(),hasCompute:e.boolean(),hasDatabase:e.boolean(),hasStorage:e.boolean(),hasMessaging:e.boolean(),hasCdn:e.boolean()}).strict(),requiredSecrets:e.array(e.string().max(512)).max(100).optional()}).strict().optional(),log:e.object({message:e.string().max(2048),level:e.enum(["info","debug","warn"])}).strict().optional()}).strict().superRefine((t,s)=>{const a=m[t.type],o=a?t[a]:void 0;a&&o==null&&s.addIssue({code:e.ZodIssueCode.custom,message:`"${a}" is required when type is "${t.type}"`,path:[a]}),t.type==="complete"&&!t.message&&s.addIssue({code:e.ZodIssueCode.custom,message:'"message" is required when type is "complete"',path:["message"]})});function u(t){if(t==="platform")return"platform";if(t==="account")return"accounts"}export{c as CASCADE_ACCOUNT_STATUSES,n as CASCADE_PHASES,r as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,i as DEPLOYMENT_EVENT_TYPES,p as DeploymentEventSchema,u as toCascadePhase};
1
+ import{z as e}from"zod";import{TRAIL_MIGRATION_PHASES as r,TRAIL_MIGRATION_STATUSES as i}from"./events.js";const c=["security","network","compute","database","storage","monitoring","dns","identity","bootstrap","events","registry","backup"],n=["platform","domains","accounts"],m=["started","deploying","completed","failed"],l=2048,p=4096,u=2048,g=["step","resource","docker","ecs","error","complete","cascade_phase","cascade_account","cascade_missing_accounts","parallel_phase","detection","trail_migration","log"],d={step:"step",resource:"resource",docker:"docker",ecs:"ecs",error:"error",complete:null,cascade_phase:"cascadePhase",cascade_account:"cascadeAccount",cascade_missing_accounts:"cascadeMissingAccounts",parallel_phase:"parallelPhase",detection:"detection",trail_migration:"trailMigration",log:"log"},_=e.object({type:e.enum(g),timestamp:e.string().max(64),sequence:e.number().int().nonnegative().optional(),step:e.object({id:e.string().max(256),name:e.string().max(256),index:e.number(),total:e.number(),status:e.string().max(64)}).strict().optional(),resource:e.object({logicalId:e.string().max(256),resourceType:e.string().max(256),category:e.enum(c),group:e.string().max(128).optional(),constructPath:e.string().max(512).optional(),displayName:e.string().max(256),status:e.string().max(64),statusReason:e.string().max(l).optional(),physicalId:e.string().max(2048).optional(),expectedDurationSeconds:e.number().optional(),stack:e.string().max(256).optional()}).strict().optional(),docker:e.object({message:e.string().max(2048),percentage:e.number().optional()}).strict().optional(),ecs:e.object({status:e.string().max(64),message:e.string().max(2048).optional(),percentage:e.number().optional()}).strict().optional(),error:e.object({message:e.string().max(p),category:e.string().max(128).optional(),remediation:e.array(e.string().max(1024)).max(10).optional()}).strict().optional(),message:e.string().max(2048).optional(),cascadePhase:e.object({phase:e.enum(n),status:e.enum(["started","completed"])}).strict().optional(),cascadeAccount:e.object({accountId:e.string().max(32),region:e.string().max(32),operationKey:e.string().max(256),status:e.enum(m),error:e.string().max(2048).optional(),phase:e.enum(["bootstrap","synth","deploy","destroy"]).optional(),cascadePhase:e.enum(n).optional()}).strict().optional(),cascadeMissingAccounts:e.object({accountNames:e.array(e.string().max(256)).max(256)}).strict().optional(),parallelPhase:e.object({stacks:e.array(e.string().max(256)).max(20),status:e.enum(["started","completed"]),results:e.array(e.object({stack:e.string().max(256),success:e.boolean(),error:e.string().max(2048).optional()}).strict()).max(20).optional()}).strict().optional(),detection:e.object({pattern:e.string().max(128).nullable(),hasDockerfile:e.boolean(),hasDifferences:e.boolean(),resources:e.object({hasNetwork:e.boolean(),hasCompute:e.boolean(),hasDatabase:e.boolean(),hasStorage:e.boolean(),hasMessaging:e.boolean(),hasCdn:e.boolean()}).strict(),requiredSecrets:e.array(e.string().max(512)).max(100).optional()}).strict().optional(),trailMigration:e.object({accountId:e.string().max(32),accountName:e.string().max(256),phase:e.enum(r),status:e.enum(i),detail:e.string().max(u).optional()}).strict().optional(),log:e.object({message:e.string().max(2048),level:e.enum(["info","debug","warn"])}).strict().optional()}).strict().superRefine((t,o)=>{const a=d[t.type],s=a?t[a]:void 0;a&&s==null&&o.addIssue({code:e.ZodIssueCode.custom,message:`"${a}" is required when type is "${t.type}"`,path:[a]}),t.type==="complete"&&!t.message&&o.addIssue({code:e.ZodIssueCode.custom,message:'"message" is required when type is "complete"',path:["message"]})});function b(t){if(t==="platform")return"platform";if(t==="account")return"accounts"}export{m as CASCADE_ACCOUNT_STATUSES,n as CASCADE_PHASES,p as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,c as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,l as DEPLOYMENT_EVENT_STATUS_REASON_MAX,u as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,g as DEPLOYMENT_EVENT_TYPES,_ as DeploymentEventSchema,b as toCascadePhase};
@@ -88,3 +88,15 @@ export interface MigrationsCompleteEvent {
88
88
  /** ECS stoppedReason verbatim when success=false. */
89
89
  reason?: string;
90
90
  }
91
+ export declare const TRAIL_MIGRATION_PHASES: readonly ["verify-delivery", "decommission"];
92
+ export type TrailMigrationPhase = (typeof TRAIL_MIGRATION_PHASES)[number];
93
+ export declare const TRAIL_MIGRATION_STATUSES: readonly ["started", "completed", "blocked", "failed"];
94
+ export type TrailMigrationStatus = (typeof TRAIL_MIGRATION_STATUSES)[number];
95
+ export interface TrailMigrationPhaseEvent {
96
+ accountId: string;
97
+ accountName: string;
98
+ phase: TrailMigrationPhase;
99
+ status: TrailMigrationStatus;
100
+ /** Pre-masked human-readable detail (block reason, failure summary). */
101
+ detail?: string;
102
+ }
@@ -0,0 +1 @@
1
+ const e=["verify-delivery","decommission"],o=["started","completed","blocked","failed"];export{e as TRAIL_MIGRATION_PHASES,o as TRAIL_MIGRATION_STATUSES};
@@ -1,11 +1,13 @@
1
- export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURCE_CATEGORIES, CASCADE_PHASES, CASCADE_ACCOUNT_STATUSES, toCascadePhase } from "./deploymentEventSchema.js";
1
+ export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURCE_CATEGORIES, DEPLOYMENT_EVENT_STATUS_REASON_MAX, DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX, DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX, CASCADE_PHASES, CASCADE_ACCOUNT_STATUSES, toCascadePhase } from "./deploymentEventSchema.js";
2
2
  export type { DeploymentEvent, DeploymentEventType, DeploymentEventResourceCategory, DeploymentEventCascadePhase, DeploymentEventCascadeAccountStatus } from "./deploymentEventSchema.js";
3
3
  export type { AwsCredentials, DeployIdentity } from "./credentials.js";
4
- export type { DeployCallbacks, StepCompleteStatus } from "./callbacks.js";
5
- export type { ProgressEvent, ProgressEventType, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent } from "./events.js";
4
+ export type { DeployCallbacks, StepCompleteStatus, StackCleanupQuarantineDetail, StackCleanupRetainedBucketsDetail } from "./callbacks.js";
5
+ export { isQuarantineDetail, isRetainedBucketsDetail } from "./callbacks.js";
6
+ export type { ProgressEvent, ProgressEventType, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhase, TrailMigrationStatus, TrailMigrationPhaseEvent } from "./events.js";
7
+ export { TRAIL_MIGRATION_PHASES, TRAIL_MIGRATION_STATUSES } from "./events.js";
6
8
  export type { ApiClientInterface, EntitlementsData } from "./apiClient.js";
7
9
  export type { DeployParams, DeployOptions, DeploymentType, DeployResult, DestroyParams, DestroyOptions, DestroyResult } from "./params.js";
8
- export type { OrgConfig, ProviderAccount, SSOSession } from "./orgConfig.js";
10
+ export type { OrgConfig, ProviderAccount, RootAccessManagementMode, SSOSession } from "./orgConfig.js";
9
11
  export type { Entitlements } from "./entitlements.js";
10
12
  export type { StackOutput, StackOutputsRecord, DeploymentContext, StepOutput, ApplicationDeploymentContext, CallerIdentity } from "./deployment/index.js";
11
13
  export { stubCallerIdentity } from "./deployment/index.js";
@@ -20,16 +22,10 @@ export { PARALLEL_OPERATION_TYPES } from "./deployment/index.js";
20
22
  export type { OpenNextPattern, AppResourceFlags } from "./patternTypes.js";
21
23
  export { isOpenNextPattern, OPENNEXT_PATTERNS } from "./patternTypes.js";
22
24
  export { deriveResourcesFromManifestStacks } from "./patternDetection.js";
23
- /** @deprecated Use FrameworkRegistry.resolve() instead */
24
- export { detectPattern } from "./patternDetection.js";
25
- /** @deprecated Use FrameworkRegistry.resolve() instead */
26
- export { detectPayloadPattern } from "./patternDetection.js";
27
- /** @deprecated Use FrameworkRegistry.resolve() instead */
28
- export { detectDatabase } from "./patternDetection.js";
29
25
  export { STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME } from "./constants.js";
30
26
  export { ApplicationError, wrapApplicationError, type ApplicationErrorType, type StackDeploymentData, type StackDeploymentOptions, type ApplicationDeploymentData, type ApplicationDestructionData } from "./application/index.js";
31
27
  export type { FjallStateFile, TemplateHashEntry } from "./FjallState.js";
32
- export { FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath } from "./FjallState.js";
28
+ export { FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, regionSuffix } from "./FjallState.js";
33
29
  export type { FrameworkBuilder, FrameworkDetection, BuildPlan, BuildCommand, BuildCallbacks, DetectionContext, BuildOptions } from "./frameworkBuilder.js";
34
30
  export { STEP_IDS, STEP_NAMES, INFRASTRUCTURE_STEP_NAMES, INFRA_STEP_NAME } from "./stepDefinitions.js";
35
31
  export type { StepId, InfrastructureStepName, StepDefinition, StepDeploymentType, Operation, StepContext } from "./stepDefinitions.js";
@@ -1 +1 @@
1
- import{DeploymentEventSchema as r,DEPLOYMENT_EVENT_TYPES as E,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as a,CASCADE_PHASES as o,CASCADE_ACCOUNT_STATUSES as A,toCascadePhase as S}from"./deploymentEventSchema.js";import{stubCallerIdentity as T}from"./deployment/index.js";import{ProgressReporter as _}from"./ProgressEvent.js";import{APPLICATION_STACKS as i,ORGANISATION_TYPES as N,APPLICATION_DEPLOY_ORDER as R,APPLICATION_DESTROY_ORDER as l,OPENNEXT_DEPLOY_ORDER as D,OPENNEXT_DESTROY_ORDER as m,PARALLEL_DEPLOY_GROUPS as n,PARALLEL_DESTROY_GROUPS as s,OPENNEXT_PARALLEL_GROUPS as c,isApplicationOperation as C,isOrganisationOperation as L,getParallelDeployGroups as I,getParallelDestroyGroups as f,getApplicationDeployOrder as x,getApplicationDestroyOrder as d,getApplicationStackName as F,getOrganisationStackName as g,isApplicationStack as U,getApplicationStepName as Y,getApplicationStepId as y,toPascalCase as M}from"./operations.js";import{PARALLEL_OPERATION_TYPES as h}from"./deployment/index.js";import{isOpenNextPattern as K,OPENNEXT_PATTERNS as k}from"./patternTypes.js";import{deriveResourcesFromManifestStacks as H}from"./patternDetection.js";import{detectPattern as v}from"./patternDetection.js";import{detectPayloadPattern as V}from"./patternDetection.js";import{detectDatabase as q}from"./patternDetection.js";import{STACK_NOT_FOUND_PATTERN as B,STACK_FAILED_STATE_PATTERN as J,CDK_NO_STACKS_MATCH as Q,INFRASTRUCTURE_FILENAME as W}from"./constants.js";import{ApplicationError as $,wrapApplicationError as ee}from"./application/index.js";import{FjallStateFileSchema as re,readStateFile as Ee,writeStateFile as ae,createEmptyState as oe,deleteStateFile as Ae,updateTemplateHash as Se,getStateFilePath as pe}from"./FjallState.js";import{STEP_IDS as Pe,STEP_NAMES as _e,INFRASTRUCTURE_STEP_NAMES as Oe,INFRA_STEP_NAME as ie}from"./stepDefinitions.js";export{R as APPLICATION_DEPLOY_ORDER,l as APPLICATION_DESTROY_ORDER,i as APPLICATION_STACKS,$ as ApplicationError,A as CASCADE_ACCOUNT_STATUSES,o as CASCADE_PHASES,Q as CDK_NO_STACKS_MATCH,a as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,E as DEPLOYMENT_EVENT_TYPES,r as DeploymentEventSchema,re as FjallStateFileSchema,W as INFRASTRUCTURE_FILENAME,Oe as INFRASTRUCTURE_STEP_NAMES,ie as INFRA_STEP_NAME,D as OPENNEXT_DEPLOY_ORDER,m as OPENNEXT_DESTROY_ORDER,c as OPENNEXT_PARALLEL_GROUPS,k as OPENNEXT_PATTERNS,N as ORGANISATION_TYPES,n as PARALLEL_DEPLOY_GROUPS,s as PARALLEL_DESTROY_GROUPS,h as PARALLEL_OPERATION_TYPES,_ as ProgressReporter,J as STACK_FAILED_STATE_PATTERN,B as STACK_NOT_FOUND_PATTERN,Pe as STEP_IDS,_e as STEP_NAMES,oe as createEmptyState,Ae as deleteStateFile,H as deriveResourcesFromManifestStacks,q as detectDatabase,v as detectPattern,V as detectPayloadPattern,x as getApplicationDeployOrder,d as getApplicationDestroyOrder,F as getApplicationStackName,y as getApplicationStepId,Y as getApplicationStepName,g as getOrganisationStackName,I as getParallelDeployGroups,f as getParallelDestroyGroups,pe as getStateFilePath,C as isApplicationOperation,U as isApplicationStack,K as isOpenNextPattern,L as isOrganisationOperation,Ee as readStateFile,T as stubCallerIdentity,S as toCascadePhase,M as toPascalCase,Se as updateTemplateHash,ee as wrapApplicationError,ae as writeStateFile};
1
+ import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as A,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as T,DEPLOYMENT_EVENT_STATUS_REASON_MAX as r,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as S,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as _,CASCADE_PHASES as a,CASCADE_ACCOUNT_STATUSES as o,toCascadePhase as p}from"./deploymentEventSchema.js";import{isQuarantineDetail as i,isRetainedBucketsDetail as N}from"./callbacks.js";import{TRAIL_MIGRATION_PHASES as R,TRAIL_MIGRATION_STATUSES as l}from"./events.js";import{stubCallerIdentity as L}from"./deployment/index.js";import{ProgressReporter as n}from"./ProgressEvent.js";import{APPLICATION_STACKS as m,ORGANISATION_TYPES as C,APPLICATION_DEPLOY_ORDER as c,APPLICATION_DESTROY_ORDER as M,OPENNEXT_DEPLOY_ORDER as f,OPENNEXT_DESTROY_ORDER as x,PARALLEL_DEPLOY_GROUPS as Y,PARALLEL_DESTROY_GROUPS as g,OPENNEXT_PARALLEL_GROUPS as F,isApplicationOperation as U,isOrganisationOperation as d,getParallelDeployGroups as G,getParallelDestroyGroups as u,getApplicationDeployOrder as y,getApplicationDestroyOrder as X,getApplicationStackName as h,getOrganisationStackName as k,isApplicationStack as K,getApplicationStepName as V,getApplicationStepId as H,toPascalCase as v}from"./operations.js";import{PARALLEL_OPERATION_TYPES as b}from"./deployment/index.js";import{isOpenNextPattern as B,OPENNEXT_PATTERNS as Q}from"./patternTypes.js";import{deriveResourcesFromManifestStacks as z}from"./patternDetection.js";import{STACK_NOT_FOUND_PATTERN as W,STACK_FAILED_STATE_PATTERN as Z,CDK_NO_STACKS_MATCH as $,INFRASTRUCTURE_FILENAME as ee}from"./constants.js";import{ApplicationError as te,wrapApplicationError as Ae}from"./application/index.js";import{FjallStateFileSchema as re,readStateFile as Se,writeStateFile as _e,createEmptyState as ae,deleteStateFile as oe,updateTemplateHash as pe,getStateFilePath as Oe,regionSuffix as ie}from"./FjallState.js";import{STEP_IDS as Pe,STEP_NAMES as Re,INFRASTRUCTURE_STEP_NAMES as le,INFRA_STEP_NAME as De}from"./stepDefinitions.js";export{c as APPLICATION_DEPLOY_ORDER,M as APPLICATION_DESTROY_ORDER,m as APPLICATION_STACKS,te as ApplicationError,o as CASCADE_ACCOUNT_STATUSES,a as CASCADE_PHASES,$ as CDK_NO_STACKS_MATCH,S as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,T as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,r as DEPLOYMENT_EVENT_STATUS_REASON_MAX,_ as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,A as DEPLOYMENT_EVENT_TYPES,t as DeploymentEventSchema,re as FjallStateFileSchema,ee as INFRASTRUCTURE_FILENAME,le as INFRASTRUCTURE_STEP_NAMES,De as INFRA_STEP_NAME,f as OPENNEXT_DEPLOY_ORDER,x as OPENNEXT_DESTROY_ORDER,F as OPENNEXT_PARALLEL_GROUPS,Q as OPENNEXT_PATTERNS,C as ORGANISATION_TYPES,Y as PARALLEL_DEPLOY_GROUPS,g as PARALLEL_DESTROY_GROUPS,b as PARALLEL_OPERATION_TYPES,n as ProgressReporter,Z as STACK_FAILED_STATE_PATTERN,W as STACK_NOT_FOUND_PATTERN,Pe as STEP_IDS,Re as STEP_NAMES,R as TRAIL_MIGRATION_PHASES,l as TRAIL_MIGRATION_STATUSES,ae as createEmptyState,oe as deleteStateFile,z as deriveResourcesFromManifestStacks,y as getApplicationDeployOrder,X as getApplicationDestroyOrder,h as getApplicationStackName,H as getApplicationStepId,V as getApplicationStepName,k as getOrganisationStackName,G as getParallelDeployGroups,u as getParallelDestroyGroups,Oe as getStateFilePath,U as isApplicationOperation,K as isApplicationStack,B as isOpenNextPattern,d as isOrganisationOperation,i as isQuarantineDetail,N as isRetainedBucketsDetail,Se as readStateFile,ie as regionSuffix,L as stubCallerIdentity,p as toCascadePhase,v as toPascalCase,pe as updateTemplateHash,Ae as wrapApplicationError,_e as writeStateFile};
@@ -8,8 +8,8 @@
8
8
  * Passed to CDK via -c orgConfig=<json> context at synthesis time.
9
9
  * See: investigations/2026-03-16-config-split-investigation.md
10
10
  */
11
- import type { ProviderAccount, SSOSession } from "@fjall/util/config";
12
- export type { ProviderAccount, SSOSession };
11
+ import type { ProviderAccount, RootAccessManagementMode, SSOSession } from "@fjall/util/config";
12
+ export type { ProviderAccount, RootAccessManagementMode, SSOSession };
13
13
  export interface OrgConfig {
14
14
  providerAccounts: ProviderAccount[];
15
15
  primaryRegion?: string;
@@ -17,4 +17,10 @@ export interface OrgConfig {
17
17
  disasterRecoveryRegion?: string;
18
18
  rootOidcRoleArn?: string;
19
19
  ssoSessions?: Record<string, SSOSession>;
20
+ /**
21
+ * Centralised root-access opt-out. Absent ⇒ default-on ("centralised");
22
+ * "off" maps to OrgSetupConfig.skipRootAccessManagement at the adapter
23
+ * boundary — the engine never sees this union.
24
+ */
25
+ rootAccessManagement?: RootAccessManagementMode;
20
26
  }
@@ -49,6 +49,12 @@ export interface DeployParams {
49
49
  * If omitted, the domains cascade phase is skipped.
50
50
  */
51
51
  domainProvider?: DomainDeployProvider;
52
+ /**
53
+ * Caller shutdown signal. Long-running SDK probes (org-trail delivery
54
+ * verification, member-trail cleanup) compose this with their own
55
+ * per-request timeouts so SIGTERM is not stalled by an in-flight call.
56
+ */
57
+ abortSignal?: AbortSignal;
52
58
  }
53
59
  export interface DeployOptions {
54
60
  skipConfirmation?: boolean;
@@ -66,6 +72,11 @@ export interface DeployOptions {
66
72
  serviceName?: string;
67
73
  /** Skip the pre-rollout migrations RunTask. Honoured by the code-only orchestrator. */
68
74
  skipMigrations?: boolean;
75
+ /**
76
+ * Skip the pre-deploy TARGET_READINESS probe. The step still emits and
77
+ * completes as "skipped" so the bypass is recorded in output (AC2b.3).
78
+ */
79
+ skipReadinessCheck?: boolean;
69
80
  /**
70
81
  * Roll forward/back to an existing image tag. When set, the orchestrator skips
71
82
  * build + push and rolls ECS to `<repo>:<imageTag>`. Implies `deployOnly`.
@@ -123,6 +134,13 @@ export interface DestroyParams {
123
134
  * Worker: provide this from DB, omit apiClient.
124
135
  */
125
136
  identity?: DeployIdentity;
137
+ /**
138
+ * Caller shutdown signal. Stack-cleanup probes, bucket pre-empty/orphan
139
+ * sweeps, and the failed-stack deletion poll compose this with their own
140
+ * per-request timeouts so SIGTERM is not stalled by an in-flight call
141
+ * (mirrors DeployParams.abortSignal).
142
+ */
143
+ abortSignal?: AbortSignal;
126
144
  }
127
145
  export interface DestroyOptions {
128
146
  /** Skip interactive confirmation prompts */
@@ -4,7 +4,6 @@
4
4
  * Pure types and predicates live in patternTypes.ts (browser-safe).
5
5
  * This file contains only functions that require Node fs access.
6
6
  */
7
- import type { PatternType } from "@fjall/generator";
8
7
  export type { OpenNextPattern, AppResourceFlags } from "./patternTypes.js";
9
8
  export { OPENNEXT_PATTERNS, isOpenNextPattern } from "./patternTypes.js";
10
9
  import type { AppResourceFlags } from "./patternTypes.js";
@@ -15,27 +14,3 @@ export declare function deriveResourcesFromManifestStacks(stackNames: string[]):
15
14
  * Returns null if file doesn't exist or can't be read.
16
15
  */
17
16
  export declare function readInfrastructureContent(appPath: string): string | null;
18
- /**
19
- * Detect the application pattern (Payload, Next.js, or none) from infrastructure.ts.
20
- *
21
- * Pattern detection is based on the IaC file (infrastructure.ts), NOT on
22
- * project files like package.json. This ensures accurate detection even
23
- * when multiple apps coexist in the same project directory.
24
- *
25
- * @deprecated Use FrameworkRegistry.resolve() instead. This function is retained
26
- * for backwards compatibility with consumers that have not yet migrated.
27
- *
28
- * @param appPath - The fjall app path (e.g., "fjall/app8" or absolute path)
29
- */
30
- export declare function detectPattern(appPath: string): {
31
- pattern: PatternType | null;
32
- hasDatabase: boolean;
33
- };
34
- /**
35
- * Detect if infrastructure.ts contains a Payload CMS pattern.
36
- */
37
- export declare function detectPayloadPattern(appPath: string): boolean;
38
- /**
39
- * Detect if infrastructure.ts contains a database resource.
40
- */
41
- export declare function detectDatabase(appPath: string): boolean;
@@ -1 +1 @@
1
- import{existsSync as o,readFileSync as i}from"fs";import{join as u}from"path";import{logger as c}from"@fjall/util/logger";import{getErrorMessage as l}from"@fjall/util";import{APPLICATION_STACKS as a}from"./operations.js";import{INFRASTRUCTURE_FILENAME as d}from"./constants.js";import{OPENNEXT_PATTERNS as x,isOpenNextPattern as P}from"./patternTypes.js";function E(e){const t=r=>e.some(n=>n.endsWith(r));return{hasNetwork:t(a.NETWORK),hasCompute:t(a.COMPUTE),hasDatabase:t(a.DATABASE),hasStorage:t(a.STORAGE),hasMessaging:t(a.MESSAGING),hasCdn:t(a.CDN)}}function f(e){try{const t=u(e,d);return o(t)?i(t,"utf-8"):null}catch(t){return c.debug("patternDetection","Failed to read infrastructure file",{appPath:e,error:l(t)}),null}}function s(e){const t=f(e);if(!t)return{pattern:null,hasDatabase:!1};if(t.includes("PatternFactory")){if(t.includes('type: "payload"'))return{pattern:"payload",hasDatabase:!0};if(t.includes('type: "nextjs"'))return{pattern:"nextjs",hasDatabase:t.includes("DatabaseFactory.build(")||t.includes("database:")}}return{pattern:null,hasDatabase:t.includes("DatabaseFactory.build(")}}function S(e){const{pattern:t}=s(e);return t==="payload"}function A(e){const{hasDatabase:t}=s(e);return t}export{x as OPENNEXT_PATTERNS,E as deriveResourcesFromManifestStacks,A as detectDatabase,s as detectPattern,S as detectPayloadPattern,P as isOpenNextPattern,f as readInfrastructureContent};
1
+ import{existsSync as s,readFileSync as a}from"fs";import{join as i}from"path";import{logger as f}from"@fjall/util/logger";import{getErrorMessage as m}from"@fjall/util";import{APPLICATION_STACKS as e}from"./operations.js";import{INFRASTRUCTURE_FILENAME as u}from"./constants.js";import{OPENNEXT_PATTERNS as g,isOpenNextPattern as C}from"./patternTypes.js";function p(t){const r=o=>t.some(n=>n.endsWith(o));return{hasNetwork:r(e.NETWORK),hasCompute:r(e.COMPUTE),hasDatabase:r(e.DATABASE),hasStorage:r(e.STORAGE),hasMessaging:r(e.MESSAGING),hasCdn:r(e.CDN)}}function h(t){try{const r=i(t,u);return s(r)?a(r,"utf-8"):null}catch(r){return f.debug("patternDetection","Failed to read infrastructure file",{appPath:t,error:m(r)}),null}}export{g as OPENNEXT_PATTERNS,p as deriveResourcesFromManifestStacks,C as isOpenNextPattern,h as readInfrastructureContent};
@@ -15,6 +15,7 @@ import type { AppResourceFlags } from "./patternTypes.js";
15
15
  export declare const STEP_IDS: {
16
16
  readonly AUTH: "auth";
17
17
  readonly DETECT_CONFIG: "detect-config";
18
+ readonly TARGET_READINESS: "target-readiness";
18
19
  readonly BOOTSTRAP: "bootstrap";
19
20
  readonly CFN_CHECK: "cfn-check";
20
21
  readonly DIFF: "diff";
@@ -71,6 +72,7 @@ export declare const STEP_NAMES: {
71
72
  readonly AUTH: "Authenticating with AWS";
72
73
  readonly PREPARE_DEPLOY: "Preparing deployment";
73
74
  readonly PREPARE_DESTROY: "Preparing destruction";
75
+ readonly TARGET_READINESS: "Verifying target readiness";
74
76
  readonly BOOTSTRAP: "Bootstrapping AWS environment";
75
77
  readonly CHECK_INFRA_STATE: "Checking infrastructure state";
76
78
  readonly ORG_SETUP: "Configuring organisation";
@@ -1 +1 @@
1
- const E={AUTH:"auth",DETECT_CONFIG:"detect-config",BOOTSTRAP:"bootstrap",CFN_CHECK:"cfn-check",DIFF:"diff",DEPLOY:"deploy",DESTROY:"destroy",VERIFY:"verify",CDK_SYNTH:"cdk-synth",DOCKER_OPERATIONS:"docker-operations",ECR_INIT:"ecr-init",DOCKER_DEPLOY:"docker-deploy",TAG_ECR_IMAGES:"tag-ecr-images",ORG_SETUP:"org-setup",ORG_ENSURE:"org-ensure",ORG_POLICY_TYPES:"policy-types",ORG_SERVICE_ACCESS:"service-access",ORG_CREATE_ACCOUNTS:"create-accounts",ORG_ENSURE_OUS:"ensure-ous",ORG_PLACE_ACCOUNTS:"place-accounts",IDENTITY_CENTRE:"identity-centre",ORG_ACCOUNTS:"accounts",ORG_COST_TAGS:"cost-tags",ORG_PROFILES:"profiles",PREPARE:"prepare",PREPARE_ENVIRONMENT:"prepare-environment",PLATFORM_ACCOUNT:"platform-account",ACCOUNT_CONTEXT:"account-context",CONNECT:"connect",MONITORING:"monitoring",ORG_DEPLOY:"organisation-deploy",ORG_DESTROY:"organisation-destroy",CASCADE_PLATFORM:"cascade-platform",CASCADE_DOMAINS:"cascade-domains",CASCADE_ACCOUNTS:"cascade-accounts",NETWORK:"network",STORAGE:"storage",MESSAGING:"messaging",DATABASE:"database",COMPUTE:"compute",CDN:"cdn",NETWORK_DESTROY:"network-destroy",STORAGE_DESTROY:"storage-destroy",MESSAGING_DESTROY:"messaging-destroy",DATABASE_DESTROY:"database-destroy",COMPUTE_DESTROY:"compute-destroy",CDN_DESTROY:"cdn-destroy"},t={AUTH:"Authenticating with AWS",PREPARE_DEPLOY:"Preparing deployment",PREPARE_DESTROY:"Preparing destruction",BOOTSTRAP:"Bootstrapping AWS environment",CHECK_INFRA_STATE:"Checking infrastructure state",ORG_SETUP:"Configuring organisation",ORG_DEPLOY:"Deploying organisation",CASCADE_PLATFORM:"Deploying platform",CASCADE_ACCOUNTS:"Deploying accounts"},e=["Connect securely","Prepare environment","Deploy infrastructure","Enable monitoring"],o={CONNECT:e[0],PREPARE:e[1],DEPLOY:e[2],MONITORING:e[3]};export{e as INFRASTRUCTURE_STEP_NAMES,o as INFRA_STEP_NAME,E as STEP_IDS,t as STEP_NAMES};
1
+ const E={AUTH:"auth",DETECT_CONFIG:"detect-config",TARGET_READINESS:"target-readiness",BOOTSTRAP:"bootstrap",CFN_CHECK:"cfn-check",DIFF:"diff",DEPLOY:"deploy",DESTROY:"destroy",VERIFY:"verify",CDK_SYNTH:"cdk-synth",DOCKER_OPERATIONS:"docker-operations",ECR_INIT:"ecr-init",DOCKER_DEPLOY:"docker-deploy",TAG_ECR_IMAGES:"tag-ecr-images",ORG_SETUP:"org-setup",ORG_ENSURE:"org-ensure",ORG_POLICY_TYPES:"policy-types",ORG_SERVICE_ACCESS:"service-access",ORG_CREATE_ACCOUNTS:"create-accounts",ORG_ENSURE_OUS:"ensure-ous",ORG_PLACE_ACCOUNTS:"place-accounts",IDENTITY_CENTRE:"identity-centre",ORG_ACCOUNTS:"accounts",ORG_COST_TAGS:"cost-tags",ORG_PROFILES:"profiles",PREPARE:"prepare",PREPARE_ENVIRONMENT:"prepare-environment",PLATFORM_ACCOUNT:"platform-account",ACCOUNT_CONTEXT:"account-context",CONNECT:"connect",MONITORING:"monitoring",ORG_DEPLOY:"organisation-deploy",ORG_DESTROY:"organisation-destroy",CASCADE_PLATFORM:"cascade-platform",CASCADE_DOMAINS:"cascade-domains",CASCADE_ACCOUNTS:"cascade-accounts",NETWORK:"network",STORAGE:"storage",MESSAGING:"messaging",DATABASE:"database",COMPUTE:"compute",CDN:"cdn",NETWORK_DESTROY:"network-destroy",STORAGE_DESTROY:"storage-destroy",MESSAGING_DESTROY:"messaging-destroy",DATABASE_DESTROY:"database-destroy",COMPUTE_DESTROY:"compute-destroy",CDN_DESTROY:"cdn-destroy"},t={AUTH:"Authenticating with AWS",PREPARE_DEPLOY:"Preparing deployment",PREPARE_DESTROY:"Preparing destruction",TARGET_READINESS:"Verifying target readiness",BOOTSTRAP:"Bootstrapping AWS environment",CHECK_INFRA_STATE:"Checking infrastructure state",ORG_SETUP:"Configuring organisation",ORG_DEPLOY:"Deploying organisation",CASCADE_PLATFORM:"Deploying platform",CASCADE_ACCOUNTS:"Deploying accounts"},e=["Connect securely","Prepare environment","Deploy infrastructure","Enable monitoring"],o={CONNECT:e[0],PREPARE:e[1],DEPLOY:e[2],MONITORING:e[3]};export{e as INFRASTRUCTURE_STEP_NAMES,o as INFRA_STEP_NAME,E as STEP_IDS,t as STEP_NAMES};
@@ -1,4 +1,5 @@
1
1
  export { DANGEROUS_ENV_VARS, filterDangerousEnvVars, maskSensitiveOutput, parseShellArgs, sleep, singleton } from "@fjall/util";
2
2
  export { hasDockerfile } from "./dockerfileDetection.js";
3
+ export { sleepAbortable } from "./sleepAbortable.js";
3
4
  export { createSequencedCallbacks } from "./sequencedCallbacks.js";
4
5
  export type { CallbackMetadata, SequencedCallbackEvent, SequencedCallbacksResult } from "./sequencedCallbacks.js";
@@ -1 +1 @@
1
- import{DANGEROUS_ENV_VARS as s,filterDangerousEnvVars as o,maskSensitiveOutput as t,parseShellArgs as a,sleep as l,singleton as n}from"@fjall/util";import{hasDockerfile as f}from"./dockerfileDetection.js";import{createSequencedCallbacks as S}from"./sequencedCallbacks.js";export{s as DANGEROUS_ENV_VARS,S as createSequencedCallbacks,o as filterDangerousEnvVars,f as hasDockerfile,t as maskSensitiveOutput,a as parseShellArgs,n as singleton,l as sleep};
1
+ import{DANGEROUS_ENV_VARS as o,filterDangerousEnvVars as s,maskSensitiveOutput as t,parseShellArgs as l,sleep as a,singleton as p}from"@fjall/util";import{hasDockerfile as n}from"./dockerfileDetection.js";import{sleepAbortable as m}from"./sleepAbortable.js";import{createSequencedCallbacks as c}from"./sequencedCallbacks.js";export{o as DANGEROUS_ENV_VARS,c as createSequencedCallbacks,s as filterDangerousEnvVars,n as hasDockerfile,t as maskSensitiveOutput,l as parseShellArgs,p as singleton,a as sleep,m as sleepAbortable};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Promise-based sleep that short-circuits when the supplied abort signal
3
+ * fires. Long-running poll loops MUST use this for inter-poll delays so a
4
+ * shutdown signal (e.g. SIGTERM in the webapp deployment worker) does not
5
+ * stall for the full sleep duration. Resolves (never rejects) on abort;
6
+ * callers check `signal.aborted` after waking.
7
+ */
8
+ export declare function sleepAbortable(ms: number, signal?: AbortSignal): Promise<void>;
@@ -0,0 +1 @@
1
+ function i(o,e){return e?.aborted===!0?Promise.resolve():new Promise(t=>{const n=setTimeout(()=>{e?.removeEventListener("abort",r),t()},o),r=()=>{clearTimeout(n),t()};e?.addEventListener("abort",r,{once:!0})})}export{i as sleepAbortable};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/deploy-core",
3
- "version": "2.12.0",
3
+ "version": "2.14.0",
4
4
  "description": "Shared deployment engine for Fjall — used by CLI and webapp worker",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -65,17 +65,21 @@
65
65
  "dependencies": {
66
66
  "@aws-sdk/client-backup": "^3.1038.0",
67
67
  "@aws-sdk/client-cloudformation": "^3.1038.0",
68
+ "@aws-sdk/client-cloudtrail": "^3.1065.0",
68
69
  "@aws-sdk/client-cost-explorer": "^3.1038.0",
69
70
  "@aws-sdk/client-ec2": "^3.1038.0",
70
71
  "@aws-sdk/client-ecr": "^3.1039.0",
72
+ "@aws-sdk/client-iam": "^3.1038.0",
73
+ "@aws-sdk/client-kms": "^3.1065.0",
71
74
  "@aws-sdk/client-organizations": "^3.1038.0",
72
75
  "@aws-sdk/client-ram": "^3.1038.0",
73
76
  "@aws-sdk/client-s3": "^3.1038.0",
74
77
  "@aws-sdk/client-secrets-manager": "^3.1038.0",
78
+ "@aws-sdk/client-sqs": "^3.1067.0",
75
79
  "@aws-sdk/client-sso-admin": "^3.1038.0",
76
80
  "@aws-sdk/client-sts": "^3.1038.0",
77
- "@fjall/generator": "^2.12.0",
78
- "@fjall/util": "^2.12.0",
81
+ "@fjall/generator": "^2.14.0",
82
+ "@fjall/util": "^2.14.0",
79
83
  "@smithy/node-http-handler": "^4.6.1",
80
84
  "tsx": "^4.21.0",
81
85
  "zod": "^4.4.3"
@@ -84,5 +88,5 @@
84
88
  "@types/node": "^25.6.0",
85
89
  "vitest": "^4.1.5"
86
90
  },
87
- "gitHead": "dca39a47da956d3d94c689dd782fe285d711d25e"
91
+ "gitHead": "ce434478f9e3d5e5ccf979c152a237c81e4acee5"
88
92
  }