@fjall/deploy-core 12.2.0 → 12.3.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.
@@ -9,7 +9,7 @@
9
9
  "package.json",
10
10
  "tsconfig.json"
11
11
  ],
12
- "hash": "6b78e1eebed9bece06d3bfb1f9fce5f4eb011cfe37a53d0e48fdd6ebe1cf33e0",
12
+ "hash": "65d954316a08e048d0759bd92b4e8ff9da327e6092db2fb75d99fe52a88fef92",
13
13
  "files": {
14
14
  "src/__test-utils__/awsMockHelpers.ts": "fea371c1b1869678",
15
15
  "src/__test-utils__/index.ts": "e03cf35821157dc4",
@@ -52,7 +52,7 @@
52
52
  "src/aws/utils/regions.ts": "3a5191f4d2242a60",
53
53
  "src/aws/utils/stackStatus.ts": "55fb23ba5514bc13",
54
54
  "src/events/index.ts": "e55c022f0d9013e6",
55
- "src/index.ts": "28221a2c59ab861d",
55
+ "src/index.ts": "6e4df366dcde403c",
56
56
  "src/orchestration/activeDeploymentGuard.ts": "e8dde742c00ea728",
57
57
  "src/orchestration/application/applicationDeploy.ts": "867232cbc981906c",
58
58
  "src/orchestration/application/applicationDeployHelpers.ts": "bca833cc04f0b4c5",
@@ -100,15 +100,15 @@
100
100
  "src/orchestration/builders/index.ts": "3b0b2492294c62db",
101
101
  "src/orchestration/builders/openNextBuilder.ts": "7416a37e19380660",
102
102
  "src/orchestration/builders/staticSiteBuilder.ts": "a0403be58052310f",
103
- "src/orchestration/contextHelpers.ts": "4f8e7903cb79d9fe",
104
- "src/orchestration/deploy.ts": "5cbdc229366ea1e6",
103
+ "src/orchestration/contextHelpers.ts": "0dd4f0347b517d61",
104
+ "src/orchestration/deploy.ts": "3e277c099ebbb6be",
105
105
  "src/orchestration/deployEnvironment.ts": "acfddd575949b7ca",
106
106
  "src/orchestration/destroy.ts": "b6da154984e63a8d",
107
107
  "src/orchestration/dockerBuildParamsKeys.ts": "ac3d6ecd24d68792",
108
108
  "src/orchestration/dockerInterface.ts": "f2efc8a98d3b3d65",
109
109
  "src/orchestration/domain/caaPreflight.ts": "4a9ab5bd9567fb41",
110
- "src/orchestration/domain/delegatedDomainDeploy.ts": "832c278797908795",
111
- "src/orchestration/domain/delegationDestroyMirror.ts": "40323fffaece2300",
110
+ "src/orchestration/domain/delegatedDomainDeploy.ts": "b5e5c2db59250b8a",
111
+ "src/orchestration/domain/delegationDestroyMirror.ts": "939f6c3cc3293d8b",
112
112
  "src/orchestration/domain/index.ts": "cd2f98114a42c758",
113
113
  "src/orchestration/domain/nsPropagationGate.ts": "c7a443e7048d4430",
114
114
  "src/orchestration/domain/route53Delegation.ts": "a7149a0542e4d185",
@@ -128,8 +128,8 @@
128
128
  "src/orchestration/index.ts": "0b230a38e1ef50d2",
129
129
  "src/orchestration/manifestSecretParser.ts": "c5576bd88a3652f8",
130
130
  "src/orchestration/organisation/accountsConfig.ts": "a55a3306564e7b2f",
131
- "src/orchestration/organisation/cascadeDestroyHelpers.ts": "1dddeae830fbb549",
132
- "src/orchestration/organisation/cascadeHelpers.ts": "97f7f12727b8c0ed",
131
+ "src/orchestration/organisation/cascadeDestroyHelpers.ts": "7f1927a00ed24767",
132
+ "src/orchestration/organisation/cascadeHelpers.ts": "7b000925ae82e1f1",
133
133
  "src/orchestration/organisation/cascadeSummary.ts": "335be9649cea0626",
134
134
  "src/orchestration/organisation/organisationDeploy.ts": "f3fad626230d8a16",
135
135
  "src/orchestration/organisation/organisationDestroy.ts": "06076a7e76345854",
@@ -137,9 +137,9 @@
137
137
  "src/orchestration/organisation/reconcileProviderAccounts.ts": "91920b2ed61dd811",
138
138
  "src/orchestration/organisationDeploy/cascadeExecution.ts": "ebc32ef8857d8037",
139
139
  "src/orchestration/organisationDeploy/infraSteps.ts": "53880cef5020dd04",
140
- "src/orchestration/organisationDeploy/orgCascadeDeploy.ts": "97a85277580be283",
140
+ "src/orchestration/organisationDeploy/orgCascadeDeploy.ts": "b38841dd8a84a8a0",
141
141
  "src/orchestration/organisationDeploy/orgContext.ts": "635f429a7cbb7c32",
142
- "src/orchestration/organisationDeploy/resolveCascadeAccounts.ts": "1804c62e365a881a",
142
+ "src/orchestration/organisationDeploy/resolveCascadeAccounts.ts": "9882c235a302cbf9",
143
143
  "src/orchestration/organisationDeploy/singleComponentDeploy.ts": "3e35f43f3a59097c",
144
144
  "src/orchestration/organisationDeploy/trailReconciliation.ts": "7aefb6417c77280b",
145
145
  "src/orchestration/probes/deleteBlockProbes.ts": "fa3111386026ca6e",
@@ -172,7 +172,7 @@
172
172
  "src/orchestration/stackCleanup/stackResources.ts": "13ffd8bfaad6baec",
173
173
  "src/orchestration/stepLifecycle.ts": "71722e3e50b19ee6",
174
174
  "src/orchestration/trailMigration/memberTrailCleanup.ts": "469e4390c18e45a8",
175
- "src/orchestration/trailMigration/trailMigration.ts": "b52a84a694c81f2d",
175
+ "src/orchestration/trailMigration/trailMigration.ts": "a8e3710d5c2fbff9",
176
176
  "src/orchestration/unlock/bucketPolicyTriage.ts": "a40d55c0fc5ba63e",
177
177
  "src/orchestration/unlock/restoreAndReconcileQuarantinedBucket.ts": "c534511ed49952ad",
178
178
  "src/orchestration/unlock/restoreBucketPolicy.ts": "f266285ffacf3cf6",
@@ -190,7 +190,7 @@
190
190
  "src/services/infrastructure/CdkEventMonitoring.ts": "f172272948a5db40",
191
191
  "src/services/infrastructure/CdkOutputAnalyser.ts": "2e7cb06b6554de84",
192
192
  "src/services/infrastructure/CdkOutputParser.ts": "eed9f3475324118e",
193
- "src/services/infrastructure/CdkProcessManager.ts": "8e1237546cebb2a4",
193
+ "src/services/infrastructure/CdkProcessManager.ts": "165c97be53d6de8f",
194
194
  "src/services/infrastructure/CdkService.ts": "954ac16a4c646912",
195
195
  "src/services/infrastructure/CdkServiceTypes.ts": "c4f3075238952728",
196
196
  "src/services/infrastructure/CfnRegistryService.ts": "bd4f57d97982cdda",
@@ -256,15 +256,16 @@
256
256
  "src/types/remediation.ts": "0e1138f0c8fdc6bf",
257
257
  "src/types/stepDefinitions.ts": "a5e2aa03b15011b4",
258
258
  "src/types/validation.ts": "44aa473ec0e25dc4",
259
+ "src/util/diagnosticScopes.ts": "8a6ba150da18c6cb",
259
260
  "src/util/dockerfileDetection.ts": "c407ab8208fb65ec",
260
261
  "src/util/index.ts": "6fcf776825c4518e",
261
262
  "src/util/sequencedCallbacks.ts": "e0eb541cff459083",
262
263
  "src/util/sleepAbortable.ts": "f9cac3bf8a79a476",
263
264
  "src/version.ts": "1811a4475823b27e",
264
265
  "../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
265
- "package.json": "3ec136a748cfb286",
266
+ "package.json": "07999f2f0e75d9f2",
266
267
  "tsconfig.json": "1929cf3f99fe9b1e"
267
268
  },
268
- "outputHash": "2f1528573ef4691ce96b7659a55d94cd328f8eb2ebe984fae8b9fdea749c6b87",
269
- "outputFileCount": 493
269
+ "outputHash": "79740bb131a738975638440ec19c20462959edc87151bb81517329ab31053cab",
270
+ "outputFileCount": 495
270
271
  }
package/dist/.minified CHANGED
@@ -1 +1 @@
1
- 246 files minified at 2026-08-15T22:07:59.770Z
1
+ 247 files minified at 2026-08-16T01:19:59.801Z
@@ -54,6 +54,8 @@ export { type Result, success, failure, isSuccess, isFailure } from "@fjall/gene
54
54
  export { deploy } from "./orchestration/index.js";
55
55
  export { destroy } from "./orchestration/index.js";
56
56
  export { buildParamsContext } from "./orchestration/contextHelpers.js";
57
+ export { emitStepWarnings, emitWarningEvent } from "./orchestration/contextHelpers.js";
58
+ export { ENGINE_DIAGNOSTIC_SCOPE } from "./util/diagnosticScopes.js";
57
59
  export { restart, probeSecretsDrift, probeServiceDeploymentStatus, computeSecretsDrift, deriveStaleParameters, extractConsumedSsmParameters } from "./orchestration/index.js";
58
60
  export type { RestartParams, RestartResult, SecretsDriftProbeParams, ServiceDeploymentStatus, ApplicationServiceStatus, ApplicationSecretsDrift, ServiceSecretsDrift, StaleParameter } from "./orchestration/index.js";
59
61
  export { partitionAccounts } from "./orchestration/index.js";
package/dist/src/index.js CHANGED
@@ -1 +1 @@
1
- import{DEPLOY_CORE_VERSION_GLOBAL as t}from"./version.js";import{DeploymentEventSchema as i,DEPLOYMENT_EVENT_TYPES as a,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as n,DEPLOYMENT_EVENT_STATUS_REASON_MAX as s,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as E,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as c,DEPLOYMENT_ERROR_MESSAGE_MAX as S,CASCADE_PHASES as l,CASCADE_ACCOUNT_STATUSES as _,clampDeploymentEventStrings as A,truncateUtf16Safe as p}from"./types/index.js";import{DeployEventSchema as T,StepProgressSchema as m,DeployResourceSchema as d,PlanChangeSchema as u,PlanPropertyChangeSchema as D,ChangeCountsSchema as P,DEPLOY_EVENT_CONTRACT as O,DEPLOY_EVENT_CONTRACT_MAJOR as f,DEPLOY_EVENT_CONTRACT_MINOR as C,SUPPORTED_CONTRACT_MARKERS as N,DEPLOY_EVENT_ID_MAX as I,DEPLOY_EVENT_NAME_MAX as L,DEPLOY_EVENT_MESSAGE_MAX as g,DEPLOY_EVENT_STATUS_REASON_MAX as y,DEPLOY_EVENT_ERROR_MESSAGE_MAX as F,DEPLOY_EVENT_TRAIL_DETAIL_MAX as h,DEPLOY_EVENT_OUTPUT_MAX as x,DEPLOY_EVENT_ARN_MAX as M,DEPLOY_EVENT_URL_MAX as U,STEP_COMPLETE_STATUSES as v,LOG_LEVELS as b,STACK_CLEANUP_PHASES as k,CASCADE_ACCOUNT_PHASES as Y,DEPLOY_RESULTS as V,DETECTION_PHASES as G,PHASE_STATUSES as B,BUILDERS as K,CASCADE_OUTCOME_RESULTS as X,PLAN_ACTIONS as H,REPLACEMENT_MODES as w,APPROVAL_KINDS as J,APPROVAL_DECISIONS as Q,ALL_PROGRESS_KINDS as j,createDeployEmitter as W,parseDeployEvent as Z,parseDeployContractVersion as q}from"./types/index.js";import{SimpleAwsProvider as $}from"./aws/index.js";import{checkTargetReadiness as re,describeTargetReadinessReason as te,buildTargetUnreadyAdvisory as oe,buildTargetSetUnreadyAdvisory as ie,probeAccountStackExists as ae}from"./aws/index.js";import{checkRegionEnabled as se,regionDisabledMessage as Ee}from"./aws/index.js";import{ensureOrganisationExists as Se,describeOrganisation as le,enablePolicyTypes as _e,enableServiceAccess as Ae,SERVICE_PRINCIPALS as pe,enableRamSharing as Re,activateTrustedAccess as Te,enableIpamDelegatedAdmin as me,updateBackupGlobalSettings as de,listAccounts as ue,findAccount as De,createAccount as Pe,ensureOrganisationalUnitsExist as Oe,placeAccountsInOUs as fe,buildAccountToOUMap as Ce,findDevelopmentOuId as Ne,activateCostAllocationTags as Ie,checkIdentityCentreStatus as Le,snapshotIdentityCentre as ge,composeSdkAbortSignal as ye,extractErrorName as Fe,isAborted as he,DEFAULT_MAX_PAGES as xe,IDENTITY_STORE_PAGE_SIZE as Me,drainPages as Ue,isOULeaf as ve,registerSecurityDelegates as be,SECURITY_SERVICE_PRINCIPALS as ke,enableCentralisedRootAccess as Ye,ROOT_ACCESS_FEATURES as Ve,RootAccessEnablementError as Ge}from"./aws/index.js";import{STEP_IDS as Ke,STEP_NAMES as Xe,INFRASTRUCTURE_STEP_NAMES as He,INFRA_STEP_NAME as we}from"./types/index.js";import{RemediationVerbSchema as Qe,REMEDIATION_VERB_GLOSS as je,IDENTITY_PIN_SLOT_SWAP_GLOSS as We,DestructionFindingSchema as Ze,DestructionTicketResourceSchema as qe,DestructionTicketSchema as ze,DestructionConsentSchema as $e,DestructionOutcomeSchema as er,DESTRUCTION_FINDINGS as rr,CONSENT_VERDICTS as tr,TICKET_VERDICT_SOURCES as or,TicketVerdictSourceSchema as ir}from"./types/index.js";import{DRIFT_VERDICTS as nr,DriftVerdictSchema as sr,DriftSuspectSchema as Er,DriftFindingSchema as cr,DriftJournalRecordSchema as Sr,verbsForDriftVerdict as lr}from"./types/index.js";import{REMEDIATION_PHASES as Ar,RemediationPhaseSchema as pr,RemediationTargetSchema as Rr,RemediationFlipProofSchema as Tr,RemediationJournalRecordSchema as mr,RemediationVerbWithSurgerySchema as dr,remediationPhaseRank as ur,remediationPlaceholderPhysicalId as Dr,isRemediationPlaceholderPhysicalId as Pr}from"./types/index.js";import{ProgressReporter as fr,APPLICATION_STACKS as Cr,ORGANISATION_TYPES as Nr,APPLICATION_DEPLOY_ORDER as Ir,APPLICATION_DESTROY_ORDER as Lr,OPENNEXT_DEPLOY_ORDER as gr,OPENNEXT_DESTROY_ORDER as yr,PARALLEL_DEPLOY_GROUPS as Fr,PARALLEL_DESTROY_GROUPS as hr,OPENNEXT_PARALLEL_GROUPS as xr,PARALLEL_OPERATION_TYPES as Mr,isApplicationOperation as Ur,isOrganisationOperation as vr,getParallelDeployGroups as br,getParallelDestroyGroups as kr,getApplicationDeployOrder as Yr,getApplicationDestroyOrder as Vr,getApplicationStackName as Gr,getOrganisationStackName as Br,isApplicationStack as Kr,isQuarantineDetail as Xr,isRetainedBucketsDetail as Hr,getApplicationStepName as wr,getApplicationStepId as Jr,toPascalCase as Qr,isOpenNextPattern as jr,OPENNEXT_PATTERNS as Wr,STACK_NOT_FOUND_PATTERN as Zr,STACK_FAILED_STATE_PATTERN as qr,CDK_NO_STACKS_MATCH as zr,INFRASTRUCTURE_FILENAME as $r,ApplicationError as et,wrapApplicationError as rt,stubCallerIdentity as tt}from"./types/index.js";import{deriveResourcesFromManifestStacks as it}from"./types/detection/patternDetection.js";import{FjallStateFileSchema as nt,readStateFile as st,writeStateFile as Et,createEmptyState as ct,deleteStateFile as St,updateTemplateHash as lt,getStateFilePath as _t,regionSuffix as At}from"./types/config/FjallState.js";import{readDomainState as Rt,writeDomainState as Tt,recordDomainDeployState as mt,deleteDomainState as dt,hashDomainDirectory as ut,LEGACY_DOMAIN_STATE_FILENAME as Dt}from"./types/config/DomainState.js";import{CloudFormationEventMonitor as Ot}from"./aws/index.js";import{CdkService as Ct,CdkArgumentBuilder as Nt,CdkProcessManager as It,ensureDependencyIntegrity as Lt,clearDependencyIntegrityCache as gt,DEPENDENCY_SYNC_TIMEOUT_MS as yt,CdkEventMonitor as Ft,startStackMonitoring as ht,DEFAULT_DEPLOY_TIMEOUT_MS as xt,isCdkError as Mt,formatInfrastructureError as Ut,getStructuralHint as vt,getSourceContext as bt,hasCdkDifferences as kt,parseDiffOutput as Yt,CloudFormationService as Vt,CloudFormationError as Gt,EcsService as Bt,EcsError as Kt,EcsServiceResolver as Xt,TemplateHashService as Ht,TemplateHashError as wt,CdkContextBuilder as Jt,emitProgress as Qt,PROGRESS_MESSAGES as jt,parseBuildPhase as Wt,buildStepContextBuildConfig as Zt,convertCloudFormationOutputsToRecord as qt,ApplicationStackService as zt}from"./services/index.js";import{CdkError as eo}from"./types/errors/index.js";import{BaseServiceError as to,ValidationError as oo,AuthError as io,AwsError as ao,DeploymentError as no,NetworkError as so,FileSystemError as Eo,ConfigError as co,toServiceError as So}from"./types/errors/index.js";import{filterDangerousEnvVars as _o,maskSensitiveOutput as Ao,parseShellArgs as po,sleep as Ro}from"@fjall/util";import{artefactOutputKey as mo,DeployModeSchema as uo,ServiceArtefactSchema as Do,ServiceArtefactsSchema as Po}from"@fjall/util";import{hasDockerfile as fo}from"./util/dockerfileDetection.js";import{sleepAbortable as No}from"./util/sleepAbortable.js";import{createSequencedCallbacks as Lo}from"./util/sequencedCallbacks.js";import{fileExists as yo}from"@fjall/util/fsHelpers";import{success as ho,failure as xo,isSuccess as Mo,isFailure as Uo}from"@fjall/generator";import{deploy as bo}from"./orchestration/index.js";import{destroy as Yo}from"./orchestration/index.js";import{buildParamsContext as Go}from"./orchestration/contextHelpers.js";import{restart as Ko,probeSecretsDrift as Xo,probeServiceDeploymentStatus as Ho,computeSecretsDrift as wo,deriveStaleParameters as Jo,extractConsumedSsmParameters as Qo}from"./orchestration/index.js";import{partitionAccounts as Wo}from"./orchestration/index.js";import{buildRegionList as qo,buildAccountRegionPairs as zo,cascadeHomeRegion as $o,cascadeOperationKey as ei}from"./orchestration/index.js";import{projectScalarSummary as ti,projectAccountRows as oi}from"./orchestration/index.js";import{reconcileProviderAccounts as ai,mergeReconciledProviderAccounts as ni}from"./orchestration/index.js";import{decideNextTransition as Ei,reconcileTrailMigration as ci,decommissionMemberTrailStorage as Si,ORG_TRAIL_BUCKET_OUTPUT_KEY as li,TRAIL_BUCKET_OUTPUT_KEY as _i,TRAIL_KEY_ARN_OUTPUT_KEY as Ai}from"./orchestration/index.js";import{classifyDriftFailure as Ri,fetchLastOperationEvents as Ti,DriftProbe as mi,clearDriftSuspects as di,defaultDriftJournalDir as ui,readDriftSuspects as Di,recordDriftSuspects as Pi,detectStackDrift as Oi,runDriftPreFlight as fi,formatDriftPreFlightBlock as Ci,DRIFT_PREFLIGHT_TRIGGER_STATUSES as Ni,DRIFT_PREFLIGHT_BUDGET_MS as Ii,runRoute53RecordPreflight as Li}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as yi,computeRemediationOpId as Fi,defaultRemediationJournalDir as hi,findRemediationJournalByOpId as xi,listActiveRemediationOps as Mi,listActiveRemediationOpsForContext as Ui,readRemediationJournal as vi,sweepExpiredRemediationJournals as bi,writeRemediationJournal as ki,REMEDIATION_JOURNAL_RETENTION_DAYS as Yi,captureRemediationForensics as Vi,defaultRemediationForensicsDir as Gi,applyRetainFlip as Bi,composeFlipCapabilities as Ki,computeTemplateDigest as Xi,deriveRetainFlipTemplate as Hi,findMarkedResourcesByOpId as wi,proveFlipMetadataOnly as Ji,readRetainFlipState as Qi,verifyRetainFlipDiff as ji,FORGET_MARKER_KEY as Wi,FORGET_FLIP_SPEC as Zi,RECREATE_MARKER_KEY as qi,assessForgetResumability as zi,completeForgetAfterConverge as $i,completeForgetAfterDeploy as ea,formatRecreateInFlightCures as ra,partitionPreFlightByRemediation as ta,runForgetSurgery as oa,synthTemplateDeclaresResource as ia,runRecreateSurgery as aa,snapshotPolicyForType as na,SNAPSHOT_CAPABLE_RESOURCE_TYPES as sa,runRecreatePreFlight as Ea,deriveRemovalTemplate as ca,findRemovalDeletionFailures as Sa,findResourcesPresent as la,proveRemovalTargetsOnly as _a,advertisableDriftVerbs as Aa,buildDriftRepairTicket as pa,runDriftRepairGate as Ra,formatPinOutcomeDetail as Ta,pinProbeCoverage as ma,renderPinReportLines as da,runPinRemediation as ua,captureLegacySurfaces as Da,decodeLegacyAnchor as Pa,runIdentitySurfaceGate as Oa,collectIdentityPinCandidates as fa,degradedIdentityPinOutcomes as Ca,renderIdentityPinReportLines as Na,runIdentityPinMigration as Ia,composePostFailureRepairOffer as La,formatDriftRepairOffer as ga,DriftRepairAvailableError as ya,checkDeployPathStackAvailability as Fa,isDeployPathBlockingStatus as ha,StackUnavailableError as xa,assertLeaseBeforeStack as Ma,LeaseDeniedError as Ua}from"./orchestration/index.js";import{unlockBucket as ba,unlockQueue as ka}from"./orchestration/index.js";import{triageBucketPolicy as Va,isEnforceSslStatement as Ga,toResourcePolicyStatements as Ba,restoreBucketPolicy as Ka,synthesiseEnforceSslDocument as Xa,ensureEnforceSsl as Ha,restoreAndReconcileQuarantinedBucket as wa}from"./orchestration/index.js";import{verifyOrgTrailDelivery as Qa}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as Wa,isRootTaskPolicyArn as Za,ROOT_TASK_POLICY_ARNS as qa,MAX_ROOT_SESSION_SECONDS as za}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as en,flattenAccountsToEnvironments as rn,extractAllAccountNames as tn,accountsConfigToOUTree as on,isStringArray as an,isAccountsConfig as nn,isOuOnlyAccountBucket as sn,OU_ONLY_ACCOUNT_BUCKETS as En}from"./orchestration/index.js";import{runOpenNextBuild as Sn}from"./orchestration/index.js";import{runOrganisationSetup as _n,ORG_SETUP_PHASES as An}from"./orchestration/index.js";import{DOMAIN_DELEGATION_ERROR_TYPES as Rn,DomainDelegationError as Tn,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as mn,PUBLIC_DNS_QUERY_TIMEOUT_MS as dn,createPublicResolvers as un,NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS as Dn,NS_PROPAGATION_DEFAULT_INTERVAL_MS as Pn,waitForNsPropagation as On,ACM_CAA_ISSUERS as fn,runCaaPreflight as Cn,deployDelegatedDomain as Nn,CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as In,templateOwnsDelegationRecord as Ln,deleteChildNsFromParent as gn,nsDelegationPhysicalName as yn,runDelegatedDomainDestroy as Fn}from"./orchestration/index.js";import{classifyZoneRecords as xn,buildSatelliteRecordIndex as Mn,createSystemDnsNameProbe as Un,systemDnsNameProbe as vn,normaliseRecordName as bn,isRoute53NameServer as kn,isDelegatedToRoute53 as Yn}from"./orchestration/index.js";import{resolveBuildSecrets as Gn,resolveSecretRefValue as Bn,resolveBuildSecretSessionProvider as Kn,sourcedRefsFromBuildArgs as Xn,resolveBuildArgs as Hn,buildBuildSecretSessionPolicy as wn,buildDeploySessionPolicy as Jn,partitionForRegion as Qn,validateBuildGroup as jn}from"./orchestration/index.js";import{FrameworkRegistry as Zn}from"./orchestration/index.js";import{openNextBuilder as zn,staticSiteBuilder as $n,dockerBuilder as es}from"./orchestration/index.js";import{StepRegistry as ts,getDestroyStepId as os}from"./steps/index.js";import{buildDeployPlan as as,computeDeployPlan as ns,computeAssemblyDigest as ss,digestHead as Es,classifyImpact as cs,derivePropertyChanges as Ss,isDataLoss as ls,isStatefulResourceType as _s,renderPlanSummary as As,renderPlanLines as ps,toWirePlanChanges as Rs,signApprovalToken as Ts,verifyApprovalToken as ms,DEFAULT_APPROVAL_TTL_MS as ds,APPROVAL_TOKEN_PATTERN as us,runApprovalGate as Ds,approvalRefusalReason as Ps}from"./orchestration/index.js";import{runDestructionGate as fs,buildDestructionTicket as Cs,evaluateDestructionConsents as Ns,computeTicketDigest as Is,legalRemediationVerbs as Ls,executableRemediationVerbs as gs,advertisableRemediationVerbs as ys,renderDestructionTicketLines as Fs,renderConsentVerdictLines as hs,loadDeployPlan as xs,createMemoisedPlanLoader as Ms}from"./orchestration/index.js";import{DEPLOYMENT_FAILURE_CLASSIFIER_VERSION as vs,classifyDeployFailure as bs,classifyFromEcsCompletion as ks,classifyFromFailureAnalysis as Ys,classifyUnclassified as Vs}from"./orchestration/failure/classifyFailure.js";import{attachDeploymentFailure as Bs,getDeploymentFailure as Ks}from"./orchestration/failure/deploymentFailureAttachment.js";export{fn as ACM_CAA_ISSUERS,j as ALL_PROGRESS_KINDS,Ir as APPLICATION_DEPLOY_ORDER,Lr as APPLICATION_DESTROY_ORDER,Cr as APPLICATION_STACKS,Q as APPROVAL_DECISIONS,J as APPROVAL_KINDS,us as APPROVAL_TOKEN_PATTERN,et as ApplicationError,zt as ApplicationStackService,io as AuthError,ao as AwsError,K as BUILDERS,to as BaseServiceError,Y as CASCADE_ACCOUNT_PHASES,_ as CASCADE_ACCOUNT_STATUSES,X as CASCADE_OUTCOME_RESULTS,l as CASCADE_PHASES,zr as CDK_NO_STACKS_MATCH,tr as CONSENT_VERDICTS,In as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,Nt as CdkArgumentBuilder,Jt as CdkContextBuilder,eo as CdkError,Ft as CdkEventMonitor,It as CdkProcessManager,Ct as CdkService,P as ChangeCountsSchema,Gt as CloudFormationError,Ot as CloudFormationEventMonitor,Vt as CloudFormationService,co as ConfigError,ds as DEFAULT_APPROVAL_TTL_MS,xt as DEFAULT_DEPLOY_TIMEOUT_MS,xe as DEFAULT_MAX_PAGES,mn as DEFAULT_PUBLIC_RESOLVER_ADDRESSES,yt as DEPENDENCY_SYNC_TIMEOUT_MS,S as DEPLOYMENT_ERROR_MESSAGE_MAX,E as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,n as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,s as DEPLOYMENT_EVENT_STATUS_REASON_MAX,c as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,a as DEPLOYMENT_EVENT_TYPES,vs as DEPLOYMENT_FAILURE_CLASSIFIER_VERSION,t as DEPLOY_CORE_VERSION_GLOBAL,M as DEPLOY_EVENT_ARN_MAX,O as DEPLOY_EVENT_CONTRACT,f as DEPLOY_EVENT_CONTRACT_MAJOR,C as DEPLOY_EVENT_CONTRACT_MINOR,F as DEPLOY_EVENT_ERROR_MESSAGE_MAX,I as DEPLOY_EVENT_ID_MAX,g as DEPLOY_EVENT_MESSAGE_MAX,L as DEPLOY_EVENT_NAME_MAX,x as DEPLOY_EVENT_OUTPUT_MAX,y as DEPLOY_EVENT_STATUS_REASON_MAX,h as DEPLOY_EVENT_TRAIL_DETAIL_MAX,U as DEPLOY_EVENT_URL_MAX,V as DEPLOY_RESULTS,rr as DESTRUCTION_FINDINGS,G as DETECTION_PHASES,Rn as DOMAIN_DELEGATION_ERROR_TYPES,Ii as DRIFT_PREFLIGHT_BUDGET_MS,Ni as DRIFT_PREFLIGHT_TRIGGER_STATUSES,nr as DRIFT_VERDICTS,T as DeployEventSchema,uo as DeployModeSchema,d as DeployResourceSchema,no as DeploymentError,i as DeploymentEventSchema,$e as DestructionConsentSchema,Ze as DestructionFindingSchema,er as DestructionOutcomeSchema,qe as DestructionTicketResourceSchema,ze as DestructionTicketSchema,Tn as DomainDelegationError,cr as DriftFindingSchema,Sr as DriftJournalRecordSchema,mi as DriftProbe,ya as DriftRepairAvailableError,Er as DriftSuspectSchema,sr as DriftVerdictSchema,Kt as EcsError,Bt as EcsService,Xt as EcsServiceResolver,Zi as FORGET_FLIP_SPEC,Wi as FORGET_MARKER_KEY,Eo as FileSystemError,nt as FjallStateFileSchema,Zn as FrameworkRegistry,We as IDENTITY_PIN_SLOT_SWAP_GLOSS,Me as IDENTITY_STORE_PAGE_SIZE,$r as INFRASTRUCTURE_FILENAME,He as INFRASTRUCTURE_STEP_NAMES,we as INFRA_STEP_NAME,Dt as LEGACY_DOMAIN_STATE_FILENAME,b as LOG_LEVELS,Ua as LeaseDeniedError,za as MAX_ROOT_SESSION_SECONDS,Pn as NS_PROPAGATION_DEFAULT_INTERVAL_MS,Dn as NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS,so as NetworkError,gr as OPENNEXT_DEPLOY_ORDER,yr as OPENNEXT_DESTROY_ORDER,xr as OPENNEXT_PARALLEL_GROUPS,Wr as OPENNEXT_PATTERNS,Nr as ORGANISATION_TYPES,An as ORG_SETUP_PHASES,li as ORG_TRAIL_BUCKET_OUTPUT_KEY,En as OU_ONLY_ACCOUNT_BUCKETS,Fr as PARALLEL_DEPLOY_GROUPS,hr as PARALLEL_DESTROY_GROUPS,Mr as PARALLEL_OPERATION_TYPES,B as PHASE_STATUSES,H as PLAN_ACTIONS,jt as PROGRESS_MESSAGES,dn as PUBLIC_DNS_QUERY_TIMEOUT_MS,u as PlanChangeSchema,D as PlanPropertyChangeSchema,fr as ProgressReporter,qi as RECREATE_MARKER_KEY,Yi as REMEDIATION_JOURNAL_RETENTION_DAYS,Ar as REMEDIATION_PHASES,je as REMEDIATION_VERB_GLOSS,w as REPLACEMENT_MODES,Ve as ROOT_ACCESS_FEATURES,qa as ROOT_TASK_POLICY_ARNS,Tr as RemediationFlipProofSchema,mr as RemediationJournalRecordSchema,pr as RemediationPhaseSchema,Rr as RemediationTargetSchema,Qe as RemediationVerbSchema,dr as RemediationVerbWithSurgerySchema,Ge as RootAccessEnablementError,ke as SECURITY_SERVICE_PRINCIPALS,pe as SERVICE_PRINCIPALS,sa as SNAPSHOT_CAPABLE_RESOURCE_TYPES,k as STACK_CLEANUP_PHASES,qr as STACK_FAILED_STATE_PATTERN,Zr as STACK_NOT_FOUND_PATTERN,v as STEP_COMPLETE_STATUSES,Ke as STEP_IDS,Xe as STEP_NAMES,N as SUPPORTED_CONTRACT_MARKERS,Do as ServiceArtefactSchema,Po as ServiceArtefactsSchema,$ as SimpleAwsProvider,xa as StackUnavailableError,m as StepProgressSchema,ts as StepRegistry,or as TICKET_VERDICT_SOURCES,_i as TRAIL_BUCKET_OUTPUT_KEY,Ai as TRAIL_KEY_ARN_OUTPUT_KEY,wt as TemplateHashError,Ht as TemplateHashService,ir as TicketVerdictSourceSchema,oo as ValidationError,on as accountsConfigToOUTree,Ie as activateCostAllocationTags,Te as activateTrustedAccess,Aa as advertisableDriftVerbs,ys as advertisableRemediationVerbs,Bi as applyRetainFlip,Ps as approvalRefusalReason,yi as archiveCompletedRemediationJournal,mo as artefactOutputKey,Ma as assertLeaseBeforeStack,zi as assessForgetResumability,Wa as assumeRootForTask,Bs as attachDeploymentFailure,zo as buildAccountRegionPairs,Ce as buildAccountToOUMap,wn as buildBuildSecretSessionPolicy,as as buildDeployPlan,Jn as buildDeploySessionPolicy,Cs as buildDestructionTicket,pa as buildDriftRepairTicket,Go as buildParamsContext,qo as buildRegionList,Mn as buildSatelliteRecordIndex,Zt as buildStepContextBuildConfig,ie as buildTargetSetUnreadyAdvisory,oe as buildTargetUnreadyAdvisory,Da as captureLegacySurfaces,Vi as captureRemediationForensics,$o as cascadeHomeRegion,ei as cascadeOperationKey,Fa as checkDeployPathStackAvailability,Le as checkIdentityCentreStatus,se as checkRegionEnabled,re as checkTargetReadiness,A as clampDeploymentEventStrings,bs as classifyDeployFailure,Ri as classifyDriftFailure,ks as classifyFromEcsCompletion,Ys as classifyFromFailureAnalysis,cs as classifyImpact,Vs as classifyUnclassified,xn as classifyZoneRecords,gt as clearDependencyIntegrityCache,di as clearDriftSuspects,fa as collectIdentityPinCandidates,$i as completeForgetAfterConverge,ea as completeForgetAfterDeploy,Ki as composeFlipCapabilities,La as composePostFailureRepairOffer,ye as composeSdkAbortSignal,ss as computeAssemblyDigest,ns as computeDeployPlan,Fi as computeRemediationOpId,wo as computeSecretsDrift,Xi as computeTemplateDigest,Is as computeTicketDigest,qt as convertCloudFormationOutputsToRecord,Pe as createAccount,W as createDeployEmitter,ct as createEmptyState,Ms as createMemoisedPlanLoader,un as createPublicResolvers,Lo as createSequencedCallbacks,Un as createSystemDnsNameProbe,Ei as decideNextTransition,Pa as decodeLegacyAnchor,Si as decommissionMemberTrailStorage,ui as defaultDriftJournalDir,Gi as defaultRemediationForensicsDir,hi as defaultRemediationJournalDir,Ca as degradedIdentityPinOutcomes,gn as deleteChildNsFromParent,dt as deleteDomainState,St as deleteStateFile,bo as deploy,Nn as deployDelegatedDomain,Ss as derivePropertyChanges,ca as deriveRemovalTemplate,it as deriveResourcesFromManifestStacks,Hi as deriveRetainFlipTemplate,Jo as deriveStaleParameters,le as describeOrganisation,te as describeTargetReadinessReason,Yo as destroy,Oi as detectStackDrift,Es as digestHead,es as dockerBuilder,Ue as drainPages,Qt as emitProgress,Ye as enableCentralisedRootAccess,me as enableIpamDelegatedAdmin,_e as enablePolicyTypes,Re as enableRamSharing,Ae as enableServiceAccess,Lt as ensureDependencyIntegrity,Ha as ensureEnforceSsl,Se as ensureOrganisationExists,Oe as ensureOrganisationalUnitsExist,Ns as evaluateDestructionConsents,gs as executableRemediationVerbs,tn as extractAllAccountNames,Qo as extractConsumedSsmParameters,Fe as extractErrorName,xo as failure,Ti as fetchLastOperationEvents,yo as fileExists,_o as filterDangerousEnvVars,De as findAccount,Ne as findDevelopmentOuId,wi as findMarkedResourcesByOpId,xi as findRemediationJournalByOpId,Sa as findRemovalDeletionFailures,la as findResourcesPresent,rn as flattenAccountsToEnvironments,Ci as formatDriftPreFlightBlock,ga as formatDriftRepairOffer,Ut as formatInfrastructureError,Ta as formatPinOutcomeDetail,ra as formatRecreateInFlightCures,Yr as getApplicationDeployOrder,Vr as getApplicationDestroyOrder,Gr as getApplicationStackName,Jr as getApplicationStepId,wr as getApplicationStepName,Ks as getDeploymentFailure,os as getDestroyStepId,Br as getOrganisationStackName,br as getParallelDeployGroups,kr as getParallelDestroyGroups,bt as getSourceContext,_t as getStateFilePath,vt as getStructuralHint,kt as hasCdkDifferences,fo as hasDockerfile,ut as hashDomainDirectory,he as isAborted,nn as isAccountsConfig,Ur as isApplicationOperation,Kr as isApplicationStack,Mt as isCdkError,ls as isDataLoss,Yn as isDelegatedToRoute53,ha as isDeployPathBlockingStatus,Ga as isEnforceSslStatement,Uo as isFailure,ve as isOULeaf,jr as isOpenNextPattern,vr as isOrganisationOperation,sn as isOuOnlyAccountBucket,Xr as isQuarantineDetail,Pr as isRemediationPlaceholderPhysicalId,Hr as isRetainedBucketsDetail,Za as isRootTaskPolicyArn,kn as isRoute53NameServer,_s as isStatefulResourceType,an as isStringArray,Mo as isSuccess,Ls as legalRemediationVerbs,ue as listAccounts,Mi as listActiveRemediationOps,Ui as listActiveRemediationOpsForContext,xs as loadDeployPlan,Ao as maskSensitiveOutput,ni as mergeReconciledProviderAccounts,bn as normaliseRecordName,yn as nsDelegationPhysicalName,zn as openNextBuilder,en as parseAccountsConfiguration,Wt as parseBuildPhase,q as parseDeployContractVersion,Z as parseDeployEvent,Yt as parseDiffOutput,po as parseShellArgs,Wo as partitionAccounts,Qn as partitionForRegion,ta as partitionPreFlightByRemediation,ma as pinProbeCoverage,fe as placeAccountsInOUs,ae as probeAccountStackExists,Xo as probeSecretsDrift,Ho as probeServiceDeploymentStatus,oi as projectAccountRows,ti as projectScalarSummary,Ji as proveFlipMetadataOnly,_a as proveRemovalTargetsOnly,Rt as readDomainState,Di as readDriftSuspects,vi as readRemediationJournal,Qi as readRetainFlipState,st as readStateFile,ai as reconcileProviderAccounts,ci as reconcileTrailMigration,mt as recordDomainDeployState,Pi as recordDriftSuspects,Ee as regionDisabledMessage,At as regionSuffix,be as registerSecurityDelegates,ur as remediationPhaseRank,Dr as remediationPlaceholderPhysicalId,hs as renderConsentVerdictLines,Fs as renderDestructionTicketLines,Na as renderIdentityPinReportLines,da as renderPinReportLines,ps as renderPlanLines,As as renderPlanSummary,Hn as resolveBuildArgs,Kn as resolveBuildSecretSessionProvider,Gn as resolveBuildSecrets,Bn as resolveSecretRefValue,Ko as restart,wa as restoreAndReconcileQuarantinedBucket,Ka as restoreBucketPolicy,Ds as runApprovalGate,Cn as runCaaPreflight,Fn as runDelegatedDomainDestroy,fs as runDestructionGate,fi as runDriftPreFlight,Ra as runDriftRepairGate,oa as runForgetSurgery,Ia as runIdentityPinMigration,Oa as runIdentitySurfaceGate,Sn as runOpenNextBuild,_n as runOrganisationSetup,ua as runPinRemediation,Ea as runRecreatePreFlight,aa as runRecreateSurgery,Li as runRoute53RecordPreflight,Ts as signApprovalToken,Ro as sleep,No as sleepAbortable,ge as snapshotIdentityCentre,na as snapshotPolicyForType,Xn as sourcedRefsFromBuildArgs,ht as startStackMonitoring,$n as staticSiteBuilder,tt as stubCallerIdentity,ho as success,bi as sweepExpiredRemediationJournals,ia as synthTemplateDeclaresResource,Xa as synthesiseEnforceSslDocument,vn as systemDnsNameProbe,Ln as templateOwnsDelegationRecord,Qr as toPascalCase,Ba as toResourcePolicyStatements,So as toServiceError,Rs as toWirePlanChanges,Va as triageBucketPolicy,p as truncateUtf16Safe,ba as unlockBucket,ka as unlockQueue,de as updateBackupGlobalSettings,lt as updateTemplateHash,jn as validateBuildGroup,lr as verbsForDriftVerdict,ms as verifyApprovalToken,Qa as verifyOrgTrailDelivery,ji as verifyRetainFlipDiff,On as waitForNsPropagation,rt as wrapApplicationError,Tt as writeDomainState,ki as writeRemediationJournal,Et as writeStateFile};
1
+ import{DEPLOY_CORE_VERSION_GLOBAL as t}from"./version.js";import{DeploymentEventSchema as i,DEPLOYMENT_EVENT_TYPES as a,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as n,DEPLOYMENT_EVENT_STATUS_REASON_MAX as s,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as E,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as c,DEPLOYMENT_ERROR_MESSAGE_MAX as S,CASCADE_PHASES as l,CASCADE_ACCOUNT_STATUSES as _,clampDeploymentEventStrings as p,truncateUtf16Safe as A}from"./types/index.js";import{DeployEventSchema as R,StepProgressSchema as m,DeployResourceSchema as d,PlanChangeSchema as u,PlanPropertyChangeSchema as D,ChangeCountsSchema as P,DEPLOY_EVENT_CONTRACT as O,DEPLOY_EVENT_CONTRACT_MAJOR as f,DEPLOY_EVENT_CONTRACT_MINOR as N,SUPPORTED_CONTRACT_MARKERS as C,DEPLOY_EVENT_ID_MAX as I,DEPLOY_EVENT_NAME_MAX as L,DEPLOY_EVENT_MESSAGE_MAX as g,DEPLOY_EVENT_STATUS_REASON_MAX as y,DEPLOY_EVENT_ERROR_MESSAGE_MAX as x,DEPLOY_EVENT_TRAIL_DETAIL_MAX as F,DEPLOY_EVENT_OUTPUT_MAX as h,DEPLOY_EVENT_ARN_MAX as M,DEPLOY_EVENT_URL_MAX as v,STEP_COMPLETE_STATUSES as U,LOG_LEVELS as b,STACK_CLEANUP_PHASES as k,CASCADE_ACCOUNT_PHASES as Y,DEPLOY_RESULTS as V,DETECTION_PHASES as G,PHASE_STATUSES as B,BUILDERS as K,CASCADE_OUTCOME_RESULTS as X,PLAN_ACTIONS as H,REPLACEMENT_MODES as w,APPROVAL_KINDS as J,APPROVAL_DECISIONS as W,ALL_PROGRESS_KINDS as Q,createDeployEmitter as j,parseDeployEvent as Z,parseDeployContractVersion as q}from"./types/index.js";import{SimpleAwsProvider as $}from"./aws/index.js";import{checkTargetReadiness as re,describeTargetReadinessReason as te,buildTargetUnreadyAdvisory as oe,buildTargetSetUnreadyAdvisory as ie,probeAccountStackExists as ae}from"./aws/index.js";import{checkRegionEnabled as se,regionDisabledMessage as Ee}from"./aws/index.js";import{ensureOrganisationExists as Se,describeOrganisation as le,enablePolicyTypes as _e,enableServiceAccess as pe,SERVICE_PRINCIPALS as Ae,enableRamSharing as Te,activateTrustedAccess as Re,enableIpamDelegatedAdmin as me,updateBackupGlobalSettings as de,listAccounts as ue,findAccount as De,createAccount as Pe,ensureOrganisationalUnitsExist as Oe,placeAccountsInOUs as fe,buildAccountToOUMap as Ne,findDevelopmentOuId as Ce,activateCostAllocationTags as Ie,checkIdentityCentreStatus as Le,snapshotIdentityCentre as ge,composeSdkAbortSignal as ye,extractErrorName as xe,isAborted as Fe,DEFAULT_MAX_PAGES as he,IDENTITY_STORE_PAGE_SIZE as Me,drainPages as ve,isOULeaf as Ue,registerSecurityDelegates as be,SECURITY_SERVICE_PRINCIPALS as ke,enableCentralisedRootAccess as Ye,ROOT_ACCESS_FEATURES as Ve,RootAccessEnablementError as Ge}from"./aws/index.js";import{STEP_IDS as Ke,STEP_NAMES as Xe,INFRASTRUCTURE_STEP_NAMES as He,INFRA_STEP_NAME as we}from"./types/index.js";import{RemediationVerbSchema as We,REMEDIATION_VERB_GLOSS as Qe,IDENTITY_PIN_SLOT_SWAP_GLOSS as je,DestructionFindingSchema as Ze,DestructionTicketResourceSchema as qe,DestructionTicketSchema as ze,DestructionConsentSchema as $e,DestructionOutcomeSchema as er,DESTRUCTION_FINDINGS as rr,CONSENT_VERDICTS as tr,TICKET_VERDICT_SOURCES as or,TicketVerdictSourceSchema as ir}from"./types/index.js";import{DRIFT_VERDICTS as nr,DriftVerdictSchema as sr,DriftSuspectSchema as Er,DriftFindingSchema as cr,DriftJournalRecordSchema as Sr,verbsForDriftVerdict as lr}from"./types/index.js";import{REMEDIATION_PHASES as pr,RemediationPhaseSchema as Ar,RemediationTargetSchema as Tr,RemediationFlipProofSchema as Rr,RemediationJournalRecordSchema as mr,RemediationVerbWithSurgerySchema as dr,remediationPhaseRank as ur,remediationPlaceholderPhysicalId as Dr,isRemediationPlaceholderPhysicalId as Pr}from"./types/index.js";import{ProgressReporter as fr,APPLICATION_STACKS as Nr,ORGANISATION_TYPES as Cr,APPLICATION_DEPLOY_ORDER as Ir,APPLICATION_DESTROY_ORDER as Lr,OPENNEXT_DEPLOY_ORDER as gr,OPENNEXT_DESTROY_ORDER as yr,PARALLEL_DEPLOY_GROUPS as xr,PARALLEL_DESTROY_GROUPS as Fr,OPENNEXT_PARALLEL_GROUPS as hr,PARALLEL_OPERATION_TYPES as Mr,isApplicationOperation as vr,isOrganisationOperation as Ur,getParallelDeployGroups as br,getParallelDestroyGroups as kr,getApplicationDeployOrder as Yr,getApplicationDestroyOrder as Vr,getApplicationStackName as Gr,getOrganisationStackName as Br,isApplicationStack as Kr,isQuarantineDetail as Xr,isRetainedBucketsDetail as Hr,getApplicationStepName as wr,getApplicationStepId as Jr,toPascalCase as Wr,isOpenNextPattern as Qr,OPENNEXT_PATTERNS as jr,STACK_NOT_FOUND_PATTERN as Zr,STACK_FAILED_STATE_PATTERN as qr,CDK_NO_STACKS_MATCH as zr,INFRASTRUCTURE_FILENAME as $r,ApplicationError as et,wrapApplicationError as rt,stubCallerIdentity as tt}from"./types/index.js";import{deriveResourcesFromManifestStacks as it}from"./types/detection/patternDetection.js";import{FjallStateFileSchema as nt,readStateFile as st,writeStateFile as Et,createEmptyState as ct,deleteStateFile as St,updateTemplateHash as lt,getStateFilePath as _t,regionSuffix as pt}from"./types/config/FjallState.js";import{readDomainState as Tt,writeDomainState as Rt,recordDomainDeployState as mt,deleteDomainState as dt,hashDomainDirectory as ut,LEGACY_DOMAIN_STATE_FILENAME as Dt}from"./types/config/DomainState.js";import{CloudFormationEventMonitor as Ot}from"./aws/index.js";import{CdkService as Nt,CdkArgumentBuilder as Ct,CdkProcessManager as It,ensureDependencyIntegrity as Lt,clearDependencyIntegrityCache as gt,DEPENDENCY_SYNC_TIMEOUT_MS as yt,CdkEventMonitor as xt,startStackMonitoring as Ft,DEFAULT_DEPLOY_TIMEOUT_MS as ht,isCdkError as Mt,formatInfrastructureError as vt,getStructuralHint as Ut,getSourceContext as bt,hasCdkDifferences as kt,parseDiffOutput as Yt,CloudFormationService as Vt,CloudFormationError as Gt,EcsService as Bt,EcsError as Kt,EcsServiceResolver as Xt,TemplateHashService as Ht,TemplateHashError as wt,CdkContextBuilder as Jt,emitProgress as Wt,PROGRESS_MESSAGES as Qt,parseBuildPhase as jt,buildStepContextBuildConfig as Zt,convertCloudFormationOutputsToRecord as qt,ApplicationStackService as zt}from"./services/index.js";import{CdkError as eo}from"./types/errors/index.js";import{BaseServiceError as to,ValidationError as oo,AuthError as io,AwsError as ao,DeploymentError as no,NetworkError as so,FileSystemError as Eo,ConfigError as co,toServiceError as So}from"./types/errors/index.js";import{filterDangerousEnvVars as _o,maskSensitiveOutput as po,parseShellArgs as Ao,sleep as To}from"@fjall/util";import{artefactOutputKey as mo,DeployModeSchema as uo,ServiceArtefactSchema as Do,ServiceArtefactsSchema as Po}from"@fjall/util";import{hasDockerfile as fo}from"./util/dockerfileDetection.js";import{sleepAbortable as Co}from"./util/sleepAbortable.js";import{createSequencedCallbacks as Lo}from"./util/sequencedCallbacks.js";import{fileExists as yo}from"@fjall/util/fsHelpers";import{success as Fo,failure as ho,isSuccess as Mo,isFailure as vo}from"@fjall/generator";import{deploy as bo}from"./orchestration/index.js";import{destroy as Yo}from"./orchestration/index.js";import{buildParamsContext as Go}from"./orchestration/contextHelpers.js";import{emitStepWarnings as Ko,emitWarningEvent as Xo}from"./orchestration/contextHelpers.js";import{ENGINE_DIAGNOSTIC_SCOPE as wo}from"./util/diagnosticScopes.js";import{restart as Wo,probeSecretsDrift as Qo,probeServiceDeploymentStatus as jo,computeSecretsDrift as Zo,deriveStaleParameters as qo,extractConsumedSsmParameters as zo}from"./orchestration/index.js";import{partitionAccounts as ei}from"./orchestration/index.js";import{buildRegionList as ti,buildAccountRegionPairs as oi,cascadeHomeRegion as ii,cascadeOperationKey as ai}from"./orchestration/index.js";import{projectScalarSummary as si,projectAccountRows as Ei}from"./orchestration/index.js";import{reconcileProviderAccounts as Si,mergeReconciledProviderAccounts as li}from"./orchestration/index.js";import{decideNextTransition as pi,reconcileTrailMigration as Ai,decommissionMemberTrailStorage as Ti,ORG_TRAIL_BUCKET_OUTPUT_KEY as Ri,TRAIL_BUCKET_OUTPUT_KEY as mi,TRAIL_KEY_ARN_OUTPUT_KEY as di}from"./orchestration/index.js";import{classifyDriftFailure as Di,fetchLastOperationEvents as Pi,DriftProbe as Oi,clearDriftSuspects as fi,defaultDriftJournalDir as Ni,readDriftSuspects as Ci,recordDriftSuspects as Ii,detectStackDrift as Li,runDriftPreFlight as gi,formatDriftPreFlightBlock as yi,DRIFT_PREFLIGHT_TRIGGER_STATUSES as xi,DRIFT_PREFLIGHT_BUDGET_MS as Fi,runRoute53RecordPreflight as hi}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as vi,computeRemediationOpId as Ui,defaultRemediationJournalDir as bi,findRemediationJournalByOpId as ki,listActiveRemediationOps as Yi,listActiveRemediationOpsForContext as Vi,readRemediationJournal as Gi,sweepExpiredRemediationJournals as Bi,writeRemediationJournal as Ki,REMEDIATION_JOURNAL_RETENTION_DAYS as Xi,captureRemediationForensics as Hi,defaultRemediationForensicsDir as wi,applyRetainFlip as Ji,composeFlipCapabilities as Wi,computeTemplateDigest as Qi,deriveRetainFlipTemplate as ji,findMarkedResourcesByOpId as Zi,proveFlipMetadataOnly as qi,readRetainFlipState as zi,verifyRetainFlipDiff as $i,FORGET_MARKER_KEY as ea,FORGET_FLIP_SPEC as ra,RECREATE_MARKER_KEY as ta,assessForgetResumability as oa,completeForgetAfterConverge as ia,completeForgetAfterDeploy as aa,formatRecreateInFlightCures as na,partitionPreFlightByRemediation as sa,runForgetSurgery as Ea,synthTemplateDeclaresResource as ca,runRecreateSurgery as Sa,snapshotPolicyForType as la,SNAPSHOT_CAPABLE_RESOURCE_TYPES as _a,runRecreatePreFlight as pa,deriveRemovalTemplate as Aa,findRemovalDeletionFailures as Ta,findResourcesPresent as Ra,proveRemovalTargetsOnly as ma,advertisableDriftVerbs as da,buildDriftRepairTicket as ua,runDriftRepairGate as Da,formatPinOutcomeDetail as Pa,pinProbeCoverage as Oa,renderPinReportLines as fa,runPinRemediation as Na,captureLegacySurfaces as Ca,decodeLegacyAnchor as Ia,runIdentitySurfaceGate as La,collectIdentityPinCandidates as ga,degradedIdentityPinOutcomes as ya,renderIdentityPinReportLines as xa,runIdentityPinMigration as Fa,composePostFailureRepairOffer as ha,formatDriftRepairOffer as Ma,DriftRepairAvailableError as va,checkDeployPathStackAvailability as Ua,isDeployPathBlockingStatus as ba,StackUnavailableError as ka,assertLeaseBeforeStack as Ya,LeaseDeniedError as Va}from"./orchestration/index.js";import{unlockBucket as Ba,unlockQueue as Ka}from"./orchestration/index.js";import{triageBucketPolicy as Ha,isEnforceSslStatement as wa,toResourcePolicyStatements as Ja,restoreBucketPolicy as Wa,synthesiseEnforceSslDocument as Qa,ensureEnforceSsl as ja,restoreAndReconcileQuarantinedBucket as Za}from"./orchestration/index.js";import{verifyOrgTrailDelivery as za}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as en,isRootTaskPolicyArn as rn,ROOT_TASK_POLICY_ARNS as tn,MAX_ROOT_SESSION_SECONDS as on}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as nn,flattenAccountsToEnvironments as sn,extractAllAccountNames as En,accountsConfigToOUTree as cn,isStringArray as Sn,isAccountsConfig as ln,isOuOnlyAccountBucket as _n,OU_ONLY_ACCOUNT_BUCKETS as pn}from"./orchestration/index.js";import{runOpenNextBuild as Tn}from"./orchestration/index.js";import{runOrganisationSetup as mn,ORG_SETUP_PHASES as dn}from"./orchestration/index.js";import{DOMAIN_DELEGATION_ERROR_TYPES as Dn,DomainDelegationError as Pn,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as On,PUBLIC_DNS_QUERY_TIMEOUT_MS as fn,createPublicResolvers as Nn,NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS as Cn,NS_PROPAGATION_DEFAULT_INTERVAL_MS as In,waitForNsPropagation as Ln,ACM_CAA_ISSUERS as gn,runCaaPreflight as yn,deployDelegatedDomain as xn,CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as Fn,templateOwnsDelegationRecord as hn,deleteChildNsFromParent as Mn,nsDelegationPhysicalName as vn,runDelegatedDomainDestroy as Un}from"./orchestration/index.js";import{classifyZoneRecords as kn,buildSatelliteRecordIndex as Yn,createSystemDnsNameProbe as Vn,systemDnsNameProbe as Gn,normaliseRecordName as Bn,isRoute53NameServer as Kn,isDelegatedToRoute53 as Xn}from"./orchestration/index.js";import{resolveBuildSecrets as wn,resolveSecretRefValue as Jn,resolveBuildSecretSessionProvider as Wn,sourcedRefsFromBuildArgs as Qn,resolveBuildArgs as jn,buildBuildSecretSessionPolicy as Zn,buildDeploySessionPolicy as qn,partitionForRegion as zn,validateBuildGroup as $n}from"./orchestration/index.js";import{FrameworkRegistry as rs}from"./orchestration/index.js";import{openNextBuilder as os,staticSiteBuilder as is,dockerBuilder as as}from"./orchestration/index.js";import{StepRegistry as ss,getDestroyStepId as Es}from"./steps/index.js";import{buildDeployPlan as Ss,computeDeployPlan as ls,computeAssemblyDigest as _s,digestHead as ps,classifyImpact as As,derivePropertyChanges as Ts,isDataLoss as Rs,isStatefulResourceType as ms,renderPlanSummary as ds,renderPlanLines as us,toWirePlanChanges as Ds,signApprovalToken as Ps,verifyApprovalToken as Os,DEFAULT_APPROVAL_TTL_MS as fs,APPROVAL_TOKEN_PATTERN as Ns,runApprovalGate as Cs,approvalRefusalReason as Is}from"./orchestration/index.js";import{runDestructionGate as gs,buildDestructionTicket as ys,evaluateDestructionConsents as xs,computeTicketDigest as Fs,legalRemediationVerbs as hs,executableRemediationVerbs as Ms,advertisableRemediationVerbs as vs,renderDestructionTicketLines as Us,renderConsentVerdictLines as bs,loadDeployPlan as ks,createMemoisedPlanLoader as Ys}from"./orchestration/index.js";import{DEPLOYMENT_FAILURE_CLASSIFIER_VERSION as Gs,classifyDeployFailure as Bs,classifyFromEcsCompletion as Ks,classifyFromFailureAnalysis as Xs,classifyUnclassified as Hs}from"./orchestration/failure/classifyFailure.js";import{attachDeploymentFailure as Js,getDeploymentFailure as Ws}from"./orchestration/failure/deploymentFailureAttachment.js";export{gn as ACM_CAA_ISSUERS,Q as ALL_PROGRESS_KINDS,Ir as APPLICATION_DEPLOY_ORDER,Lr as APPLICATION_DESTROY_ORDER,Nr as APPLICATION_STACKS,W as APPROVAL_DECISIONS,J as APPROVAL_KINDS,Ns as APPROVAL_TOKEN_PATTERN,et as ApplicationError,zt as ApplicationStackService,io as AuthError,ao as AwsError,K as BUILDERS,to as BaseServiceError,Y as CASCADE_ACCOUNT_PHASES,_ as CASCADE_ACCOUNT_STATUSES,X as CASCADE_OUTCOME_RESULTS,l as CASCADE_PHASES,zr as CDK_NO_STACKS_MATCH,tr as CONSENT_VERDICTS,Fn as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,Ct as CdkArgumentBuilder,Jt as CdkContextBuilder,eo as CdkError,xt as CdkEventMonitor,It as CdkProcessManager,Nt as CdkService,P as ChangeCountsSchema,Gt as CloudFormationError,Ot as CloudFormationEventMonitor,Vt as CloudFormationService,co as ConfigError,fs as DEFAULT_APPROVAL_TTL_MS,ht as DEFAULT_DEPLOY_TIMEOUT_MS,he as DEFAULT_MAX_PAGES,On as DEFAULT_PUBLIC_RESOLVER_ADDRESSES,yt as DEPENDENCY_SYNC_TIMEOUT_MS,S as DEPLOYMENT_ERROR_MESSAGE_MAX,E as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,n as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,s as DEPLOYMENT_EVENT_STATUS_REASON_MAX,c as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,a as DEPLOYMENT_EVENT_TYPES,Gs as DEPLOYMENT_FAILURE_CLASSIFIER_VERSION,t as DEPLOY_CORE_VERSION_GLOBAL,M as DEPLOY_EVENT_ARN_MAX,O as DEPLOY_EVENT_CONTRACT,f as DEPLOY_EVENT_CONTRACT_MAJOR,N as DEPLOY_EVENT_CONTRACT_MINOR,x as DEPLOY_EVENT_ERROR_MESSAGE_MAX,I as DEPLOY_EVENT_ID_MAX,g as DEPLOY_EVENT_MESSAGE_MAX,L as DEPLOY_EVENT_NAME_MAX,h as DEPLOY_EVENT_OUTPUT_MAX,y as DEPLOY_EVENT_STATUS_REASON_MAX,F as DEPLOY_EVENT_TRAIL_DETAIL_MAX,v as DEPLOY_EVENT_URL_MAX,V as DEPLOY_RESULTS,rr as DESTRUCTION_FINDINGS,G as DETECTION_PHASES,Dn as DOMAIN_DELEGATION_ERROR_TYPES,Fi as DRIFT_PREFLIGHT_BUDGET_MS,xi as DRIFT_PREFLIGHT_TRIGGER_STATUSES,nr as DRIFT_VERDICTS,R as DeployEventSchema,uo as DeployModeSchema,d as DeployResourceSchema,no as DeploymentError,i as DeploymentEventSchema,$e as DestructionConsentSchema,Ze as DestructionFindingSchema,er as DestructionOutcomeSchema,qe as DestructionTicketResourceSchema,ze as DestructionTicketSchema,Pn as DomainDelegationError,cr as DriftFindingSchema,Sr as DriftJournalRecordSchema,Oi as DriftProbe,va as DriftRepairAvailableError,Er as DriftSuspectSchema,sr as DriftVerdictSchema,wo as ENGINE_DIAGNOSTIC_SCOPE,Kt as EcsError,Bt as EcsService,Xt as EcsServiceResolver,ra as FORGET_FLIP_SPEC,ea as FORGET_MARKER_KEY,Eo as FileSystemError,nt as FjallStateFileSchema,rs as FrameworkRegistry,je as IDENTITY_PIN_SLOT_SWAP_GLOSS,Me as IDENTITY_STORE_PAGE_SIZE,$r as INFRASTRUCTURE_FILENAME,He as INFRASTRUCTURE_STEP_NAMES,we as INFRA_STEP_NAME,Dt as LEGACY_DOMAIN_STATE_FILENAME,b as LOG_LEVELS,Va as LeaseDeniedError,on as MAX_ROOT_SESSION_SECONDS,In as NS_PROPAGATION_DEFAULT_INTERVAL_MS,Cn as NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS,so as NetworkError,gr as OPENNEXT_DEPLOY_ORDER,yr as OPENNEXT_DESTROY_ORDER,hr as OPENNEXT_PARALLEL_GROUPS,jr as OPENNEXT_PATTERNS,Cr as ORGANISATION_TYPES,dn as ORG_SETUP_PHASES,Ri as ORG_TRAIL_BUCKET_OUTPUT_KEY,pn as OU_ONLY_ACCOUNT_BUCKETS,xr as PARALLEL_DEPLOY_GROUPS,Fr as PARALLEL_DESTROY_GROUPS,Mr as PARALLEL_OPERATION_TYPES,B as PHASE_STATUSES,H as PLAN_ACTIONS,Qt as PROGRESS_MESSAGES,fn as PUBLIC_DNS_QUERY_TIMEOUT_MS,u as PlanChangeSchema,D as PlanPropertyChangeSchema,fr as ProgressReporter,ta as RECREATE_MARKER_KEY,Xi as REMEDIATION_JOURNAL_RETENTION_DAYS,pr as REMEDIATION_PHASES,Qe as REMEDIATION_VERB_GLOSS,w as REPLACEMENT_MODES,Ve as ROOT_ACCESS_FEATURES,tn as ROOT_TASK_POLICY_ARNS,Rr as RemediationFlipProofSchema,mr as RemediationJournalRecordSchema,Ar as RemediationPhaseSchema,Tr as RemediationTargetSchema,We as RemediationVerbSchema,dr as RemediationVerbWithSurgerySchema,Ge as RootAccessEnablementError,ke as SECURITY_SERVICE_PRINCIPALS,Ae as SERVICE_PRINCIPALS,_a as SNAPSHOT_CAPABLE_RESOURCE_TYPES,k as STACK_CLEANUP_PHASES,qr as STACK_FAILED_STATE_PATTERN,Zr as STACK_NOT_FOUND_PATTERN,U as STEP_COMPLETE_STATUSES,Ke as STEP_IDS,Xe as STEP_NAMES,C as SUPPORTED_CONTRACT_MARKERS,Do as ServiceArtefactSchema,Po as ServiceArtefactsSchema,$ as SimpleAwsProvider,ka as StackUnavailableError,m as StepProgressSchema,ss as StepRegistry,or as TICKET_VERDICT_SOURCES,mi as TRAIL_BUCKET_OUTPUT_KEY,di as TRAIL_KEY_ARN_OUTPUT_KEY,wt as TemplateHashError,Ht as TemplateHashService,ir as TicketVerdictSourceSchema,oo as ValidationError,cn as accountsConfigToOUTree,Ie as activateCostAllocationTags,Re as activateTrustedAccess,da as advertisableDriftVerbs,vs as advertisableRemediationVerbs,Ji as applyRetainFlip,Is as approvalRefusalReason,vi as archiveCompletedRemediationJournal,mo as artefactOutputKey,Ya as assertLeaseBeforeStack,oa as assessForgetResumability,en as assumeRootForTask,Js as attachDeploymentFailure,oi as buildAccountRegionPairs,Ne as buildAccountToOUMap,Zn as buildBuildSecretSessionPolicy,Ss as buildDeployPlan,qn as buildDeploySessionPolicy,ys as buildDestructionTicket,ua as buildDriftRepairTicket,Go as buildParamsContext,ti as buildRegionList,Yn as buildSatelliteRecordIndex,Zt as buildStepContextBuildConfig,ie as buildTargetSetUnreadyAdvisory,oe as buildTargetUnreadyAdvisory,Ca as captureLegacySurfaces,Hi as captureRemediationForensics,ii as cascadeHomeRegion,ai as cascadeOperationKey,Ua as checkDeployPathStackAvailability,Le as checkIdentityCentreStatus,se as checkRegionEnabled,re as checkTargetReadiness,p as clampDeploymentEventStrings,Bs as classifyDeployFailure,Di as classifyDriftFailure,Ks as classifyFromEcsCompletion,Xs as classifyFromFailureAnalysis,As as classifyImpact,Hs as classifyUnclassified,kn as classifyZoneRecords,gt as clearDependencyIntegrityCache,fi as clearDriftSuspects,ga as collectIdentityPinCandidates,ia as completeForgetAfterConverge,aa as completeForgetAfterDeploy,Wi as composeFlipCapabilities,ha as composePostFailureRepairOffer,ye as composeSdkAbortSignal,_s as computeAssemblyDigest,ls as computeDeployPlan,Ui as computeRemediationOpId,Zo as computeSecretsDrift,Qi as computeTemplateDigest,Fs as computeTicketDigest,qt as convertCloudFormationOutputsToRecord,Pe as createAccount,j as createDeployEmitter,ct as createEmptyState,Ys as createMemoisedPlanLoader,Nn as createPublicResolvers,Lo as createSequencedCallbacks,Vn as createSystemDnsNameProbe,pi as decideNextTransition,Ia as decodeLegacyAnchor,Ti as decommissionMemberTrailStorage,Ni as defaultDriftJournalDir,wi as defaultRemediationForensicsDir,bi as defaultRemediationJournalDir,ya as degradedIdentityPinOutcomes,Mn as deleteChildNsFromParent,dt as deleteDomainState,St as deleteStateFile,bo as deploy,xn as deployDelegatedDomain,Ts as derivePropertyChanges,Aa as deriveRemovalTemplate,it as deriveResourcesFromManifestStacks,ji as deriveRetainFlipTemplate,qo as deriveStaleParameters,le as describeOrganisation,te as describeTargetReadinessReason,Yo as destroy,Li as detectStackDrift,ps as digestHead,as as dockerBuilder,ve as drainPages,Wt as emitProgress,Ko as emitStepWarnings,Xo as emitWarningEvent,Ye as enableCentralisedRootAccess,me as enableIpamDelegatedAdmin,_e as enablePolicyTypes,Te as enableRamSharing,pe as enableServiceAccess,Lt as ensureDependencyIntegrity,ja as ensureEnforceSsl,Se as ensureOrganisationExists,Oe as ensureOrganisationalUnitsExist,xs as evaluateDestructionConsents,Ms as executableRemediationVerbs,En as extractAllAccountNames,zo as extractConsumedSsmParameters,xe as extractErrorName,ho as failure,Pi as fetchLastOperationEvents,yo as fileExists,_o as filterDangerousEnvVars,De as findAccount,Ce as findDevelopmentOuId,Zi as findMarkedResourcesByOpId,ki as findRemediationJournalByOpId,Ta as findRemovalDeletionFailures,Ra as findResourcesPresent,sn as flattenAccountsToEnvironments,yi as formatDriftPreFlightBlock,Ma as formatDriftRepairOffer,vt as formatInfrastructureError,Pa as formatPinOutcomeDetail,na as formatRecreateInFlightCures,Yr as getApplicationDeployOrder,Vr as getApplicationDestroyOrder,Gr as getApplicationStackName,Jr as getApplicationStepId,wr as getApplicationStepName,Ws as getDeploymentFailure,Es as getDestroyStepId,Br as getOrganisationStackName,br as getParallelDeployGroups,kr as getParallelDestroyGroups,bt as getSourceContext,_t as getStateFilePath,Ut as getStructuralHint,kt as hasCdkDifferences,fo as hasDockerfile,ut as hashDomainDirectory,Fe as isAborted,ln as isAccountsConfig,vr as isApplicationOperation,Kr as isApplicationStack,Mt as isCdkError,Rs as isDataLoss,Xn as isDelegatedToRoute53,ba as isDeployPathBlockingStatus,wa as isEnforceSslStatement,vo as isFailure,Ue as isOULeaf,Qr as isOpenNextPattern,Ur as isOrganisationOperation,_n as isOuOnlyAccountBucket,Xr as isQuarantineDetail,Pr as isRemediationPlaceholderPhysicalId,Hr as isRetainedBucketsDetail,rn as isRootTaskPolicyArn,Kn as isRoute53NameServer,ms as isStatefulResourceType,Sn as isStringArray,Mo as isSuccess,hs as legalRemediationVerbs,ue as listAccounts,Yi as listActiveRemediationOps,Vi as listActiveRemediationOpsForContext,ks as loadDeployPlan,po as maskSensitiveOutput,li as mergeReconciledProviderAccounts,Bn as normaliseRecordName,vn as nsDelegationPhysicalName,os as openNextBuilder,nn as parseAccountsConfiguration,jt as parseBuildPhase,q as parseDeployContractVersion,Z as parseDeployEvent,Yt as parseDiffOutput,Ao as parseShellArgs,ei as partitionAccounts,zn as partitionForRegion,sa as partitionPreFlightByRemediation,Oa as pinProbeCoverage,fe as placeAccountsInOUs,ae as probeAccountStackExists,Qo as probeSecretsDrift,jo as probeServiceDeploymentStatus,Ei as projectAccountRows,si as projectScalarSummary,qi as proveFlipMetadataOnly,ma as proveRemovalTargetsOnly,Tt as readDomainState,Ci as readDriftSuspects,Gi as readRemediationJournal,zi as readRetainFlipState,st as readStateFile,Si as reconcileProviderAccounts,Ai as reconcileTrailMigration,mt as recordDomainDeployState,Ii as recordDriftSuspects,Ee as regionDisabledMessage,pt as regionSuffix,be as registerSecurityDelegates,ur as remediationPhaseRank,Dr as remediationPlaceholderPhysicalId,bs as renderConsentVerdictLines,Us as renderDestructionTicketLines,xa as renderIdentityPinReportLines,fa as renderPinReportLines,us as renderPlanLines,ds as renderPlanSummary,jn as resolveBuildArgs,Wn as resolveBuildSecretSessionProvider,wn as resolveBuildSecrets,Jn as resolveSecretRefValue,Wo as restart,Za as restoreAndReconcileQuarantinedBucket,Wa as restoreBucketPolicy,Cs as runApprovalGate,yn as runCaaPreflight,Un as runDelegatedDomainDestroy,gs as runDestructionGate,gi as runDriftPreFlight,Da as runDriftRepairGate,Ea as runForgetSurgery,Fa as runIdentityPinMigration,La as runIdentitySurfaceGate,Tn as runOpenNextBuild,mn as runOrganisationSetup,Na as runPinRemediation,pa as runRecreatePreFlight,Sa as runRecreateSurgery,hi as runRoute53RecordPreflight,Ps as signApprovalToken,To as sleep,Co as sleepAbortable,ge as snapshotIdentityCentre,la as snapshotPolicyForType,Qn as sourcedRefsFromBuildArgs,Ft as startStackMonitoring,is as staticSiteBuilder,tt as stubCallerIdentity,Fo as success,Bi as sweepExpiredRemediationJournals,ca as synthTemplateDeclaresResource,Qa as synthesiseEnforceSslDocument,Gn as systemDnsNameProbe,hn as templateOwnsDelegationRecord,Wr as toPascalCase,Ja as toResourcePolicyStatements,So as toServiceError,Ds as toWirePlanChanges,Ha as triageBucketPolicy,A as truncateUtf16Safe,Ba as unlockBucket,Ka as unlockQueue,de as updateBackupGlobalSettings,lt as updateTemplateHash,$n as validateBuildGroup,lr as verbsForDriftVerdict,Os as verifyApprovalToken,za as verifyOrgTrailDelivery,$i as verifyRetainFlipDiff,Ln as waitForNsPropagation,rt as wrapApplicationError,Rt as writeDomainState,Ki as writeRemediationJournal,Et as writeStateFile};
@@ -8,6 +8,7 @@ import type { AwsProvider, AwsProviderCredentials } from "../aws/AwsProvider.js"
8
8
  import { SimpleAwsProvider } from "../aws/SimpleAwsProvider.js";
9
9
  import type { DeploymentContext, StepOutput } from "../types/deployment/DeploymentTypes.js";
10
10
  import type { DeployCallbacks } from "../types/callbacks.js";
11
+ import type { ProgressEvent } from "../types/events.js";
11
12
  import type { DeployServices } from "./serviceFactory.js";
12
13
  /**
13
14
  * Whether a deploy targets a region other than the resolved primary. Shared
@@ -130,15 +131,27 @@ export declare function reconcileOidcProviderIfCarried(context: SynthOidcContext
130
131
  export declare function forwardOutput(callbacks: DeployCallbacks): (chunk: string) => void;
131
132
  /** Forward onResourceProgress callback — reduces lambda repetition across orchestration files. */
132
133
  export declare function forwardResourceProgress(callbacks: DeployCallbacks): (event: ResourceEvent) => void;
134
+ /**
135
+ * Emit one warning-typed progress event with the external-boundary fallback:
136
+ * a wired onProgress receives it as today, otherwise it rides the
137
+ * diagnostics spine (whose bound sink owns visibility) instead of vanishing.
138
+ * The spine arm never dedupes — repeat emissions (gate warnings per synth)
139
+ * repeat by design. Consent-flow onWarning lanes must not route through
140
+ * here: this is fire-and-forget.
141
+ */
142
+ export declare function emitWarningEvent(callbacks: DeployCallbacks | undefined, message: string, opts?: {
143
+ metadata?: ProgressEvent["metadata"];
144
+ }): void;
133
145
  /**
134
146
  * Re-emit a successful step's degradation warnings (`StepOutput.warnings`,
135
147
  * pre-masked at construction) as typed progress events. The raw
136
148
  * onOutput/onCdkOutput chunk channel lands in debug logging on the TUI,
137
- * agent and piped-human surfaces, so every step-running caller that holds
138
- * DeployCallbacks must route the payload's warnings through here or the
139
- * degrade is invisible (read-failure posture ADR clause 2).
149
+ * agent and piped-human surfaces, so every step-running caller must route
150
+ * the payload's warnings through here or the degrade is invisible
151
+ * (read-failure posture ADR clause 2). Callers without a wired onProgress
152
+ * fall back to the diagnostics spine via {@link emitWarningEvent}.
140
153
  */
141
- export declare function emitStepWarnings(callbacks: DeployCallbacks, step: StepOutput | undefined): void;
154
+ export declare function emitStepWarnings(callbacks: DeployCallbacks | undefined, step: StepOutput): void;
142
155
  /** Convert CloudFormation getStackOutputs result to Record<string, string>. */
143
156
  export declare function collectStackOutputs(result: Result<Array<{
144
157
  OutputKey?: string;
@@ -1 +1 @@
1
- var w=Object.defineProperty;var n=(e,r)=>w(e,"name",{value:r,configurable:!0});import{join as R}from"path";import{success as p,failure as u}from"@fjall/generator";import{getErrorMessage as A,maskSensitiveOutput as a,projectCapacityIdentityToTarget as S,sleep as E}from"@fjall/util";import{logger as T}from"@fjall/util/logger";import{IAMClient as b}from"@aws-sdk/client-iam";import{hasOrganisationTierAccount as h}from"../aws/organisations/accountGlobals.js";import{reconcileOidcProviderAfterDeploy as _}from"../aws/organisations/oidcProvider.js";import{SimpleAwsProvider as $}from"../aws/SimpleAwsProvider.js";import{assertEngineCompatibleWithAssembly as v}from"./application/engineCompat.js";const K={account:"active",draining:"draining",org:"removed"};function x(e,r){return e!==void 0&&e!==""&&r!==void 0&&r!==""&&e!==r}n(x,"targetsNonPrimaryRegion");function q(e){const r=x(e.region,e.primaryRegion);return{...e.orgConfig!==void 0?{orgConfig:JSON.stringify(e.orgConfig)}:{},...e.identity!==void 0?{fjallOrgId:e.identity.fjallOrgId}:{},...e.skipOidc?{fjallOidcConfigured:!0}:{},...r?{fjallAccountGlobalsConfigured:!0}:{},...e.trailLifecycle!==void 0?{fjallAccountTrailState:K[e.trailLifecycle]}:{}}}n(q,"buildParamsContext");function H(e){if(e.capacityIdentity===void 0||e.deployTargetName===void 0)return{};const r=S(e.capacityIdentity,e.deployTargetName);return r!==void 0?{capacityIdentity:JSON.stringify(r)}:{}}n(H,"buildCapacityIdentityContext");function Q(e,r,t,o){if(t!==void 0)return t;if(e==="account")return h(r?.providerAccounts)?o===!0:!0}n(Q,"resolveAccountBootstrapSkipOidc");function j(e){return e.fjallOrgId!==void 0&&e.fjallOrgId!==""&&e.fjallOidcConfigured!==!0&&e.fjallAccountGlobalsConfigured!==!0}n(j,"synthCarriedOidcConnector");async function Z(e,r,t,o){j(e)&&await _(r.getClient(b),t,o)}n(Z,"reconcileOidcProviderIfCarried");function I(e){return r=>e.onOutput?.(r)}n(I,"forwardOutput");function ee(e){return r=>e.onResourceProgress?.(r)}n(ee,"forwardResourceProgress");function M(e,r){for(const t of r?.warnings??[])e.onProgress?.({type:"warning",message:t})}n(M,"emitStepWarnings");function re(e){if(!e.success||e.data.length===0)return;const r={};for(const t of e.data)t.OutputKey&&t.OutputValue!==void 0&&(r[t.OutputKey]=t.OutputValue);return Object.keys(r).length>0?r:void 0}n(re,"collectStackOutputs");const C="OrganizationAccountAccessRole",m=5,P=5e3,D=3e4;function L(e){return`arn:aws:iam::${e}:role/${C}`}n(L,"buildCascadeRoleArn");function k(e,r){return r===void 0?E(e):r.aborted?Promise.resolve():new Promise(t=>{const o=n(()=>{t()},"onAbort");r.addEventListener("abort",o,{once:!0}),E(e).then(()=>{r.removeEventListener("abort",o),t()})})}n(k,"sleepAbortable");async function te(e,r,t,o,i){if(!e.assumeRole)return u(new Error("AwsProvider does not support assumeRole"));const d=L(r),s=e.assumeRole.bind(e);let c;for(let f=0;f<=m;f++)try{c=await s(d,o);break}catch(l){const y=l instanceof Error?l.name:void 0;if(y==="AccessDenied"||y==="AccessDeniedException")return u(new Error(`Access denied assuming ${C} in account ${r}. The role may not exist or may not trust the management account.`));if(f<m){const g=Math.min(P*2**f,D);if(T.debug("assumeCascadeRole",`Attempt ${f+1} failed for account ${r}, retrying in ${Math.round(g/1e3)}s`,{error:a(A(l))}),await k(g,i),i?.aborted)return u(new Error(`Aborted while retrying assume-role for account ${r}`));continue}return u(new Error(`Failed to assume role in account ${r} after ${m+1} attempts: ${a(A(l))}`))}if(!c)return u(new Error(`Failed to assume role in account ${r}`));const O=new $({accessKeyId:c.accessKeyId,secretAccessKey:c.secretAccessKey,sessionToken:c.sessionToken,region:t,accountId:r});return p({provider:O,credentials:{accessKeyId:c.accessKeyId,secretAccessKey:c.secretAccessKey,sessionToken:c.sessionToken}})}n(te,"assumeCascadeRole");function B(e,r){const t=v({cdkOutPath:e,onWarning:n(o=>r.onLog?.(o,"warn"),"onWarning")});return t.success?p(void 0):u(new Error(a(t.error.message)))}n(B,"assertAssemblyEngineCompat");async function ne(e,r,t,o){const i=await e.cdkService.runCdkSynth(r,s=>t.onCdkOutput?.(s,"synth"));if(!i.success){const s=new Error(a(`${o}: ${i.error}`));return t.onError?.(s),u(s)}M(t,i.data);const d=B(r.assemblyDir??R(r.path,"cdk.out"),t);if(!d.success){const s=new Error(a(d.error.message));return t.onError?.(s),u(s)}return p(void 0)}n(ne,"synthOrFail");async function oe(e,r,t,o){t.onCDKBootstrap?.("bootstrapping");const i=await e.cdkService.runCdkBootstrap(r,I(t),void 0,void 0,o);if(!i.success){t.onCDKBootstrap?.("failed");const d=new Error(a(`Bootstrap failed: ${i.error}`));return t.onError?.(d),u(d)}return t.onCDKBootstrap?.("complete"),p(void 0)}n(oe,"bootstrapOrFail");export{B as assertAssemblyEngineCompat,te as assumeCascadeRole,oe as bootstrapOrFail,H as buildCapacityIdentityContext,L as buildCascadeRoleArn,q as buildParamsContext,re as collectStackOutputs,M as emitStepWarnings,I as forwardOutput,ee as forwardResourceProgress,Z as reconcileOidcProviderIfCarried,Q as resolveAccountBootstrapSkipOidc,j as synthCarriedOidcConnector,ne as synthOrFail,x as targetsNonPrimaryRegion};
1
+ var w=Object.defineProperty;var n=(e,r)=>w(e,"name",{value:r,configurable:!0});import{join as S}from"path";import{success as p,failure as u}from"@fjall/generator";import{getErrorMessage as A,maskSensitiveOutput as d,projectCapacityIdentityToTarget as R,sleep as E}from"@fjall/util";import{logger as T}from"@fjall/util/logger";import{emitWarning as b}from"@fjall/util/diagnostics";import{IAMClient as h}from"@aws-sdk/client-iam";import{hasOrganisationTierAccount as _}from"../aws/organisations/accountGlobals.js";import{reconcileOidcProviderAfterDeploy as v}from"../aws/organisations/oidcProvider.js";import{SimpleAwsProvider as I}from"../aws/SimpleAwsProvider.js";import{ENGINE_DIAGNOSTIC_SCOPE as $}from"../util/diagnosticScopes.js";import{assertEngineCompatibleWithAssembly as x}from"./application/engineCompat.js";const K={account:"active",draining:"draining",org:"removed"};function P(e,r){return e!==void 0&&e!==""&&r!==void 0&&r!==""&&e!==r}n(P,"targetsNonPrimaryRegion");function re(e){const r=P(e.region,e.primaryRegion);return{...e.orgConfig!==void 0?{orgConfig:JSON.stringify(e.orgConfig)}:{},...e.identity!==void 0?{fjallOrgId:e.identity.fjallOrgId}:{},...e.skipOidc?{fjallOidcConfigured:!0}:{},...r?{fjallAccountGlobalsConfigured:!0}:{},...e.trailLifecycle!==void 0?{fjallAccountTrailState:K[e.trailLifecycle]}:{}}}n(re,"buildParamsContext");function te(e){if(e.capacityIdentity===void 0||e.deployTargetName===void 0)return{};const r=R(e.capacityIdentity,e.deployTargetName);return r!==void 0?{capacityIdentity:JSON.stringify(r)}:{}}n(te,"buildCapacityIdentityContext");function ne(e,r,t,o){if(t!==void 0)return t;if(e==="account")return _(r?.providerAccounts)?o===!0:!0}n(ne,"resolveAccountBootstrapSkipOidc");function j(e){return e.fjallOrgId!==void 0&&e.fjallOrgId!==""&&e.fjallOidcConfigured!==!0&&e.fjallAccountGlobalsConfigured!==!0}n(j,"synthCarriedOidcConnector");async function oe(e,r,t,o){j(e)&&await v(r.getClient(h),t,o)}n(oe,"reconcileOidcProviderIfCarried");function D(e){return r=>e.onOutput?.(r)}n(D,"forwardOutput");function ie(e){return r=>e.onResourceProgress?.(r)}n(ie,"forwardResourceProgress");function M(e,r,t){const o=e?.onProgress;if(o!==void 0){o({type:"warning",message:r,...t?.metadata!==void 0?{metadata:t.metadata}:{}});return}b(r,{scope:$,...t?.metadata!==void 0?{metadata:t.metadata}:{}})}n(M,"emitWarningEvent");function L(e,r){for(const t of r.warnings??[])M(e,t)}n(L,"emitStepWarnings");function se(e){if(!e.success||e.data.length===0)return;const r={};for(const t of e.data)t.OutputKey&&t.OutputValue!==void 0&&(r[t.OutputKey]=t.OutputValue);return Object.keys(r).length>0?r:void 0}n(se,"collectStackOutputs");const C="OrganizationAccountAccessRole",m=5,N=5e3,k=3e4;function B(e){return`arn:aws:iam::${e}:role/${C}`}n(B,"buildCascadeRoleArn");function F(e,r){return r===void 0?E(e):r.aborted?Promise.resolve():new Promise(t=>{const o=n(()=>{t()},"onAbort");r.addEventListener("abort",o,{once:!0}),E(e).then(()=>{r.removeEventListener("abort",o),t()})})}n(F,"sleepAbortable");async function ue(e,r,t,o,i){if(!e.assumeRole)return u(new Error("AwsProvider does not support assumeRole"));const a=B(r),s=e.assumeRole.bind(e);let c;for(let f=0;f<=m;f++)try{c=await s(a,o);break}catch(l){const y=l instanceof Error?l.name:void 0;if(y==="AccessDenied"||y==="AccessDeniedException")return u(new Error(`Access denied assuming ${C} in account ${r}. The role may not exist or may not trust the management account.`));if(f<m){const g=Math.min(N*2**f,k);if(T.debug("assumeCascadeRole",`Attempt ${f+1} failed for account ${r}, retrying in ${Math.round(g/1e3)}s`,{error:d(A(l))}),await F(g,i),i?.aborted)return u(new Error(`Aborted while retrying assume-role for account ${r}`));continue}return u(new Error(`Failed to assume role in account ${r} after ${m+1} attempts: ${d(A(l))}`))}if(!c)return u(new Error(`Failed to assume role in account ${r}`));const O=new I({accessKeyId:c.accessKeyId,secretAccessKey:c.secretAccessKey,sessionToken:c.sessionToken,region:t,accountId:r});return p({provider:O,credentials:{accessKeyId:c.accessKeyId,secretAccessKey:c.secretAccessKey,sessionToken:c.sessionToken}})}n(ue,"assumeCascadeRole");function G(e,r){const t=x({cdkOutPath:e,onWarning:n(o=>r.onLog?.(o,"warn"),"onWarning")});return t.success?p(void 0):u(new Error(d(t.error.message)))}n(G,"assertAssemblyEngineCompat");async function ce(e,r,t,o){const i=await e.cdkService.runCdkSynth(r,s=>t.onCdkOutput?.(s,"synth"));if(!i.success){const s=new Error(d(`${o}: ${i.error}`));return t.onError?.(s),u(s)}L(t,i.data);const a=G(r.assemblyDir??S(r.path,"cdk.out"),t);if(!a.success){const s=new Error(d(a.error.message));return t.onError?.(s),u(s)}return p(void 0)}n(ce,"synthOrFail");async function ae(e,r,t,o){t.onCDKBootstrap?.("bootstrapping");const i=await e.cdkService.runCdkBootstrap(r,D(t),void 0,void 0,o);if(!i.success){t.onCDKBootstrap?.("failed");const a=new Error(d(`Bootstrap failed: ${i.error}`));return t.onError?.(a),u(a)}return t.onCDKBootstrap?.("complete"),p(void 0)}n(ae,"bootstrapOrFail");export{G as assertAssemblyEngineCompat,ue as assumeCascadeRole,ae as bootstrapOrFail,te as buildCapacityIdentityContext,B as buildCascadeRoleArn,re as buildParamsContext,se as collectStackOutputs,L as emitStepWarnings,M as emitWarningEvent,D as forwardOutput,ie as forwardResourceProgress,oe as reconcileOidcProviderIfCarried,ne as resolveAccountBootstrapSkipOidc,j as synthCarriedOidcConnector,ce as synthOrFail,P as targetsNonPrimaryRegion};
@@ -1 +1 @@
1
- var C=Object.defineProperty;var l=(e,r)=>C(e,"name",{value:r,configurable:!0});import{success as p,failure as g}from"@fjall/generator";import{isApplicationOperation as y}from"../types/operations.js";import{isAborted as k}from"../aws/organisations/types.js";import{checkRegionEnabled as A,regionDisabledMessage as D}from"../aws/regions/regionOptStatus.js";import{createDeployServices as E}from"./serviceFactory.js";import{resolveOperation as F}from"./resolveOperation.js";import{classifyDeployFailure as S}from"./failure/classifyFailure.js";import{attachDeploymentFailure as O}from"./failure/deploymentFailureAttachment.js";import{deployApplication as h}from"./application/applicationDeploy.js";import{deployOrganisation as M}from"./organisation/organisationDeploy.js";async function $(e){const r=Date.now(),u=await A(e.awsCredentials.region,e.awsCredentials,e.abortSignal);if(u==="disabled"){const t=new Error(D(e.awsCredentials.region));return e.callbacks.onError?.(t),g(t)}u==="enabling"&&e.callbacks.onProgress?.({type:"warning",message:`Region ${e.awsCredentials.region} is still activating (opt-in status ENABLING); the deploy may fail until activation completes.`});let i,s;const b=e.callbacks.onFailureAnalysis,m=e.callbacks.onECSComplete,c={...e,callbacks:{...e.callbacks,onFailureAnalysis:l(t=>{i=t,b?.(t)},"onFailureAnalysis"),onECSComplete:l(t=>{t.success||(s=t),m?.(t)},"onECSComplete")}},d=E(c),n=await F(e.target,e.workingDirectory);if(!n.success)return e.callbacks.onError?.(n.error),n;const a=n.data,w=y(a)?"application":"organisation",o=y(a)?await h(c,d,a):await M(c,d,a);if(k(e.abortSignal))return p({target:e.target,deploymentType:w,cancelled:!0,artefacts:[],durationMs:Date.now()-r});if(!o.success){const t=S({error:o.error,...i!==void 0&&{analysis:i},...s!==void 0&&{ecsFailure:s}});return e.callbacks.onDeploymentFailure?.(t),g(O(o.error,t))}const f=i!==void 0&&o.data.failureAnalysis===void 0?{...o.data,failureAnalysis:i}:o.data;return p({...f,...f.durationMs===void 0?{durationMs:Date.now()-r}:{}})}l($,"deploy");export{$ as deploy};
1
+ var C=Object.defineProperty;var l=(e,r)=>C(e,"name",{value:r,configurable:!0});import{success as p,failure as y}from"@fjall/generator";import{isApplicationOperation as g}from"../types/operations.js";import{isAborted as k}from"../aws/organisations/types.js";import{checkRegionEnabled as A,regionDisabledMessage as E}from"../aws/regions/regionOptStatus.js";import{createDeployServices as D}from"./serviceFactory.js";import{emitWarningEvent as F}from"./contextHelpers.js";import{resolveOperation as S}from"./resolveOperation.js";import{classifyDeployFailure as O}from"./failure/classifyFailure.js";import{attachDeploymentFailure as h}from"./failure/deploymentFailureAttachment.js";import{deployApplication as v}from"./application/applicationDeploy.js";import{deployOrganisation as M}from"./organisation/organisationDeploy.js";async function z(e){const r=Date.now(),u=await A(e.awsCredentials.region,e.awsCredentials,e.abortSignal);if(u==="disabled"){const t=new Error(E(e.awsCredentials.region));return e.callbacks.onError?.(t),y(t)}u==="enabling"&&F(e.callbacks,`Region ${e.awsCredentials.region} is still activating (opt-in status ENABLING); the deploy may fail until activation completes.`);let o,s;const m=e.callbacks.onFailureAnalysis,b=e.callbacks.onECSComplete,c={...e,callbacks:{...e.callbacks,onFailureAnalysis:l(t=>{o=t,m?.(t)},"onFailureAnalysis"),onECSComplete:l(t=>{t.success||(s=t),b?.(t)},"onECSComplete")}},d=D(c),n=await S(e.target,e.workingDirectory);if(!n.success)return e.callbacks.onError?.(n.error),n;const a=n.data,w=g(a)?"application":"organisation",i=g(a)?await v(c,d,a):await M(c,d,a);if(k(e.abortSignal))return p({target:e.target,deploymentType:w,cancelled:!0,artefacts:[],durationMs:Date.now()-r});if(!i.success){const t=O({error:i.error,...o!==void 0&&{analysis:o},...s!==void 0&&{ecsFailure:s}});return e.callbacks.onDeploymentFailure?.(t),y(h(i.error,t))}const f=o!==void 0&&i.data.failureAnalysis===void 0?{...i.data,failureAnalysis:o}:i.data;return p({...f,...f.durationMs===void 0?{durationMs:Date.now()-r}:{}})}l(z,"deploy");export{z as deploy};
@@ -1 +1 @@
1
- var $=Object.defineProperty;var d=(e,r)=>$(e,"name",{value:r,configurable:!0});import{success as v,failure as p}from"@fjall/generator";import{getErrorMessage as c,maskSensitiveOutput as g}from"@fjall/util";import{isAborted as b}from"../../aws/organisations/types.js";import{waitForNsPropagation as z}from"./nsPropagationGate.js";import{runCaaPreflight as w}from"./caaPreflight.js";import{DomainDelegationError as h}from"./types.js";const C=4;function i(e,r,o){e.onProgress?.({type:"step",message:o,metadata:{source:"domain-delegation",stepIndex:r,totalSteps:C}})}d(i,"step");async function F(e){const{deployer:r,callbacks:o}=e,t=r.zoneName,n=e.retryCommand??`fjall domain deploy ${t}`;let m="deployed",l;const s=await r.zonePhaseState();if(s.success&&s.data.complete)m="resumed",l=s.data.nameServers,i(o,0,`Zone phase for ${t} already deployed \u2014 resuming at the propagation gate`);else{s.success||o.onProgress?.({type:"info",message:`Could not probe the zone-phase state for ${t} (${g(c(s.error))}) \u2014 deploying the zone phase (idempotent)`}),i(o,0,`Deploying ${t} zone phase (phase: "zone" \u2014 child zone + NS delegation, no certificates)`);const a=await r.deployPhase("zone",o);if(!a.success)return p(new h(`Delegated-domain deploy for ${t}: the zone-phase deploy failed: ${g(c(a.error))}. No certificate was requested. Cure: fix the reported stack failure and re-run \`${n}\` \u2014 a completed zone phase is skipped on resume.`,"zone_phase_failed",{zoneName:t},!1,a.error));const S=await r.zonePhaseState();S.success&&(l=S.data.nameServers)}if(b(e.abortSignal))return p(P(t,n));i(o,1,`Waiting for the NS delegation of ${t} to propagate (public resolvers)`);const f=await z({zoneName:t,...l!==void 0?{expectedNameServers:l}:{},...e.propagation?.maxAttempts!==void 0?{maxAttempts:e.propagation.maxAttempts}:{},...e.propagation?.intervalMs!==void 0?{intervalMs:e.propagation.intervalMs}:{},...e.resolvers!==void 0?{resolvers:e.resolvers}:{},...e.sleepFn!==void 0?{sleepFn:e.sleepFn}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},callbacks:o,retryCommand:n});if(!f.success)return f;let y="passed";if(e.skipCaaPreflight===!0)y="skipped",o.onProgress?.({type:"warning",message:`CAA preflight for ${t} SKIPPED (skipCaaPreflight) \u2014 if a parent CAA record restricts issuance, ACM will hang until CloudFormation rolls back`});else{i(o,2,`CAA preflight for ${t} (parent chain, public resolvers)`);const a=await w({certificateDomain:t,...e.resolvers!==void 0?{resolvers:e.resolvers}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},callbacks:o});if(!a.success)return a}if(b(e.abortSignal))return p(P(t,n));i(o,3,`Deploying ${t} full phase (phase: "full" \u2014 certificates)`);const u=await r.deployPhase("full",o);return u.success?v({zonePhase:m,propagation:f.data,caaPreflight:y,fullPhase:"deployed"}):p(new h(`Delegated-domain deploy for ${t}: the full-phase deploy failed: ${g(c(u.error))}. The zone phase is deployed and the delegation is live. Cure: fix the reported stack failure and re-run \`${n}\` \u2014 the deploy resumes at the propagation gate and re-runs only the full phase.`,"full_phase_failed",{zoneName:t},!1,u.error))}d(F,"deployDelegatedDomain");function P(e,r){return new h(`Delegated-domain deploy for ${e} aborted between phases \u2014 the zone phase (when deployed) is retained. Re-run \`${r}\` to resume.`,"aborted",{zoneName:e},!0)}d(P,"abortedMidDeploy");export{F as deployDelegatedDomain};
1
+ var $=Object.defineProperty;var d=(e,r)=>$(e,"name",{value:r,configurable:!0});import{success as z,failure as p}from"@fjall/generator";import{getErrorMessage as c,maskSensitiveOutput as g}from"@fjall/util";import{emitWarningEvent as P}from"../contextHelpers.js";import{isAborted as b}from"../../aws/organisations/types.js";import{waitForNsPropagation as w}from"./nsPropagationGate.js";import{runCaaPreflight as C}from"./caaPreflight.js";import{DomainDelegationError as h}from"./types.js";const D=4;function i(e,r,o){e.onProgress?.({type:"step",message:o,metadata:{source:"domain-delegation",stepIndex:r,totalSteps:D}})}d(i,"step");async function _(e){const{deployer:r,callbacks:o}=e,t=r.zoneName,n=e.retryCommand??`fjall domain deploy ${t}`;let m="deployed",l;const s=await r.zonePhaseState();if(s.success&&s.data.complete)m="resumed",l=s.data.nameServers,i(o,0,`Zone phase for ${t} already deployed \u2014 resuming at the propagation gate`);else{s.success||o.onProgress?.({type:"info",message:`Could not probe the zone-phase state for ${t} (${g(c(s.error))}) \u2014 deploying the zone phase (idempotent)`}),i(o,0,`Deploying ${t} zone phase (phase: "zone" \u2014 child zone + NS delegation, no certificates)`);const a=await r.deployPhase("zone",o);if(!a.success)return p(new h(`Delegated-domain deploy for ${t}: the zone-phase deploy failed: ${g(c(a.error))}. No certificate was requested. Cure: fix the reported stack failure and re-run \`${n}\` \u2014 a completed zone phase is skipped on resume.`,"zone_phase_failed",{zoneName:t},!1,a.error));const S=await r.zonePhaseState();S.success&&(l=S.data.nameServers)}if(b(e.abortSignal))return p(v(t,n));i(o,1,`Waiting for the NS delegation of ${t} to propagate (public resolvers)`);const f=await w({zoneName:t,...l!==void 0?{expectedNameServers:l}:{},...e.propagation?.maxAttempts!==void 0?{maxAttempts:e.propagation.maxAttempts}:{},...e.propagation?.intervalMs!==void 0?{intervalMs:e.propagation.intervalMs}:{},...e.resolvers!==void 0?{resolvers:e.resolvers}:{},...e.sleepFn!==void 0?{sleepFn:e.sleepFn}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},callbacks:o,retryCommand:n});if(!f.success)return f;let y="passed";if(e.skipCaaPreflight===!0)y="skipped",P(o,`CAA preflight for ${t} SKIPPED (skipCaaPreflight) \u2014 if a parent CAA record restricts issuance, ACM will hang until CloudFormation rolls back`);else{i(o,2,`CAA preflight for ${t} (parent chain, public resolvers)`);const a=await C({certificateDomain:t,...e.resolvers!==void 0?{resolvers:e.resolvers}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},callbacks:o});if(!a.success)return a}if(b(e.abortSignal))return p(v(t,n));i(o,3,`Deploying ${t} full phase (phase: "full" \u2014 certificates)`);const u=await r.deployPhase("full",o);return u.success?z({zonePhase:m,propagation:f.data,caaPreflight:y,fullPhase:"deployed"}):p(new h(`Delegated-domain deploy for ${t}: the full-phase deploy failed: ${g(c(u.error))}. The zone phase is deployed and the delegation is live. Cure: fix the reported stack failure and re-run \`${n}\` \u2014 the deploy resumes at the propagation gate and re-runs only the full phase.`,"full_phase_failed",{zoneName:t},!1,u.error))}d(_,"deployDelegatedDomain");function v(e,r){return new h(`Delegated-domain deploy for ${e} aborted between phases \u2014 the zone phase (when deployed) is retained. Re-run \`${r}\` to resume.`,"aborted",{zoneName:e},!0)}d(v,"abortedMidDeploy");export{_ as deployDelegatedDomain};
@@ -1 +1 @@
1
- var T=Object.defineProperty;var u=(e,t)=>T(e,"name",{value:t,configurable:!0});import{Route53Client as E,ListHostedZonesByNameCommand as Z,ListResourceRecordSetsCommand as x,ChangeResourceRecordSetsCommand as I}from"@aws-sdk/client-route-53";import{success as l,failure as d}from"@fjall/generator";import{getErrorMessage as y,maskSensitiveOutput as f}from"@fjall/util";import{SimpleAwsProvider as O}from"../../aws/SimpleAwsProvider.js";import{parseArn as L}from"../../aws/utils/arnParser.js";import{composeSdkAbortSignal as P,isAborted as F}from"../../aws/organisations/types.js";import{computeTicketDigest as _,evaluateDestructionConsents as D,renderConsentVerdictLines as j,renderDestructionTicketLines as z}from"../application/destructionGate.js";import{DomainDelegationError as b,normaliseDnsName as S}from"./types.js";const C="Custom::CrossAccountZoneDelegation";function M(e){let t;try{t=JSON.parse(e)}catch(a){return d(new Error(`Delegation destroy mirror: the child stack template is not readable JSON (${f(y(a))}) \u2014 NS-record ownership cannot be determined.`))}if(typeof t!="object"||t===null)return d(new Error("Delegation destroy mirror: the child stack template parsed to a non-object \u2014 NS-record ownership cannot be determined."));const n=t.Resources;if(n===void 0||typeof n!="object")return l(!1);const i=Object.values(n).some(a=>typeof a=="object"&&a!==null&&a.Type===C);return l(i)}u(M,"templateOwnsDelegationRecord");async function B(e,t){if(e.assumeRole===void 0)return d(new Error("the AWS provider does not support assumeRole"));const n=L(t)?.accountId;if(n===void 0||n==="")return d(new Error(`'${t}' is not a valid IAM role ARN`));try{const i=await e.assumeRole(t,"fjall-domain-destroy-mirror"),a=new O({accessKeyId:i.accessKeyId,secretAccessKey:i.secretAccessKey,...i.sessionToken!==void 0?{sessionToken:i.sessionToken}:{},region:"us-east-1",accountId:n});return l(a.getClient(E))}catch(i){return d(new Error(f(y(i))))}}u(B,"defaultRoute53ClientFactory");function H(e){if(!(e instanceof Error))return!1;const t=e.name,n=e.message.toLowerCase();return t==="InvalidChangeBatch"&&(n.includes("not found")||n.includes("does not exist"))}u(H,"isRecordNotFoundChange");async function K(e){const{parentZoneName:t,childZoneName:n}=e,i=u(s=>d(new b(`Destroy mirror for ${n}: deleting the NS delegation record from parent zone ${t} failed: ${s}. The stack destroy was NOT started \u2014 delete-first is the rule, because a dangling delegation is a subdomain-takeover window. Cure: re-run the destroy, or delete the ${n} NS record in ${t} yourself and re-run.`,"ns_delete_failed",{parentZoneName:t,childZoneName:n},!0)),"fail"),a=e.route53ClientFactory!==void 0?await e.route53ClientFactory(e.delegationRoleArn):await B(e.aws,e.delegationRoleArn);if(!a.success)return d(new b(`Destroy mirror for ${n}: could not assume the parent DelegationRole ${e.delegationRoleArn}: ${f(y(a.error))}. The stack destroy was NOT started. Cure: verify the role exists and trusts this account (it is created by the parent Domain stack), or delete the ${n} NS record in ${t} yourself and re-run.`,"delegation_role_unusable",{delegationRoleArn:e.delegationRoleArn}));const w=a.data,g={abortSignal:P(e.abortSignal)};let h;try{const r=((await w.send(new Z({DNSName:t,MaxItems:100}),g)).HostedZones??[]).filter(m=>m.Name!==void 0&&S(m.Name)===S(t));h=(r.find(m=>m.Config?.PrivateZone!==!0)??r[0])?.Id?.replace("/hostedzone/","")}catch(s){return i(f(y(s)))}if(h===void 0)return e.callbacks?.onProgress?.({type:"info",message:`Destroy mirror: parent zone ${t} was not found \u2014 no delegation record can dangle, continuing to the stack destroy`}),l({kind:"parent-zone-absent"});let c;try{const r=((await w.send(new x({HostedZoneId:h,StartRecordName:n,StartRecordType:"NS",MaxItems:1}),g)).ResourceRecordSets??[])[0];c=r!==void 0&&r.Name!==void 0&&S(r.Name)===S(n)&&r.Type==="NS"?r:void 0}catch(s){return i(f(y(s)))}if(c===void 0)return e.callbacks?.onProgress?.({type:"info",message:`Destroy mirror: no NS record for ${n} exists in ${t} \u2014 already deleted (idempotent), continuing to the stack destroy`}),l({kind:"record-absent"});try{await w.send(new I({HostedZoneId:h,ChangeBatch:{Comment:`fjall destroy mirror: remove NS delegation for ${n} before the stack destroy`,Changes:[{Action:"DELETE",ResourceRecordSet:c}]}}),g)}catch(s){return H(s)?l({kind:"record-absent"}):i(f(y(s)))}const R=(c.ResourceRecords??[]).map(s=>s.Value).filter(s=>s!==void 0);return e.callbacks?.onProgress?.({type:"info",message:`Destroy mirror: deleted the NS delegation for ${n} from ${t} (was: ${R.join(", ")})`}),l({kind:"deleted",recordValues:R})}u(K,"deleteChildNsFromParent");function v(e){return`${S(e)}/NS`}u(v,"nsDelegationPhysicalName");function V(e,t){const n={stack:e.stackName,logicalId:"ParentZoneNsDelegation",resourceType:"AWS::Route53::RecordSet",physicalName:v(e.childZoneName),finding:"data-loss-delete",cause:t==="deletable"?`NS delegation for ${e.childZoneName} in parent zone ${e.parentZoneName} is not CloudFormation-owned \u2014 it is deleted from the parent BEFORE the stack destroy (destroying first releases the child zone's name servers back to the Route53 pool while the parent still delegates: a subdomain-takeover window)`:`NS delegation for ${e.childZoneName} lives in the externally-owned parent ${e.parentZoneName} \u2014 fjall cannot delete it; consent 'forget' to destroy the stack anyway, then remove the record at the parent yourself (until removed it is a dangling delegation)`,offendingProperties:[],verdictSource:"change-set",dataLossRisk:t==="deletable",verbs:t==="deletable"?["abort","recreate"]:["abort","forget"]};return{ticketDigest:_(`domain-destroy:${e.stackName}:${e.childZoneName}`,[n]),resources:[n]}}u(V,"buildNsTicket");async function te(e){const{callbacks:t,childZoneName:n,parentZoneName:i}=e,a=await e.getTemplate(e.abortSignal);if(!a.success)return d(new b(`Destroy mirror for ${n}: could not read the deployed template of ${e.stackName} to determine NS-record ownership: ${f(y(a.error))}. Nothing was destroyed. Cure: retry the destroy; if the failure persists, inspect the stack with \`aws cloudformation get-template --stack-name ${e.stackName}\`.`,"template_unreadable",{stackName:e.stackName},!0));let w=!1;if(a.data!==void 0){const o=M(a.data);if(!o.success)return d(new b(`${f(o.error.message)} Nothing was destroyed. Cure: retry the destroy; if the failure persists, inspect the stack with \`aws cloudformation get-template --stack-name ${e.stackName}\`.`,"template_unreadable",{stackName:e.stackName},!0));w=o.data}if(w){t.onProgress?.({type:"info",message:`NS delegation for ${n} is CloudFormation-owned (${C}) \u2014 the stack destroy removes it in-stack, no pre-destroy delete needed`});const o=await e.destroyStack(t);return o.success?l({kind:"destroyed",nsDelegation:{kind:"cfn-owned"}}):d(o.error)}const g=e.delegationRoleArn,h=g!==void 0?"deletable":"external",c=V(e,h),R=h==="deletable"?"recreate":"forget",s=e.consents??[];let r=D({ticket:c,consents:s,...e.consentDigest!==void 0?{consentDigest:e.consentDigest}:{}});const N=[];if(!r.satisfied&&e.consentGate!==void 0&&s.length===0&&e.consentDigest===void 0){const o=await e.consentGate.resolve({target:e.stackName,ticket:c});o.kind==="abort"?N.push("declined at the interactive destruction ceremony \u2014 nothing was deleted, nothing was destroyed"):r=D({ticket:c,consents:o.consents,consentDigest:o.ticketDigest})}const m=r.satisfied&&r.rows.some(o=>o.verdict==="matched"&&o.verb==="abort");if(!r.satisfied||m||N.length>0){const o=N.length>0||m?"declined":r.rows.length>0||r.digestMismatch?"consents-invalid":"awaiting-consent",A=o==="declined"?`Destroy of ${e.stackName} declined \u2014 the NS-delegation removal was not consented; nothing was deleted, nothing was destroyed`:`Destroying ${e.stackName} deletes the NS delegation for ${n} from ${i} \u2014 named consent required; nothing was deleted, nothing was destroyed`;t.onLog?.(A,"warn");for(const k of z(c))t.onLog?.(k,"warn");for(const k of j(r))t.onLog?.(k,"warn");for(const k of N)t.onLog?.(k,"warn");return o!=="declined"&&t.onLog?.(`Consent with --remediate ${v(n)}=${R} (exact, case-sensitive). No blanket flag exists: --auto-approve, --skip-confirmation and approval tokens never satisfy this gate.`,"warn"),l({kind:"withheld",outcome:o,ticket:c,report:r,reasons:N})}if(F(e.abortSignal))return d(new b(`Destroy of ${e.stackName} aborted before the NS-delegation removal \u2014 nothing was deleted, nothing was destroyed. Re-run the destroy to resume.`,"aborted",{stackName:e.stackName},!0));let $;if(g!==void 0){const o=await K({aws:e.aws,delegationRoleArn:g,parentZoneName:i,childZoneName:n,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},callbacks:t,...e.route53ClientFactory!==void 0?{route53ClientFactory:e.route53ClientFactory}:{}});if(!o.success)return d(o.error);$=o.data}else $={kind:"external-forget"},t.onProgress?.({type:"warning",message:`NS delegation for ${n} remains in the externally-owned parent ${i} (consented 'forget') \u2014 remove it at the parent to close the dangling delegation`});const p=await e.destroyStack(t);return p.success?l({kind:"destroyed",nsDelegation:$}):d(p.error)}u(te,"runDelegatedDomainDestroy");export{C as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,K as deleteChildNsFromParent,v as nsDelegationPhysicalName,te as runDelegatedDomainDestroy,M as templateOwnsDelegationRecord};
1
+ var E=Object.defineProperty;var u=(e,t)=>E(e,"name",{value:t,configurable:!0});import{Route53Client as T,ListHostedZonesByNameCommand as Z,ListResourceRecordSetsCommand as x,ChangeResourceRecordSetsCommand as I}from"@aws-sdk/client-route-53";import{success as l,failure as d}from"@fjall/generator";import{getErrorMessage as y,maskSensitiveOutput as f}from"@fjall/util";import{emitWarningEvent as O}from"../contextHelpers.js";import{SimpleAwsProvider as L}from"../../aws/SimpleAwsProvider.js";import{parseArn as F}from"../../aws/utils/arnParser.js";import{composeSdkAbortSignal as P,isAborted as _}from"../../aws/organisations/types.js";import{computeTicketDigest as j,evaluateDestructionConsents as D,renderConsentVerdictLines as z,renderDestructionTicketLines as M}from"../application/destructionGate.js";import{DomainDelegationError as b,normaliseDnsName as S}from"./types.js";const C="Custom::CrossAccountZoneDelegation";function B(e){let t;try{t=JSON.parse(e)}catch(a){return d(new Error(`Delegation destroy mirror: the child stack template is not readable JSON (${f(y(a))}) \u2014 NS-record ownership cannot be determined.`))}if(typeof t!="object"||t===null)return d(new Error("Delegation destroy mirror: the child stack template parsed to a non-object \u2014 NS-record ownership cannot be determined."));const n=t.Resources;if(n===void 0||typeof n!="object")return l(!1);const i=Object.values(n).some(a=>typeof a=="object"&&a!==null&&a.Type===C);return l(i)}u(B,"templateOwnsDelegationRecord");async function H(e,t){if(e.assumeRole===void 0)return d(new Error("the AWS provider does not support assumeRole"));const n=F(t)?.accountId;if(n===void 0||n==="")return d(new Error(`'${t}' is not a valid IAM role ARN`));try{const i=await e.assumeRole(t,"fjall-domain-destroy-mirror"),a=new L({accessKeyId:i.accessKeyId,secretAccessKey:i.secretAccessKey,...i.sessionToken!==void 0?{sessionToken:i.sessionToken}:{},region:"us-east-1",accountId:n});return l(a.getClient(T))}catch(i){return d(new Error(f(y(i))))}}u(H,"defaultRoute53ClientFactory");function K(e){if(!(e instanceof Error))return!1;const t=e.name,n=e.message.toLowerCase();return t==="InvalidChangeBatch"&&(n.includes("not found")||n.includes("does not exist"))}u(K,"isRecordNotFoundChange");async function V(e){const{parentZoneName:t,childZoneName:n}=e,i=u(s=>d(new b(`Destroy mirror for ${n}: deleting the NS delegation record from parent zone ${t} failed: ${s}. The stack destroy was NOT started \u2014 delete-first is the rule, because a dangling delegation is a subdomain-takeover window. Cure: re-run the destroy, or delete the ${n} NS record in ${t} yourself and re-run.`,"ns_delete_failed",{parentZoneName:t,childZoneName:n},!0)),"fail"),a=e.route53ClientFactory!==void 0?await e.route53ClientFactory(e.delegationRoleArn):await H(e.aws,e.delegationRoleArn);if(!a.success)return d(new b(`Destroy mirror for ${n}: could not assume the parent DelegationRole ${e.delegationRoleArn}: ${f(y(a.error))}. The stack destroy was NOT started. Cure: verify the role exists and trusts this account (it is created by the parent Domain stack), or delete the ${n} NS record in ${t} yourself and re-run.`,"delegation_role_unusable",{delegationRoleArn:e.delegationRoleArn}));const w=a.data,g={abortSignal:P(e.abortSignal)};let h;try{const r=((await w.send(new Z({DNSName:t,MaxItems:100}),g)).HostedZones??[]).filter(m=>m.Name!==void 0&&S(m.Name)===S(t));h=(r.find(m=>m.Config?.PrivateZone!==!0)??r[0])?.Id?.replace("/hostedzone/","")}catch(s){return i(f(y(s)))}if(h===void 0)return e.callbacks?.onProgress?.({type:"info",message:`Destroy mirror: parent zone ${t} was not found \u2014 no delegation record can dangle, continuing to the stack destroy`}),l({kind:"parent-zone-absent"});let c;try{const r=((await w.send(new x({HostedZoneId:h,StartRecordName:n,StartRecordType:"NS",MaxItems:1}),g)).ResourceRecordSets??[])[0];c=r!==void 0&&r.Name!==void 0&&S(r.Name)===S(n)&&r.Type==="NS"?r:void 0}catch(s){return i(f(y(s)))}if(c===void 0)return e.callbacks?.onProgress?.({type:"info",message:`Destroy mirror: no NS record for ${n} exists in ${t} \u2014 already deleted (idempotent), continuing to the stack destroy`}),l({kind:"record-absent"});try{await w.send(new I({HostedZoneId:h,ChangeBatch:{Comment:`fjall destroy mirror: remove NS delegation for ${n} before the stack destroy`,Changes:[{Action:"DELETE",ResourceRecordSet:c}]}}),g)}catch(s){return K(s)?l({kind:"record-absent"}):i(f(y(s)))}const R=(c.ResourceRecords??[]).map(s=>s.Value).filter(s=>s!==void 0);return e.callbacks?.onProgress?.({type:"info",message:`Destroy mirror: deleted the NS delegation for ${n} from ${t} (was: ${R.join(", ")})`}),l({kind:"deleted",recordValues:R})}u(V,"deleteChildNsFromParent");function v(e){return`${S(e)}/NS`}u(v,"nsDelegationPhysicalName");function G(e,t){const n={stack:e.stackName,logicalId:"ParentZoneNsDelegation",resourceType:"AWS::Route53::RecordSet",physicalName:v(e.childZoneName),finding:"data-loss-delete",cause:t==="deletable"?`NS delegation for ${e.childZoneName} in parent zone ${e.parentZoneName} is not CloudFormation-owned \u2014 it is deleted from the parent BEFORE the stack destroy (destroying first releases the child zone's name servers back to the Route53 pool while the parent still delegates: a subdomain-takeover window)`:`NS delegation for ${e.childZoneName} lives in the externally-owned parent ${e.parentZoneName} \u2014 fjall cannot delete it; consent 'forget' to destroy the stack anyway, then remove the record at the parent yourself (until removed it is a dangling delegation)`,offendingProperties:[],verdictSource:"change-set",dataLossRisk:t==="deletable",verbs:t==="deletable"?["abort","recreate"]:["abort","forget"]};return{ticketDigest:j(`domain-destroy:${e.stackName}:${e.childZoneName}`,[n]),resources:[n]}}u(G,"buildNsTicket");async function oe(e){const{callbacks:t,childZoneName:n,parentZoneName:i}=e,a=await e.getTemplate(e.abortSignal);if(!a.success)return d(new b(`Destroy mirror for ${n}: could not read the deployed template of ${e.stackName} to determine NS-record ownership: ${f(y(a.error))}. Nothing was destroyed. Cure: retry the destroy; if the failure persists, inspect the stack with \`aws cloudformation get-template --stack-name ${e.stackName}\`.`,"template_unreadable",{stackName:e.stackName},!0));let w=!1;if(a.data!==void 0){const o=B(a.data);if(!o.success)return d(new b(`${f(o.error.message)} Nothing was destroyed. Cure: retry the destroy; if the failure persists, inspect the stack with \`aws cloudformation get-template --stack-name ${e.stackName}\`.`,"template_unreadable",{stackName:e.stackName},!0));w=o.data}if(w){t.onProgress?.({type:"info",message:`NS delegation for ${n} is CloudFormation-owned (${C}) \u2014 the stack destroy removes it in-stack, no pre-destroy delete needed`});const o=await e.destroyStack(t);return o.success?l({kind:"destroyed",nsDelegation:{kind:"cfn-owned"}}):d(o.error)}const g=e.delegationRoleArn,h=g!==void 0?"deletable":"external",c=G(e,h),R=h==="deletable"?"recreate":"forget",s=e.consents??[];let r=D({ticket:c,consents:s,...e.consentDigest!==void 0?{consentDigest:e.consentDigest}:{}});const N=[];if(!r.satisfied&&e.consentGate!==void 0&&s.length===0&&e.consentDigest===void 0){const o=await e.consentGate.resolve({target:e.stackName,ticket:c});o.kind==="abort"?N.push("declined at the interactive destruction ceremony \u2014 nothing was deleted, nothing was destroyed"):r=D({ticket:c,consents:o.consents,consentDigest:o.ticketDigest})}const m=r.satisfied&&r.rows.some(o=>o.verdict==="matched"&&o.verb==="abort");if(!r.satisfied||m||N.length>0){const o=N.length>0||m?"declined":r.rows.length>0||r.digestMismatch?"consents-invalid":"awaiting-consent",A=o==="declined"?`Destroy of ${e.stackName} declined \u2014 the NS-delegation removal was not consented; nothing was deleted, nothing was destroyed`:`Destroying ${e.stackName} deletes the NS delegation for ${n} from ${i} \u2014 named consent required; nothing was deleted, nothing was destroyed`;t.onLog?.(A,"warn");for(const k of M(c))t.onLog?.(k,"warn");for(const k of z(r))t.onLog?.(k,"warn");for(const k of N)t.onLog?.(k,"warn");return o!=="declined"&&t.onLog?.(`Consent with --remediate ${v(n)}=${R} (exact, case-sensitive). No blanket flag exists: --auto-approve, --skip-confirmation and approval tokens never satisfy this gate.`,"warn"),l({kind:"withheld",outcome:o,ticket:c,report:r,reasons:N})}if(_(e.abortSignal))return d(new b(`Destroy of ${e.stackName} aborted before the NS-delegation removal \u2014 nothing was deleted, nothing was destroyed. Re-run the destroy to resume.`,"aborted",{stackName:e.stackName},!0));let $;if(g!==void 0){const o=await V({aws:e.aws,delegationRoleArn:g,parentZoneName:i,childZoneName:n,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{},callbacks:t,...e.route53ClientFactory!==void 0?{route53ClientFactory:e.route53ClientFactory}:{}});if(!o.success)return d(o.error);$=o.data}else $={kind:"external-forget"},O(t,`NS delegation for ${n} remains in the externally-owned parent ${i} (consented 'forget') \u2014 remove it at the parent to close the dangling delegation`);const p=await e.destroyStack(t);return p.success?l({kind:"destroyed",nsDelegation:$}):d(p.error)}u(oe,"runDelegatedDomainDestroy");export{C as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,V as deleteChildNsFromParent,v as nsDelegationPhysicalName,oe as runDelegatedDomainDestroy,B as templateOwnsDelegationRecord};
@@ -1 +1 @@
1
- var _=Object.defineProperty;var C=(t,n)=>_(t,"name",{value:n,configurable:!0});import{join as x}from"path";import{logger as l}from"@fjall/util/logger";import{maskSensitiveOutput as s,getErrorMessage as A,resolveSynthEnvironment as L}from"@fjall/util";import{stubCallerIdentity as M}from"../../types/deployment/index.js";import{CloudFormationClient as T,DescribeStacksCommand as K}from"@aws-sdk/client-cloudformation";import{S3Client as D}from"@aws-sdk/client-s3";import{BackupClient as V}from"@aws-sdk/client-backup";import{IAMClient as j}from"@aws-sdk/client-iam";import{accountHasDisasterRecovery as U,describeSurvivingBackupVault as W,formatSurvivingVaultWarning as G}from"../../aws/organisations/backup.js";import{cleanupOrphanedOidcProvider as H}from"../../aws/organisations/oidcProvider.js";import{composeSdkAbortSignal as Y}from"../../aws/organisations/types.js";import{assertLeaseBeforeStack as q}from"../application/leaseGate.js";import{ORGANISATION_TYPES as B,getOrganisationStackName as z}from"../../types/operations.js";import{CdkContextBuilder as J}from"../../services/supporting/CdkContextBuilder.js";import{regionSuffix as Q}from"../../types/config/FjallState.js";import{assertAssemblyEngineCompat as X,buildParamsContext as Z,assumeCascadeRole as ee,emitStepWarnings as te,forwardOutput as I}from"../contextHelpers.js";import{cascadeOperationKey as re}from"./cascadeHelpers.js";import{capturedSweepBuckets as ae,cleanupFailedStack as oe,preEmptyStackBuckets as ne,sweepOrphanedDestroyBuckets as $}from"../stackCleanup.js";import{STACK_NOT_FOUND_PATTERN as ie,STACK_FAILED_STATE_PATTERN as se}from"../../types/constants.js";async function Te(t,n,c,e,r,a,o,y){const g=Date.now(),m=re(e.name,a),f=C((i,p=i)=>(o.onCascadeAccountComplete?.(m,!1,p,a),{accountName:e.name,accountId:e.id,region:a,success:!1,duration:Date.now()-g,error:i}),"fail");o.onCascadeAccountStart?.(m,e.id,a,r);const v=await ee(n.awsProvider,e.id,a,`fjall-cascade-destroy-${e.name}`);if(!v.success){const i=s(v.error.message);return f(`AssumeRole failed: ${i}`,i)}const{provider:d,credentials:h}=v.data,R=x(c.path,`cdk.out.${e.id}.${Q(a)}`),E=J.buildDeploymentContext({deployType:r,target:c.target,path:c.path,assemblyDir:R,region:a,accountName:e.name,environment:L(e),callerIdentity:M(e.id),...Z({orgConfig:t.orgConfig,identity:t.identity,region:a,primaryRegion:y?.primaryRegion})},{verbose:t.options?.verbose},t.orgConfig);o.onCascadeAccountPhaseChange?.(m,"synth",a);const w=await n.cdkService.runCdkSynth(E,I(o));if(!w.success)return f(s(`Synth failed: ${w.error}`));te(o,w.data);const P=X(R,o);if(!P.success)return f(P.error.message);o.onCascadeAccountPhaseChange?.(m,"destroy",a);const u=z(r==="platform"?B.PLATFORM:B.ACCOUNT),k=await q(t.assertLeaseForStack,u,t.abortSignal,"destroy");if(k!==void 0)return{...f(k.message),leaseDenied:k};U(e.environment,t.orgConfig?.disasterRecoveryRegion)&&await de(d.getClient(V),a,o,t.abortSignal);const b=await ne(d.getClient(T),d.getClient(D),u,o,t.abortSignal),S=ae(b),N=await n.cdkService.runCdkDestroy(E,u,I(o),i=>o.onCascadeAccountResourceProgress?.(m,i,a),d,!0,h);if(!N.success){const i=N.error;if(i.includes(se)){l.warn("cascadeDestroy",`CDK destroy failed on ${u} in failed state, retrying via CloudFormation API`,{region:a,account:e.name});try{await oe(u,a,h,{accountId:e.id,abortSignal:t.abortSignal},o)}catch(F){const O=`cleanupFailedStack threw for ${u}: ${s(A(F))}`;l.warn("cascadeDestroy",O),o.onLog?.(O,"warn")}const p=await ue(u,d.getClient(T),t.abortSignal);return p.deleted?(S.length>0&&await $(d.getClient(D),S,o,t.abortSignal),o.onCascadeAccountComplete?.(m,!0,void 0,a),{accountName:e.name,accountId:e.id,region:a,success:!0,duration:Date.now()-g}):p.error?f(s(p.error)):f(s(`Stack ${u} cleanup attempted but stack still exists in ${a}`))}return f(s(i))}return S.length>0&&await $(d.getClient(D),S,o,t.abortSignal),(y?.primaryRegion===void 0||a===y.primaryRegion)&&await H(d.getClient(j),o,t.abortSignal),o.onCascadeAccountComplete?.(m,!0,void 0,a),{accountName:e.name,accountId:e.id,region:a,success:!0,duration:Date.now()-g}}C(Te,"destroyCascadeAccount");async function de(t,n,c,e){try{const r=await W(t,n,e);if(!r.success){l.debug("cascadeDestroy","Backup-vault survival probe failed",{region:n,error:s(r.error.message)});return}if(r.data===null)return;c.onProgress?.({type:"warning",message:G(r.data),metadata:{source:"backup-vault-survival"}}),l.warn("cascadeDestroy","Backup vault survives destroy",{region:n,vaultName:r.data.vaultName,recoveryPointCount:r.data.recoveryPointCount,lockPermanent:r.data.lockPermanent})}catch(r){l.debug("cascadeDestroy","Backup-vault survival probe threw",{region:n,error:s(A(r))})}}C(de,"warnIfBackupVaultSurvives");async function ue(t,n,c){try{const r=(await n.send(new K({StackName:t}),{abortSignal:Y(c)})).Stacks?.[0]?.StackStatus;return!r||r==="DELETE_COMPLETE"?{deleted:!0}:{deleted:!1,error:`Stack still in ${r} after cleanup attempt`}}catch(e){if(e instanceof Error&&e.message?.includes(ie))return{deleted:!0};const r=s(A(e));return l.debug("cascadeDestroy","Stack verification failed",{error:r}),{deleted:!1,error:`Stack verification failed: ${r}`}}}C(ue,"verifyStackDeleted");export{Te as destroyCascadeAccount};
1
+ var _=Object.defineProperty;var C=(t,o)=>_(t,"name",{value:o,configurable:!0});import{join as x}from"path";import{logger as l}from"@fjall/util/logger";import{maskSensitiveOutput as s,getErrorMessage as A,resolveSynthEnvironment as L}from"@fjall/util";import{stubCallerIdentity as M}from"../../types/deployment/index.js";import{CloudFormationClient as T,DescribeStacksCommand as K}from"@aws-sdk/client-cloudformation";import{S3Client as D}from"@aws-sdk/client-s3";import{BackupClient as V}from"@aws-sdk/client-backup";import{IAMClient as W}from"@aws-sdk/client-iam";import{accountHasDisasterRecovery as j,describeSurvivingBackupVault as U,formatSurvivingVaultWarning as G}from"../../aws/organisations/backup.js";import{cleanupOrphanedOidcProvider as H}from"../../aws/organisations/oidcProvider.js";import{composeSdkAbortSignal as Y}from"../../aws/organisations/types.js";import{assertLeaseBeforeStack as q}from"../application/leaseGate.js";import{ORGANISATION_TYPES as B,getOrganisationStackName as z}from"../../types/operations.js";import{CdkContextBuilder as J}from"../../services/supporting/CdkContextBuilder.js";import{regionSuffix as Q}from"../../types/config/FjallState.js";import{assertAssemblyEngineCompat as X,buildParamsContext as Z,assumeCascadeRole as ee,emitStepWarnings as te,emitWarningEvent as re,forwardOutput as I}from"../contextHelpers.js";import{cascadeOperationKey as ae}from"./cascadeHelpers.js";import{capturedSweepBuckets as ne,cleanupFailedStack as oe,preEmptyStackBuckets as ie,sweepOrphanedDestroyBuckets as $}from"../stackCleanup.js";import{STACK_NOT_FOUND_PATTERN as se,STACK_FAILED_STATE_PATTERN as de}from"../../types/constants.js";async function Be(t,o,c,e,r,a,n,y){const g=Date.now(),m=ae(e.name,a),f=C((i,p=i)=>(n.onCascadeAccountComplete?.(m,!1,p,a),{accountName:e.name,accountId:e.id,region:a,success:!1,duration:Date.now()-g,error:i}),"fail");n.onCascadeAccountStart?.(m,e.id,a,r);const v=await ee(o.awsProvider,e.id,a,`fjall-cascade-destroy-${e.name}`);if(!v.success){const i=s(v.error.message);return f(`AssumeRole failed: ${i}`,i)}const{provider:d,credentials:h}=v.data,E=x(c.path,`cdk.out.${e.id}.${Q(a)}`),R=J.buildDeploymentContext({deployType:r,target:c.target,path:c.path,assemblyDir:E,region:a,accountName:e.name,environment:L(e),callerIdentity:M(e.id),...Z({orgConfig:t.orgConfig,identity:t.identity,region:a,primaryRegion:y?.primaryRegion})},{verbose:t.options?.verbose},t.orgConfig);n.onCascadeAccountPhaseChange?.(m,"synth",a);const w=await o.cdkService.runCdkSynth(R,I(n));if(!w.success)return f(s(`Synth failed: ${w.error}`));te(n,w.data);const P=X(E,n);if(!P.success)return f(P.error.message);n.onCascadeAccountPhaseChange?.(m,"destroy",a);const u=z(r==="platform"?B.PLATFORM:B.ACCOUNT),k=await q(t.assertLeaseForStack,u,t.abortSignal,"destroy");if(k!==void 0)return{...f(k.message),leaseDenied:k};j(e.environment,t.orgConfig?.disasterRecoveryRegion)&&await ue(d.getClient(V),a,n,t.abortSignal);const b=await ie(d.getClient(T),d.getClient(D),u,n,t.abortSignal),S=ne(b),N=await o.cdkService.runCdkDestroy(R,u,I(n),i=>n.onCascadeAccountResourceProgress?.(m,i,a),d,!0,h);if(!N.success){const i=N.error;if(i.includes(de)){l.warn("cascadeDestroy",`CDK destroy failed on ${u} in failed state, retrying via CloudFormation API`,{region:a,account:e.name});try{await oe(u,a,h,{accountId:e.id,abortSignal:t.abortSignal},n)}catch(F){const O=`cleanupFailedStack threw for ${u}: ${s(A(F))}`;l.warn("cascadeDestroy",O),n.onLog?.(O,"warn")}const p=await ce(u,d.getClient(T),t.abortSignal);return p.deleted?(S.length>0&&await $(d.getClient(D),S,n,t.abortSignal),n.onCascadeAccountComplete?.(m,!0,void 0,a),{accountName:e.name,accountId:e.id,region:a,success:!0,duration:Date.now()-g}):p.error?f(s(p.error)):f(s(`Stack ${u} cleanup attempted but stack still exists in ${a}`))}return f(s(i))}return S.length>0&&await $(d.getClient(D),S,n,t.abortSignal),(y?.primaryRegion===void 0||a===y.primaryRegion)&&await H(d.getClient(W),n,t.abortSignal),n.onCascadeAccountComplete?.(m,!0,void 0,a),{accountName:e.name,accountId:e.id,region:a,success:!0,duration:Date.now()-g}}C(Be,"destroyCascadeAccount");async function ue(t,o,c,e){try{const r=await U(t,o,e);if(!r.success){l.debug("cascadeDestroy","Backup-vault survival probe failed",{region:o,error:s(r.error.message)});return}if(r.data===null)return;re(c,G(r.data),{metadata:{source:"backup-vault-survival"}}),l.warn("cascadeDestroy","Backup vault survives destroy",{region:o,vaultName:r.data.vaultName,recoveryPointCount:r.data.recoveryPointCount,lockPermanent:r.data.lockPermanent})}catch(r){l.debug("cascadeDestroy","Backup-vault survival probe threw",{region:o,error:s(A(r))})}}C(ue,"warnIfBackupVaultSurvives");async function ce(t,o,c){try{const r=(await o.send(new K({StackName:t}),{abortSignal:Y(c)})).Stacks?.[0]?.StackStatus;return!r||r==="DELETE_COMPLETE"?{deleted:!0}:{deleted:!1,error:`Stack still in ${r} after cleanup attempt`}}catch(e){if(e instanceof Error&&e.message?.includes(se))return{deleted:!0};const r=s(A(e));return l.debug("cascadeDestroy","Stack verification failed",{error:r}),{deleted:!1,error:`Stack verification failed: ${r}`}}}C(ce,"verifyStackDeleted");export{Be as destroyCascadeAccount};
@@ -1 +1 @@
1
- var Y=Object.defineProperty;var m=(e,o)=>Y(e,"name",{value:o,configurable:!0});import{join as H}from"path";import{success as I,failure as w}from"@fjall/generator";import{logger as A}from"@fjall/util/logger";import{maskSensitiveOutput as S,mapSettledWithConcurrency as X,resolveSynthEnvironment as q}from"@fjall/util";import{ORGANISATION_TYPES as P,getOrganisationStackName as V}from"../../types/operations.js";import{CdkContextBuilder as J}from"../../services/supporting/CdkContextBuilder.js";import{stubCallerIdentity as Q}from"../../types/deployment/index.js";import{CloudFormationService as G}from"../../services/infrastructure/CloudFormationService.js";import{getCascadeStateFilePath as Z,regionSuffix as ee}from"../../types/config/FjallState.js";import{BackupClient as te}from"@aws-sdk/client-backup";import{accountHasDisasterRecovery as oe,describeBackupVaultExists as ne}from"../../aws/organisations/backup.js";import{assertAssemblyEngineCompat as re,buildParamsContext as ae,collectStackOutputs as U,assumeCascadeRole as E,emitStepWarnings as se,forwardOutput as N,reconcileOidcProviderIfCarried as W}from"../contextHelpers.js";import{assertLeaseBeforeStack as ie}from"../application/leaseGate.js";import{deployDelegatedDomain as ce}from"../domain/delegatedDomainDeploy.js";import{normaliseRecordName as j}from"../domain/zoneClassifier.js";import{runDriftPreFlightGate as de}from"../drift/preFlightGate.js";import{accountTier as _}from"@fjall/util";import{buildBootstrapTagsIfResolved as ue}from"../bootstrapTags.js";import{hasOrganisationTierAccount as fe}from"../../aws/organisations/accountGlobals.js";import{DEFAULT_REGION as K}from"../../aws/utils/regions.js";const le=4;function Be(e){const o=e.find(n=>_(n)==="platform"),c=e.filter(n=>_(n)==="account");return{platformAccount:o,memberAccounts:c}}m(Be,"partitionAccounts");function pe(e){const o=e?.primaryRegion??K,c=e?.secondaryRegions??[],n=new Set([o,...c]),i=e?.disasterRecoveryRegion;return i&&n.add(i),[...n]}m(pe,"buildRegionList");function Te(e){return pe(e)[0]??K}m(Te,"cascadeHomeRegion");function ge(e,o){return`${e} (${o})`}m(ge,"cascadeOperationKey");function He(e,o){const c=[];for(const n of o)for(const i of e)c.push({account:i,region:n});return c}m(He,"buildAccountRegionPairs");import{buildCascadeRoleArn as ze}from"../contextHelpers.js";async function Ve(e,o,c,n){c.onLog?.(`Verifying cascade role access for ${o.length} account(s)\u2026`,"info");const i=await X(o,le,async a=>E(e.awsProvider,a.id,a.region??e.awsProvider.getRegion(),`fjall-preflight-${a.name}`,n)),t=[];return i.forEach((a,s)=>{const r=o[s];if(r){if(a.status==="rejected"){t.push({accountId:r.id,accountName:r.name,error:a.reason instanceof Error?a.reason.message:String(a.reason)});return}a.value.success||t.push({accountId:r.id,accountName:r.name,error:a.value.error.message})}}),t.length===0&&c.onLog?.(`Cascade role access verified for ${o.length} account(s)`,"info"),t}m(Ve,"probeCascadeRoles");async function Ge(e,o,c,n,i,t,a){const s=a?.region??n.region??o.awsProvider.getRegion(),r=ge(n.name,s),u=a?.orgConfig??e.orgConfig,C=a?.ipamPoolId;t.onCascadeAccountStart?.(r,n.id,s,i);const p=await E(o.awsProvider,n.id,s,`fjall-cascade-${n.name}`,e.abortSignal);if(!p.success)return t.onCascadeAccountComplete?.(r,!1,S(p.error.message),s),w(new Error(`Failed to assume role for ${n.name}: ${S(p.error.message)}`));const{provider:d,credentials:l}=p.data,h=H(e.workingDirectory,"fjall",i==="platform"?P.PLATFORM:P.ACCOUNT),f=H(h,`cdk.out.${n.id}.${ee(s)}`),R=J.buildDeploymentContext({deployType:i,target:c.target,path:h,assemblyDir:f,environment:q(n),region:s,accountName:n.name,callerIdentity:Q(n.id),ipamPoolId:C,...ae({orgConfig:u,identity:e.identity,skipOidc:e.options?.skipOidc,region:s,primaryRegion:a?.primaryRegion,trailLifecycle:n.trailLifecycle})},{verbose:e.options?.verbose},u);if(oe(n.environment,u?.disasterRecoveryRegion)){const g=await ne(d.getClient(te),e.abortSignal);if(!g.success)return t.onCascadeAccountComplete?.(r,!1,S(g.error.message),s),w(new Error(`Backup vault probe failed for ${n.name}: ${S(g.error.message)}`));R.fjallAdoptBackupVault=g.data}t.onCascadeAccountPhaseChange?.(r,"synth",s);const $=await o.cdkService.runCdkSynth(R,N(t),l);if(!$.success)return t.onCascadeAccountComplete?.(r,!1,S(`Synth failed: ${$.error}`),s),w(new Error(`Synth failed for ${n.name}: ${S($.error)}`));se(t,$.data);const b=re(f,t);if(!b.success){const g=S(b.error.message);return t.onCascadeAccountComplete?.(r,!1,g,s),w(new Error(`Engine compatibility check failed for ${n.name}: ${g}`))}const y=V(i==="platform"?P.PLATFORM:P.ACCOUNT),F=Z(h,n.id,s),D=new G(d),{changed:z,currentHash:L}=await o.hashService.compareCascadeStack(f,y,F);if(!z&&e.options?.force!==!0&&await D.stackExists(y,void 0,e.abortSignal)){const g=await D.getStackOutputs(y,void 0,e.abortSignal);g.success||A.debug("cascadeHelpers","Failed to read outputs for skipped cascade account (non-critical)",{stackName:y,account:n.name});const T=U(g);return await W(R,d,t,e.abortSignal),t.onLog?.(`${n.name}: no infrastructure changes \u2014 skipping deploy`,"info"),t.onCascadeAccountComplete?.(r,!0,void 0,s,T,!0),I({outputs:T,skipped:!0})}const v=await de(d,{stackNames:[y],cdkOutPath:f,cfnService:D,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(v.kind==="blocked")return t.onCascadeAccountComplete?.(r,!1,v.message,s),w(new Error(v.message));const O=await ie(e.assertLeaseForStack,y,e.abortSignal);if(O!==void 0)return t.onCascadeAccountComplete?.(r,!1,O.message,s),w(O);t.onCascadeAccountPhaseChange?.(r,"bootstrap",s);const x=await o.cdkService.runCdkBootstrap(R,N(t),l,void 0,ue({account:n,estate:fe(u?.providerAccounts)?"org":"solo",...a?.orgId!==void 0?{orgId:a.orgId}:{}}));if(!x.success)return t.onCascadeAccountComplete?.(r,!1,S(`Bootstrap failed: ${x.error}`),s),w(new Error(`Bootstrap failed for ${n.name}: ${S(x.error)}`));t.onCascadeAccountPhaseChange?.(r,"deploy",s);const k=await o.cdkService.runCdkDeploy(R,y,N(t),g=>t.onCascadeAccountResourceProgress?.(r,g,s),d,l);if(!k.success)return t.onCascadeAccountComplete?.(r,!1,S(k.error),s),w(new Error(S(k.error)));const M=await D.getStackOutputs(y,void 0,e.abortSignal);M.success||A.debug("cascadeHelpers","Failed to read cascade account stack outputs (non-critical)",{stackName:y,account:n.name});const B=U(M);return await W(R,d,t,e.abortSignal),L!==void 0&&((await o.hashService.persistCascadeStack(F,y,L)).success||A.debug("cascadeHelpers","Failed to persist cascade hash state (non-critical)",{stackName:y,account:n.name})),t.onCascadeAccountComplete?.(r,!0,void 0,s,B,!1),I({outputs:B,skipped:!1})}m(Ge,"deployCascadeAccount");async function Ue(e,o,c,n){const i=new Map,t=e.awsProvider.getRegion(),a=await E(e.awsProvider,o.id,t,`fjall-ipam-read-${o.name}`,n);if(!a.success)return A.debug("organisationDeploy",`Cannot read Platform outputs: ${a.error.message}`),i;const s=new G(a.data.provider),r=V(P.PLATFORM),u=await s.getStackOutputs(r);if(!u.success)return A.debug("organisationDeploy",`Failed to read Platform stack outputs: ${u.error.message}`),i;const C=/^IpamPoolId(\d{12})(\w+)$/;for(const p of u.data){const d=p.OutputKey?.match(C);if(d&&p.OutputValue){const l=`${d[1]}-${d[2]}`;i.set(l,p.OutputValue)}}return i.size>0&&c.onLog?.(`Read ${i.size} IPAM pool ID(s) from Platform stack`,"info"),i}m(Ue,"readPlatformIpamPoolIds");function me(e,o){const c=e.account!==void 0&&o?.executingAccountId!==void 0&&e.account!==o.executingAccountId,n=e.region!==void 0&&o?.executingRegion!==void 0&&e.region!==o.executingRegion;if(c)return`[${e.name}] skipped: its fjall-config.json entry records account ${e.account} as its home, but this cascade runs in account ${o?.executingAccountId} - deploy it separately with 'fjall domain deploy ${e.name} -t <target in account ${e.account}>' or run the cascade under that account.`;if(n)return`[${e.name}] skipped: its fjall-config.json entry records region ${e.region} as its home, but this cascade runs in region ${o?.executingRegion} - deploy it separately with 'fjall domain deploy ${e.name} --region ${e.region}', or update the entry's "region" key if this move is intentional.`}m(me,"foreignDomainSkipReason");function Ce(e){const o=new Map;for(const t of e)o.set(j(t.name),t);const c=new Map,n=m((t,a)=>{const s=c.get(t);if(s!==void 0)return s;if(a.includes(t))return[...a.slice(a.indexOf(t)),t];const r=o.get(t);if(r===void 0)return-1;const u=r.parentDomain!==void 0?j(r.parentDomain):void 0,C=u===void 0?-1:n(u,[...a,t]);if(Array.isArray(C))return C;const p=C+1;return c.set(t,p),p},"resolveDepth"),i=[];for(const t of e){const a=n(j(t.name),[]);if(Array.isArray(a)){const s=a.map(r=>o.get(r)?.name??r).join(" -> ");return w(new Error(`Delegated domain ordering: fjall-config.json declares a parentDomain cycle (${s}) - no deploy order satisfies it. Nothing was deployed. Cure: correct the "parentDomain" of one entry in that cycle so parents form a chain, then re-run.`))}(i[a]??=[]).push(t)}return I(i.filter(t=>t.length>0))}m(Ce,"planDelegatedDomainWaves");async function We(e,o,c){const n=e.getDomains();if(n.length===0)return{domainsDeployed:0,domainsSkipped:0,errors:[]};o.onCascadePhaseStart?.("domains");const i=[];let t=0;for(const d of n){const l=me(d,c);if(l!==void 0){t++,o.onProgress?.({type:"warning",message:l});continue}i.push(d)}const a=i.filter(d=>d.type==="apex"),s=i.filter(d=>d.type==="delegated");let r=0;const u=[],C=Ce(s);if(!C.success)return u.push(C.error.message),o.onCascadePhaseComplete?.("domains"),{domainsDeployed:r,domainsSkipped:t,errors:u};const p=C.data;for(const d of a){const l=await e.deployDomain(d.name,o);l.success?r++:u.push(`${d.name}: ${l.error.message}`)}for(const d of p){const l=await Promise.allSettled(d.map(h=>{const f=e.delegatedDeployer?.(h.name);return f!==void 0?ce({deployer:f,callbacks:o,...c?.abortSignal!==void 0?{abortSignal:c.abortSignal}:{},...c?.skipCaaPreflight!==void 0?{skipCaaPreflight:c.skipCaaPreflight}:{}}):e.deployDomain(h.name,o)}));for(let h=0;h<l.length;h++){const f=l[h],R=d[h];if(!(!f||!R))if(f.status==="fulfilled")f.value.success?r++:u.push(`${R.name}: ${f.value.error.message}`);else{const $=f.reason instanceof Error?f.reason.message:String(f.reason);u.push(`${R.name}: ${$}`)}}}return o.onCascadePhaseComplete?.("domains"),{domainsDeployed:r,domainsSkipped:t,errors:u}}m(We,"deployDomains");export{le as CASCADE_MAX_CONCURRENCY,He as buildAccountRegionPairs,ze as buildCascadeRoleArn,pe as buildRegionList,Te as cascadeHomeRegion,ge as cascadeOperationKey,Ge as deployCascadeAccount,We as deployDomains,Be as partitionAccounts,Ce as planDelegatedDomainWaves,Ve as probeCascadeRoles,Ue as readPlatformIpamPoolIds};
1
+ var Y=Object.defineProperty;var g=(e,n)=>Y(e,"name",{value:n,configurable:!0});import{join as H}from"path";import{success as I,failure as w}from"@fjall/generator";import{logger as A}from"@fjall/util/logger";import{maskSensitiveOutput as S,mapSettledWithConcurrency as X,resolveSynthEnvironment as q}from"@fjall/util";import{ORGANISATION_TYPES as P,getOrganisationStackName as V}from"../../types/operations.js";import{CdkContextBuilder as J}from"../../services/supporting/CdkContextBuilder.js";import{stubCallerIdentity as Q}from"../../types/deployment/index.js";import{CloudFormationService as W}from"../../services/infrastructure/CloudFormationService.js";import{getCascadeStateFilePath as Z,regionSuffix as ee}from"../../types/config/FjallState.js";import{BackupClient as te}from"@aws-sdk/client-backup";import{accountHasDisasterRecovery as ne,describeBackupVaultExists as oe}from"../../aws/organisations/backup.js";import{assertAssemblyEngineCompat as re,buildParamsContext as ae,collectStackOutputs as G,assumeCascadeRole as E,emitStepWarnings as se,emitWarningEvent as ie,forwardOutput as N,reconcileOidcProviderIfCarried as U}from"../contextHelpers.js";import{assertLeaseBeforeStack as ce}from"../application/leaseGate.js";import{deployDelegatedDomain as de}from"../domain/delegatedDomainDeploy.js";import{normaliseRecordName as j}from"../domain/zoneClassifier.js";import{runDriftPreFlightGate as ue}from"../drift/preFlightGate.js";import{accountTier as _}from"@fjall/util";import{buildBootstrapTagsIfResolved as fe}from"../bootstrapTags.js";import{hasOrganisationTierAccount as le}from"../../aws/organisations/accountGlobals.js";import{DEFAULT_REGION as K}from"../../aws/utils/regions.js";const pe=4;function Te(e){const n=e.find(o=>_(o)==="platform"),c=e.filter(o=>_(o)==="account");return{platformAccount:n,memberAccounts:c}}g(Te,"partitionAccounts");function me(e){const n=e?.primaryRegion??K,c=e?.secondaryRegions??[],o=new Set([n,...c]),i=e?.disasterRecoveryRegion;return i&&o.add(i),[...o]}g(me,"buildRegionList");function He(e){return me(e)[0]??K}g(He,"cascadeHomeRegion");function ge(e,n){return`${e} (${n})`}g(ge,"cascadeOperationKey");function Ve(e,n){const c=[];for(const o of n)for(const i of e)c.push({account:i,region:o});return c}g(Ve,"buildAccountRegionPairs");import{buildCascadeRoleArn as Ye}from"../contextHelpers.js";async function We(e,n,c,o){c.onLog?.(`Verifying cascade role access for ${n.length} account(s)\u2026`,"info");const i=await X(n,pe,async a=>E(e.awsProvider,a.id,a.region??e.awsProvider.getRegion(),`fjall-preflight-${a.name}`,o)),t=[];return i.forEach((a,s)=>{const r=n[s];if(r){if(a.status==="rejected"){t.push({accountId:r.id,accountName:r.name,error:a.reason instanceof Error?a.reason.message:String(a.reason)});return}a.value.success||t.push({accountId:r.id,accountName:r.name,error:a.value.error.message})}}),t.length===0&&c.onLog?.(`Cascade role access verified for ${n.length} account(s)`,"info"),t}g(We,"probeCascadeRoles");async function Ge(e,n,c,o,i,t,a){const s=a?.region??o.region??n.awsProvider.getRegion(),r=ge(o.name,s),u=a?.orgConfig??e.orgConfig,C=a?.ipamPoolId;t.onCascadeAccountStart?.(r,o.id,s,i);const p=await E(n.awsProvider,o.id,s,`fjall-cascade-${o.name}`,e.abortSignal);if(!p.success)return t.onCascadeAccountComplete?.(r,!1,S(p.error.message),s),w(new Error(`Failed to assume role for ${o.name}: ${S(p.error.message)}`));const{provider:d,credentials:l}=p.data,h=H(e.workingDirectory,"fjall",i==="platform"?P.PLATFORM:P.ACCOUNT),f=H(h,`cdk.out.${o.id}.${ee(s)}`),R=J.buildDeploymentContext({deployType:i,target:c.target,path:h,assemblyDir:f,environment:q(o),region:s,accountName:o.name,callerIdentity:Q(o.id),ipamPoolId:C,...ae({orgConfig:u,identity:e.identity,skipOidc:e.options?.skipOidc,region:s,primaryRegion:a?.primaryRegion,trailLifecycle:o.trailLifecycle})},{verbose:e.options?.verbose},u);if(ne(o.environment,u?.disasterRecoveryRegion)){const m=await oe(d.getClient(te),e.abortSignal);if(!m.success)return t.onCascadeAccountComplete?.(r,!1,S(m.error.message),s),w(new Error(`Backup vault probe failed for ${o.name}: ${S(m.error.message)}`));R.fjallAdoptBackupVault=m.data}t.onCascadeAccountPhaseChange?.(r,"synth",s);const $=await n.cdkService.runCdkSynth(R,N(t),l);if(!$.success)return t.onCascadeAccountComplete?.(r,!1,S(`Synth failed: ${$.error}`),s),w(new Error(`Synth failed for ${o.name}: ${S($.error)}`));se(t,$.data);const b=re(f,t);if(!b.success){const m=S(b.error.message);return t.onCascadeAccountComplete?.(r,!1,m,s),w(new Error(`Engine compatibility check failed for ${o.name}: ${m}`))}const y=V(i==="platform"?P.PLATFORM:P.ACCOUNT),F=Z(h,o.id,s),v=new W(d),{changed:z,currentHash:L}=await n.hashService.compareCascadeStack(f,y,F);if(!z&&e.options?.force!==!0&&await v.stackExists(y,void 0,e.abortSignal)){const m=await v.getStackOutputs(y,void 0,e.abortSignal);m.success||A.debug("cascadeHelpers","Failed to read outputs for skipped cascade account (non-critical)",{stackName:y,account:o.name});const T=G(m);return await U(R,d,t,e.abortSignal),t.onLog?.(`${o.name}: no infrastructure changes \u2014 skipping deploy`,"info"),t.onCascadeAccountComplete?.(r,!0,void 0,s,T,!0),I({outputs:T,skipped:!0})}const D=await ue(d,{stackNames:[y],cdkOutPath:f,cfnService:v,callbacks:t,...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}});if(D.kind==="blocked")return t.onCascadeAccountComplete?.(r,!1,D.message,s),w(new Error(D.message));const O=await ce(e.assertLeaseForStack,y,e.abortSignal);if(O!==void 0)return t.onCascadeAccountComplete?.(r,!1,O.message,s),w(O);t.onCascadeAccountPhaseChange?.(r,"bootstrap",s);const x=await n.cdkService.runCdkBootstrap(R,N(t),l,void 0,fe({account:o,estate:le(u?.providerAccounts)?"org":"solo",...a?.orgId!==void 0?{orgId:a.orgId}:{}}));if(!x.success)return t.onCascadeAccountComplete?.(r,!1,S(`Bootstrap failed: ${x.error}`),s),w(new Error(`Bootstrap failed for ${o.name}: ${S(x.error)}`));t.onCascadeAccountPhaseChange?.(r,"deploy",s);const k=await n.cdkService.runCdkDeploy(R,y,N(t),m=>t.onCascadeAccountResourceProgress?.(r,m,s),d,l);if(!k.success)return t.onCascadeAccountComplete?.(r,!1,S(k.error),s),w(new Error(S(k.error)));const M=await v.getStackOutputs(y,void 0,e.abortSignal);M.success||A.debug("cascadeHelpers","Failed to read cascade account stack outputs (non-critical)",{stackName:y,account:o.name});const B=G(M);return await U(R,d,t,e.abortSignal),L!==void 0&&((await n.hashService.persistCascadeStack(F,y,L)).success||A.debug("cascadeHelpers","Failed to persist cascade hash state (non-critical)",{stackName:y,account:o.name})),t.onCascadeAccountComplete?.(r,!0,void 0,s,B,!1),I({outputs:B,skipped:!1})}g(Ge,"deployCascadeAccount");async function Ue(e,n,c,o){const i=new Map,t=e.awsProvider.getRegion(),a=await E(e.awsProvider,n.id,t,`fjall-ipam-read-${n.name}`,o);if(!a.success)return A.debug("organisationDeploy",`Cannot read Platform outputs: ${a.error.message}`),i;const s=new W(a.data.provider),r=V(P.PLATFORM),u=await s.getStackOutputs(r);if(!u.success)return A.debug("organisationDeploy",`Failed to read Platform stack outputs: ${u.error.message}`),i;const C=/^IpamPoolId(\d{12})(\w+)$/;for(const p of u.data){const d=p.OutputKey?.match(C);if(d&&p.OutputValue){const l=`${d[1]}-${d[2]}`;i.set(l,p.OutputValue)}}return i.size>0&&c.onLog?.(`Read ${i.size} IPAM pool ID(s) from Platform stack`,"info"),i}g(Ue,"readPlatformIpamPoolIds");function Ce(e,n){const c=e.account!==void 0&&n?.executingAccountId!==void 0&&e.account!==n.executingAccountId,o=e.region!==void 0&&n?.executingRegion!==void 0&&e.region!==n.executingRegion;if(c)return`[${e.name}] skipped: its fjall-config.json entry records account ${e.account} as its home, but this cascade runs in account ${n?.executingAccountId} - deploy it separately with 'fjall domain deploy ${e.name} -t <target in account ${e.account}>' or run the cascade under that account.`;if(o)return`[${e.name}] skipped: its fjall-config.json entry records region ${e.region} as its home, but this cascade runs in region ${n?.executingRegion} - deploy it separately with 'fjall domain deploy ${e.name} --region ${e.region}', or update the entry's "region" key if this move is intentional.`}g(Ce,"foreignDomainSkipReason");function he(e){const n=new Map;for(const t of e)n.set(j(t.name),t);const c=new Map,o=g((t,a)=>{const s=c.get(t);if(s!==void 0)return s;if(a.includes(t))return[...a.slice(a.indexOf(t)),t];const r=n.get(t);if(r===void 0)return-1;const u=r.parentDomain!==void 0?j(r.parentDomain):void 0,C=u===void 0?-1:o(u,[...a,t]);if(Array.isArray(C))return C;const p=C+1;return c.set(t,p),p},"resolveDepth"),i=[];for(const t of e){const a=o(j(t.name),[]);if(Array.isArray(a)){const s=a.map(r=>n.get(r)?.name??r).join(" -> ");return w(new Error(`Delegated domain ordering: fjall-config.json declares a parentDomain cycle (${s}) - no deploy order satisfies it. Nothing was deployed. Cure: correct the "parentDomain" of one entry in that cycle so parents form a chain, then re-run.`))}(i[a]??=[]).push(t)}return I(i.filter(t=>t.length>0))}g(he,"planDelegatedDomainWaves");async function _e(e,n,c){const o=e.getDomains();if(o.length===0)return{domainsDeployed:0,domainsSkipped:0,errors:[]};n.onCascadePhaseStart?.("domains");const i=[];let t=0;for(const d of o){const l=Ce(d,c);if(l!==void 0){t++,ie(n,l);continue}i.push(d)}const a=i.filter(d=>d.type==="apex"),s=i.filter(d=>d.type==="delegated");let r=0;const u=[],C=he(s);if(!C.success)return u.push(C.error.message),n.onCascadePhaseComplete?.("domains"),{domainsDeployed:r,domainsSkipped:t,errors:u};const p=C.data;for(const d of a){const l=await e.deployDomain(d.name,n);l.success?r++:u.push(`${d.name}: ${l.error.message}`)}for(const d of p){const l=await Promise.allSettled(d.map(h=>{const f=e.delegatedDeployer?.(h.name);return f!==void 0?de({deployer:f,callbacks:n,...c?.abortSignal!==void 0?{abortSignal:c.abortSignal}:{},...c?.skipCaaPreflight!==void 0?{skipCaaPreflight:c.skipCaaPreflight}:{}}):e.deployDomain(h.name,n)}));for(let h=0;h<l.length;h++){const f=l[h],R=d[h];if(!(!f||!R))if(f.status==="fulfilled")f.value.success?r++:u.push(`${R.name}: ${f.value.error.message}`);else{const $=f.reason instanceof Error?f.reason.message:String(f.reason);u.push(`${R.name}: ${$}`)}}}return n.onCascadePhaseComplete?.("domains"),{domainsDeployed:r,domainsSkipped:t,errors:u}}g(_e,"deployDomains");export{pe as CASCADE_MAX_CONCURRENCY,Ve as buildAccountRegionPairs,Ye as buildCascadeRoleArn,me as buildRegionList,He as cascadeHomeRegion,ge as cascadeOperationKey,Ge as deployCascadeAccount,_e as deployDomains,Te as partitionAccounts,he as planDelegatedDomainWaves,We as probeCascadeRoles,Ue as readPlatformIpamPoolIds};
@@ -1,5 +1,5 @@
1
- var V=Object.defineProperty;var _=(o,e)=>V(o,"name",{value:e,configurable:!0});import{join as Y}from"node:path";import{OrganizationsClient as X}from"@aws-sdk/client-organizations";import{success as Z,failure as z}from"@fjall/generator";import{ORGANISATION_TYPES as I,getOrganisationStackName as A}from"../../types/operations.js";import{synthOrFail as tt,bootstrapOrFail as et,forwardOutput as ot,forwardResourceProgress as at}from"../contextHelpers.js";import{partitionAccounts as rt,probeCascadeRoles as nt,buildRegionList as it,buildAccountRegionPairs as ct}from"../organisation/cascadeHelpers.js";import{assertLeaseBeforeStack as st}from"../application/leaseGate.js";import{accountTier as dt,maskSensitiveOutput as g}from"@fjall/util";import{findDevelopmentOuId as ut}from"../../aws/organisations/organisationalUnits.js";import{buildOrgContext as lt,resolveOrgDetails as gt}from"./orgContext.js";import{buildBootstrapTagsIfResolved as ft}from"../bootstrapTags.js";import{INFRA_STEPS as K,emitOrgStackTargets as pt,maskAndFail as O,readStackOutputsBestEffort as U}from"./infraSteps.js";import{resolveCascadeAccounts as mt}from"./resolveCascadeAccounts.js";import{executeCascade as St}from"./cascadeExecution.js";import{reconcileOrgTrailOutputs as ht}from"./trailReconciliation.js";import{runDriftPreFlightGate as Ot}from"../drift/preFlightGate.js";async function Gt(o,e,R,q){const{callbacks:t,options:T}=o,{providerAccounts:f,effectiveOrgConfig:J,defaultRegion:Q}=await mt(o,e),p=await gt(e,o.abortSignal);if(!p.success)return O(t,p.error.message);const w=await ut(e.awsProvider.getClient(X),p.data.rootId,o.abortSignal);if(!w.success)return O(t,w.error.message);const P={...p.data,...w.data!==void 0?{devOuId:w.data}:{}},E=f.find(a=>dt(a)==="organisation"),d=lt(o,e,R,"organisation",P,void 0,E?.trailLifecycle),l=T?.cascade!==!1,{platformAccount:s,memberAccounts:N}=rt(f),L=l&&s!==void 0?1:0,F=l&&N.length>0?1:0,i=2+L+F,x=l?[...s!==void 0?[s]:[],...N]:[];if(x.length>0){const a=await nt(e,x,t,o.abortSignal),r=s!==void 0?a.find(n=>n.accountId===s.id):void 0;if(r!==void 0)return O(t,`Pre-flight cascade role check failed for the platform account ${r.accountName} (${r.accountId}): ${r.error}`);for(const n of a)t.onProgress?.({type:"warning",message:g(`Pre-flight cascade role check failed for ${n.accountName} (${n.accountId}) \u2014 its cascade deploy is expected to fail: ${n.error}`)})}t.onCascadeAccountsReconciled?.({hasPlatformAccount:L>0,hasMemberAccounts:F>0});const{id:C,name:b}=K.PREPARE;t.onStepStart?.(C,b,0,i),t.onLog?.("Synthesising organisation infrastructure\u2026","info");const G=await tt(e,d,t,"CDK synthesis failed");if(!G.success)return t.onStepComplete?.(C,b,"error",0,i),G;const H=e.awsProvider.getAccountId(),$=e.awsProvider.getRegion();pt(t,[{stackName:A(I.ORGANISATION),...H!==""?{accountId:H}:{},...$!==""?{region:$}:{}},...l&&s!==void 0?[{stackName:A(I.PLATFORM),accountId:s.id,region:s.region??$}]:[],...l?ct(N,it(o.orgConfig)).map(({account:a,region:r})=>({stackName:A(I.ACCOUNT),accountId:a.id,region:r})):[]]);const M=await et(e,d,t,ft({account:E,estate:"org",orgId:P.orgId}));if(!M.success)return t.onStepComplete?.(C,b,"error",0,i),M;t.onStepComplete?.(C,b,"completed",0,i);const{id:m,name:S}=K.ORG_DEPLOY,c=A(I.ORGANISATION);let j=!0;const h=await e.hashService.getTemplateHashes(Y(d.path,"cdk.out"));if(h.success){const a=await e.hashService.compareWithState(h.data,d.path);a.success?j=a.data.stackChanges.get(c)??!0:t.onLog?.(g(`Org root change detection failed \u2014 deploying to be safe: ${a.error.message}`),"warn")}else t.onLog?.(g(`Org root template hashing failed \u2014 deploying to be safe: ${h.error.message}`),"warn");const D=j||T?.force===!0||!await e.cfnService.stackExists(c,void 0,o.abortSignal);t.onOrgChangesDetected?.({hasOrgChanges:D});let y;if(D){t.onStepStart?.(m,S,1,i);const a=await Ot(e.awsProvider,{stackNames:[c],cdkOutPath:Y(d.path,"cdk.out"),cfnService:e.cfnService,callbacks:t,...o.abortSignal!==void 0?{abortSignal:o.abortSignal}:{}});if(a.kind==="blocked")return t.onStepComplete?.(m,S,"error",1,i),O(t,a.message);const r=await st(o.assertLeaseForStack,c,o.abortSignal);if(r!==void 0)return t.onStepComplete?.(m,S,"error",1,i),t.onError?.(r),z(r);const n=await e.cdkService.runCdkDeploy(d,c,ot(t),at(t),e.awsProvider);if(!n.success)return t.onStepComplete?.(m,S,"error",1,i),O(t,n.error);y=await U(e,t,c,"Failed to read org stack outputs (non-critical)",o.abortSignal);const B=h.success?h.data.get(c):void 0;if(B!==void 0){const W=await e.hashService.updateStateAfterDeploy(d.path,new Map([[c,B]]));W.success||t.onLog?.(`Warning: failed to update state file \u2014 next deploy may re-deploy the org root: ${g(W.error.message)}`,"warn")}t.onStepComplete?.(m,S,"completed",1,i)}else t.onLog?.("Organisation root: no infrastructure changes \u2014 skipping deploy","info"),y=await U(e,t,c,"Failed to read org stack outputs (non-critical)",o.abortSignal);const u=[],k=[];let v=D;if(l&&f.length>0){const{anyCascadeDeployHappened:a}=await St(o,e,R,{providerAccounts:f,effectiveOrgConfig:J,totalSteps:i,cascadeErrors:u,allCascadeOutputs:k,orgId:P.orgId});if(a&&(v=!0),await ht(o,e,{orgOutputs:y,allCascadeOutputs:k,orgDetails:p.data,providerAccounts:f,defaultRegion:Q}),u.length>0){const r=u.map(n=>` ${n.accountId}: ${n.error}`).join(`
1
+ var V=Object.defineProperty;var _=(o,e)=>V(o,"name",{value:e,configurable:!0});import{join as Y}from"node:path";import{OrganizationsClient as X}from"@aws-sdk/client-organizations";import{success as Z,failure as z}from"@fjall/generator";import{ORGANISATION_TYPES as I,getOrganisationStackName as A}from"../../types/operations.js";import{synthOrFail as tt,bootstrapOrFail as et,emitWarningEvent as ot,forwardOutput as at,forwardResourceProgress as rt}from"../contextHelpers.js";import{partitionAccounts as nt,probeCascadeRoles as it,buildRegionList as ct,buildAccountRegionPairs as st}from"../organisation/cascadeHelpers.js";import{assertLeaseBeforeStack as dt}from"../application/leaseGate.js";import{accountTier as ut,maskSensitiveOutput as g}from"@fjall/util";import{findDevelopmentOuId as lt}from"../../aws/organisations/organisationalUnits.js";import{buildOrgContext as gt,resolveOrgDetails as ft}from"./orgContext.js";import{buildBootstrapTagsIfResolved as pt}from"../bootstrapTags.js";import{INFRA_STEPS as K,emitOrgStackTargets as mt,maskAndFail as O,readStackOutputsBestEffort as U}from"./infraSteps.js";import{resolveCascadeAccounts as St}from"./resolveCascadeAccounts.js";import{executeCascade as ht}from"./cascadeExecution.js";import{reconcileOrgTrailOutputs as Ot}from"./trailReconciliation.js";import{runDriftPreFlightGate as wt}from"../drift/preFlightGate.js";async function Ht(o,e,R,q){const{callbacks:t,options:E}=o,{providerAccounts:f,effectiveOrgConfig:J,defaultRegion:Q}=await St(o,e),p=await ft(e,o.abortSignal);if(!p.success)return O(t,p.error.message);const w=await lt(e.awsProvider.getClient(X),p.data.rootId,o.abortSignal);if(!w.success)return O(t,w.error.message);const P={...p.data,...w.data!==void 0?{devOuId:w.data}:{}},T=f.find(a=>ut(a)==="organisation"),d=gt(o,e,R,"organisation",P,void 0,T?.trailLifecycle),l=E?.cascade!==!1,{platformAccount:s,memberAccounts:N}=nt(f),L=l&&s!==void 0?1:0,F=l&&N.length>0?1:0,i=2+L+F,x=l?[...s!==void 0?[s]:[],...N]:[];if(x.length>0){const a=await it(e,x,t,o.abortSignal),r=s!==void 0?a.find(n=>n.accountId===s.id):void 0;if(r!==void 0)return O(t,`Pre-flight cascade role check failed for the platform account ${r.accountName} (${r.accountId}): ${r.error}`);for(const n of a)ot(t,g(`Pre-flight cascade role check failed for ${n.accountName} (${n.accountId}) \u2014 its cascade deploy is expected to fail: ${n.error}`))}t.onCascadeAccountsReconciled?.({hasPlatformAccount:L>0,hasMemberAccounts:F>0});const{id:C,name:b}=K.PREPARE;t.onStepStart?.(C,b,0,i),t.onLog?.("Synthesising organisation infrastructure\u2026","info");const G=await tt(e,d,t,"CDK synthesis failed");if(!G.success)return t.onStepComplete?.(C,b,"error",0,i),G;const H=e.awsProvider.getAccountId(),$=e.awsProvider.getRegion();mt(t,[{stackName:A(I.ORGANISATION),...H!==""?{accountId:H}:{},...$!==""?{region:$}:{}},...l&&s!==void 0?[{stackName:A(I.PLATFORM),accountId:s.id,region:s.region??$}]:[],...l?st(N,ct(o.orgConfig)).map(({account:a,region:r})=>({stackName:A(I.ACCOUNT),accountId:a.id,region:r})):[]]);const M=await et(e,d,t,pt({account:T,estate:"org",orgId:P.orgId}));if(!M.success)return t.onStepComplete?.(C,b,"error",0,i),M;t.onStepComplete?.(C,b,"completed",0,i);const{id:m,name:S}=K.ORG_DEPLOY,c=A(I.ORGANISATION);let v=!0;const h=await e.hashService.getTemplateHashes(Y(d.path,"cdk.out"));if(h.success){const a=await e.hashService.compareWithState(h.data,d.path);a.success?v=a.data.stackChanges.get(c)??!0:t.onLog?.(g(`Org root change detection failed \u2014 deploying to be safe: ${a.error.message}`),"warn")}else t.onLog?.(g(`Org root template hashing failed \u2014 deploying to be safe: ${h.error.message}`),"warn");const D=v||E?.force===!0||!await e.cfnService.stackExists(c,void 0,o.abortSignal);t.onOrgChangesDetected?.({hasOrgChanges:D});let k;if(D){t.onStepStart?.(m,S,1,i);const a=await wt(e.awsProvider,{stackNames:[c],cdkOutPath:Y(d.path,"cdk.out"),cfnService:e.cfnService,callbacks:t,...o.abortSignal!==void 0?{abortSignal:o.abortSignal}:{}});if(a.kind==="blocked")return t.onStepComplete?.(m,S,"error",1,i),O(t,a.message);const r=await dt(o.assertLeaseForStack,c,o.abortSignal);if(r!==void 0)return t.onStepComplete?.(m,S,"error",1,i),t.onError?.(r),z(r);const n=await e.cdkService.runCdkDeploy(d,c,at(t),rt(t),e.awsProvider);if(!n.success)return t.onStepComplete?.(m,S,"error",1,i),O(t,n.error);k=await U(e,t,c,"Failed to read org stack outputs (non-critical)",o.abortSignal);const j=h.success?h.data.get(c):void 0;if(j!==void 0){const B=await e.hashService.updateStateAfterDeploy(d.path,new Map([[c,j]]));B.success||t.onLog?.(`Warning: failed to update state file \u2014 next deploy may re-deploy the org root: ${g(B.error.message)}`,"warn")}t.onStepComplete?.(m,S,"completed",1,i)}else t.onLog?.("Organisation root: no infrastructure changes \u2014 skipping deploy","info"),k=await U(e,t,c,"Failed to read org stack outputs (non-critical)",o.abortSignal);const u=[],y=[];let W=D;if(l&&f.length>0){const{anyCascadeDeployHappened:a}=await ht(o,e,R,{providerAccounts:f,effectiveOrgConfig:J,totalSteps:i,cascadeErrors:u,allCascadeOutputs:y,orgId:P.orgId});if(a&&(W=!0),await Ot(o,e,{orgOutputs:k,allCascadeOutputs:y,orgDetails:p.data,providerAccounts:f,defaultRegion:Q}),u.length>0){const r=u.map(n=>` ${n.accountId}: ${n.error}`).join(`
2
2
  `);t.onLog?.(g(`Cascade failed for ${u.length} target(s):
3
3
  ${r}`),"warn")}}if(u.length>0){const a=u.map(n=>g(`${n.accountId}: ${n.error}`)).join(`
4
4
  `),r=new Error(`Organisation root deployed, but the cascade failed for ${u.length} target(s):
5
- ${a}`);return t.onError?.(r),z(r)}return Z({target:R.target,deploymentType:"organisation",outputs:y,artefacts:[],...k.length>0?{cascadeOutputs:k}:{},...v?{}:{noChanges:!0},durationMs:Date.now()-q})}_(Gt,"deployOrgWithCascade");export{Gt as deployOrgWithCascade};
5
+ ${a}`);return t.onError?.(r),z(r)}return Z({target:R.target,deploymentType:"organisation",outputs:k,artefacts:[],...y.length>0?{cascadeOutputs:y}:{},...W?{}:{noChanges:!0},durationMs:Date.now()-q})}_(Ht,"deployOrgWithCascade");export{Ht as deployOrgWithCascade};
@@ -1 +1 @@
1
- var l=Object.defineProperty;var g=(o,i)=>l(o,"name",{value:i,configurable:!0});import{cascadeHomeRegion as d}from"../organisation/cascadeHelpers.js";import{reconcileProviderAccounts as f,mergeReconciledProviderAccounts as A}from"../organisation/reconcileProviderAccounts.js";import{accountTier as m,maskSensitiveOutput as a}from"@fjall/util";async function h(o,i){const{callbacks:c}=o;let n=o.orgConfig?.providerAccounts??[];if(n.length===0||n.every(e=>m(e)==="organisation")){const e=await f(i,o.workingDirectory);if(e.success){const{providerAccounts:t,missingAccountNames:r}=e.data;t.length>0&&(n=A(o.orgConfig,t).providerAccounts,c.onLog?.(`Reconciled ${t.length} account(s) from AWS Organizations`,"info")),r.length>0&&(c.onCascadeMissingAccounts?.(r),c.onProgress?.({type:"warning",message:a(`Accounts declared in ACCOUNTS but not yet in AWS Organizations (cascade will skip): ${r.join(", ")}`)}))}else c.onProgress?.({type:"warning",message:a(`Could not reconcile accounts from AWS Organizations \u2014 cascade may skip accounts: ${e.error.message}`)})}const s=d(o.orgConfig);n=n.map(e=>e.region!==void 0?e:{...e,region:s});const u=o.orgConfig!==void 0?{...o.orgConfig,providerAccounts:n}:n.length>0?{providerAccounts:n}:void 0;return{providerAccounts:n,effectiveOrgConfig:u,defaultRegion:s}}g(h,"resolveCascadeAccounts");export{h as resolveCascadeAccounts};
1
+ var d=Object.defineProperty;var g=(o,i)=>d(o,"name",{value:i,configurable:!0});import{cascadeHomeRegion as f}from"../organisation/cascadeHelpers.js";import{reconcileProviderAccounts as A,mergeReconciledProviderAccounts as m}from"../organisation/reconcileProviderAccounts.js";import{emitWarningEvent as u}from"../contextHelpers.js";import{accountTier as v,maskSensitiveOutput as l}from"@fjall/util";async function R(o,i){const{callbacks:c}=o;let n=o.orgConfig?.providerAccounts??[];if(n.length===0||n.every(e=>v(e)==="organisation")){const e=await A(i,o.workingDirectory);if(e.success){const{providerAccounts:t,missingAccountNames:r}=e.data;t.length>0&&(n=m(o.orgConfig,t).providerAccounts,c.onLog?.(`Reconciled ${t.length} account(s) from AWS Organizations`,"info")),r.length>0&&(c.onCascadeMissingAccounts?.(r),u(c,l(`Accounts declared in ACCOUNTS but not yet in AWS Organizations (cascade will skip): ${r.join(", ")}`)))}else u(c,l(`Could not reconcile accounts from AWS Organizations \u2014 cascade may skip accounts: ${e.error.message}`))}const s=f(o.orgConfig);n=n.map(e=>e.region!==void 0?e:{...e,region:s});const a=o.orgConfig!==void 0?{...o.orgConfig,providerAccounts:n}:n.length>0?{providerAccounts:n}:void 0;return{providerAccounts:n,effectiveOrgConfig:a,defaultRegion:s}}g(R,"resolveCascadeAccounts");export{R as resolveCascadeAccounts};
@@ -1 +1 @@
1
- var $=Object.defineProperty;var f=(n,i)=>$(n,"name",{value:i,configurable:!0});import{maskSensitiveOutput as p}from"@fjall/util";import{ACCOUNT_TRAIL_NAME as L,ORG_TRAIL_BUCKET_OUTPUT_KEY as R,TRAIL_BUCKET_OUTPUT_KEY as v,TRAIL_KEY_ARN_OUTPUT_KEY as w}from"@fjall/util/config";import{verifyOrgTrailDelivery as A}from"../../aws/cloudtrail/orgTrailDelivery.js";import{decommissionMemberTrailStorage as _}from"./memberTrailCleanup.js";function I(n,i){if(n==="account")return{action:"hold",reason:"pinned to a per-account trail"};if(n==="org")return{action:"hold",reason:"already migrated to the org trail"};if(n===void 0)return i.orgDeliveryVerified===!0?{action:"advance",to:"draining"}:{action:"hold",reason:i.orgDeliveryVerified===!1?"org-trail delivery not yet verified (first delivery can take up to 24h)":"org-trail delivery could not be determined"};switch(i.decommissionOutcome){case"decommissioned":return{action:"advance",to:"org"};case"blocked-trail-still-exists":return{action:"hold",reason:"per-account trail still exists \u2014 draining deploy not yet applied"};case"blocked-awaiting-acknowledgement":return{action:"hold",reason:"awaiting acknowledgeTrailHistoryLoss before discarding history"};case"failed":return{action:"hold",reason:"decommission attempt failed"};default:return{action:"hold",reason:"decommission was not attempted"}}}f(I,"decideNextTransition");function r(n,i){n.onTrailMigrationPhase?.({...i,...i.detail!==void 0?{detail:p(i.detail)}:{}})}f(r,"emitPhase");async function D(n,i,o){const d=[],m=i.accounts.filter(e=>e.trailLifecycle===void 0),N=i.accounts.filter(e=>e.trailLifecycle==="draining"),y=new Map;if(m.length>0){r(o,{accountId:"*",accountName:"organisation",phase:"verify-delivery",status:"started",detail:`Checking org-trail delivery for ${m.length} account(s) in s3://${i.orgTrailBucketName}`});const e=await A(n.managementS3Client,{bucketName:i.orgTrailBucketName,orgId:i.orgId,accountIds:m.map(t=>t.id),...i.recencyWindowMs!==void 0?{recencyWindowMs:i.recencyWindowMs}:{},...i.abortSignal!==void 0?{abortSignal:i.abortSignal}:{}});if(e.success){for(const t of e.data.perAccount)y.set(t.accountId,t.recentDelivery===void 0?void 0:t.delivered&&t.recentDelivery);r(o,{accountId:"*",accountName:"organisation",phase:"verify-delivery",status:"completed"})}else r(o,{accountId:"*",accountName:"organisation",phase:"verify-delivery",status:"failed",detail:e.error.message})}for(const e of m){const t={...y.get(e.id)!==void 0?{orgDeliveryVerified:y.get(e.id)}:{}},s=I(void 0,t);s.action==="advance"?(o.onTrailLifecycleChanged?.(e.id,void 0,s.to),o.onLog?.(`${e.name}: org-trail delivery verified \u2014 trail lifecycle advanced to "draining" (the next deploy removes its per-account trail)`,"info"),d.push({accountId:e.id,accountName:e.name,from:void 0,to:s.to})):d.push({accountId:e.id,accountName:e.name,from:void 0,heldReason:s.reason})}for(const e of N){const t=e.region??i.defaultRegion,s=i.cascadeOutputs.get(e.id),c=s?.[v],h=s?.[w];if(c===void 0||c===""){const a=`stack output ${v} unavailable for this run`;o.onProgress?.({type:"warning",message:`${e.name}: trail decommission skipped \u2014 ${a}. The account stays "draining"; the next deploy retries.`}),d.push({accountId:e.id,accountName:e.name,from:"draining",heldReason:a});continue}r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"started"});let l;const u=await n.getMemberClients(e,t);if(!u.success)l={decommissionOutcome:"failed"},o.onProgress?.({type:"warning",message:p(`${e.name}: trail decommission failed \u2014 ${u.error.message}. The account stays "draining"; the next deploy retries.`)}),r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"failed",detail:u.error.message});else{const a=await _(u.data,{accountId:e.id,trailName:L,bucketName:c,...h!==void 0&&h!==""?{keyArn:h}:{},acknowledgeTrailHistoryLoss:e.acknowledgeTrailHistoryLoss===!0,...i.abortSignal!==void 0?{abortSignal:i.abortSignal}:{}},o);if(!a.success)l={decommissionOutcome:"failed"},o.onProgress?.({type:"warning",message:p(`${e.name}: trail decommission failed \u2014 ${a.error.message}. The account stays "draining"; the next deploy retries.`)}),r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"failed",detail:a.error.message});else if(l={decommissionOutcome:a.data.outcome},a.data.outcome==="blocked-awaiting-acknowledgement"){const T=`${e.name}: per-account trail removed, but its log history in s3://${c} will be DISCARDED on decommission. Back the bucket up if the history matters, then set acknowledgeTrailHistoryLoss: true for account ${e.id} and redeploy.`;o.onProgress?.({type:"warning",message:T}),r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"blocked",detail:T})}else a.data.outcome==="blocked-trail-still-exists"?r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"blocked",detail:"per-account trail still exists \u2014 the draining deploy has not been applied yet"}):r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"completed",detail:`bucket s3://${c} removed; CMK scheduled for deletion`})}const g=I("draining",l);g.action==="advance"?(o.onTrailLifecycleChanged?.(e.id,"draining",g.to),o.onLog?.(`${e.name}: trail storage decommissioned \u2014 trail lifecycle advanced to "org"`,"info"),d.push({accountId:e.id,accountName:e.name,from:"draining",to:g.to})):d.push({accountId:e.id,accountName:e.name,from:"draining",heldReason:g.reason})}return d}f(D,"reconcileTrailMigration");export{R as ORG_TRAIL_BUCKET_OUTPUT_KEY,v as TRAIL_BUCKET_OUTPUT_KEY,w as TRAIL_KEY_ARN_OUTPUT_KEY,I as decideNextTransition,D as reconcileTrailMigration};
1
+ var L=Object.defineProperty;var g=(t,i)=>L(t,"name",{value:i,configurable:!0});import{maskSensitiveOutput as v}from"@fjall/util";import{ACCOUNT_TRAIL_NAME as R,ORG_TRAIL_BUCKET_OUTPUT_KEY as A,TRAIL_BUCKET_OUTPUT_KEY as T,TRAIL_KEY_ARN_OUTPUT_KEY as N}from"@fjall/util/config";import{verifyOrgTrailDelivery as _}from"../../aws/cloudtrail/orgTrailDelivery.js";import{decommissionMemberTrailStorage as x}from"./memberTrailCleanup.js";import{emitWarningEvent as y}from"../contextHelpers.js";function w(t,i){if(t==="account")return{action:"hold",reason:"pinned to a per-account trail"};if(t==="org")return{action:"hold",reason:"already migrated to the org trail"};if(t===void 0)return i.orgDeliveryVerified===!0?{action:"advance",to:"draining"}:{action:"hold",reason:i.orgDeliveryVerified===!1?"org-trail delivery not yet verified (first delivery can take up to 24h)":"org-trail delivery could not be determined"};switch(i.decommissionOutcome){case"decommissioned":return{action:"advance",to:"org"};case"blocked-trail-still-exists":return{action:"hold",reason:"per-account trail still exists \u2014 draining deploy not yet applied"};case"blocked-awaiting-acknowledgement":return{action:"hold",reason:"awaiting acknowledgeTrailHistoryLoss before discarding history"};case"failed":return{action:"hold",reason:"decommission attempt failed"};default:return{action:"hold",reason:"decommission was not attempted"}}}g(w,"decideNextTransition");function r(t,i){t.onTrailMigrationPhase?.({...i,...i.detail!==void 0?{detail:v(i.detail)}:{}})}g(r,"emitPhase");async function U(t,i,o){const s=[],m=i.accounts.filter(e=>e.trailLifecycle===void 0),$=i.accounts.filter(e=>e.trailLifecycle==="draining"),h=new Map;if(m.length>0){r(o,{accountId:"*",accountName:"organisation",phase:"verify-delivery",status:"started",detail:`Checking org-trail delivery for ${m.length} account(s) in s3://${i.orgTrailBucketName}`});const e=await _(t.managementS3Client,{bucketName:i.orgTrailBucketName,orgId:i.orgId,accountIds:m.map(n=>n.id),...i.recencyWindowMs!==void 0?{recencyWindowMs:i.recencyWindowMs}:{},...i.abortSignal!==void 0?{abortSignal:i.abortSignal}:{}});if(e.success){for(const n of e.data.perAccount)h.set(n.accountId,n.recentDelivery===void 0?void 0:n.delivered&&n.recentDelivery);r(o,{accountId:"*",accountName:"organisation",phase:"verify-delivery",status:"completed"})}else r(o,{accountId:"*",accountName:"organisation",phase:"verify-delivery",status:"failed",detail:e.error.message})}for(const e of m){const n={...h.get(e.id)!==void 0?{orgDeliveryVerified:h.get(e.id)}:{}},d=w(void 0,n);d.action==="advance"?(o.onTrailLifecycleChanged?.(e.id,void 0,d.to),o.onLog?.(`${e.name}: org-trail delivery verified \u2014 trail lifecycle advanced to "draining" (the next deploy removes its per-account trail)`,"info"),s.push({accountId:e.id,accountName:e.name,from:void 0,to:d.to})):s.push({accountId:e.id,accountName:e.name,from:void 0,heldReason:d.reason})}for(const e of $){const n=e.region??i.defaultRegion,d=i.cascadeOutputs.get(e.id),c=d?.[T],p=d?.[N];if(c===void 0||c===""){const a=`stack output ${T} unavailable for this run`;y(o,`${e.name}: trail decommission skipped \u2014 ${a}. The account stays "draining"; the next deploy retries.`),s.push({accountId:e.id,accountName:e.name,from:"draining",heldReason:a});continue}r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"started"});let l;const u=await t.getMemberClients(e,n);if(!u.success)l={decommissionOutcome:"failed"},y(o,v(`${e.name}: trail decommission failed \u2014 ${u.error.message}. The account stays "draining"; the next deploy retries.`)),r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"failed",detail:u.error.message});else{const a=await x(u.data,{accountId:e.id,trailName:R,bucketName:c,...p!==void 0&&p!==""?{keyArn:p}:{},acknowledgeTrailHistoryLoss:e.acknowledgeTrailHistoryLoss===!0,...i.abortSignal!==void 0?{abortSignal:i.abortSignal}:{}},o);if(!a.success)l={decommissionOutcome:"failed"},y(o,v(`${e.name}: trail decommission failed \u2014 ${a.error.message}. The account stays "draining"; the next deploy retries.`)),r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"failed",detail:a.error.message});else if(l={decommissionOutcome:a.data.outcome},a.data.outcome==="blocked-awaiting-acknowledgement"){const I=`${e.name}: per-account trail removed, but its log history in s3://${c} will be DISCARDED on decommission. Back the bucket up if the history matters, then set acknowledgeTrailHistoryLoss: true for account ${e.id} and redeploy.`;y(o,I),r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"blocked",detail:I})}else a.data.outcome==="blocked-trail-still-exists"?r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"blocked",detail:"per-account trail still exists \u2014 the draining deploy has not been applied yet"}):r(o,{accountId:e.id,accountName:e.name,phase:"decommission",status:"completed",detail:`bucket s3://${c} removed; CMK scheduled for deletion`})}const f=w("draining",l);f.action==="advance"?(o.onTrailLifecycleChanged?.(e.id,"draining",f.to),o.onLog?.(`${e.name}: trail storage decommissioned \u2014 trail lifecycle advanced to "org"`,"info"),s.push({accountId:e.id,accountName:e.name,from:"draining",to:f.to})):s.push({accountId:e.id,accountName:e.name,from:"draining",heldReason:f.reason})}return s}g(U,"reconcileTrailMigration");export{A as ORG_TRAIL_BUCKET_OUTPUT_KEY,T as TRAIL_BUCKET_OUTPUT_KEY,N as TRAIL_KEY_ARN_OUTPUT_KEY,w as decideNextTransition,U as reconcileTrailMigration};
@@ -1,4 +1,4 @@
1
- var B=Object.defineProperty;var P=(m,e)=>B(m,"name",{value:e,configurable:!0});import{spawn as O}from"child_process";import{existsSync as E}from"fs";import{join as y}from"path";import{createRequire as _}from"module";import{logger as I}from"@fjall/util/logger";import{filterDangerousEnvVars as N,maskSensitiveOutput as p}from"@fjall/util";import{success as $,failure as n}from"@fjall/generator";import{getErrorMessage as M}from"@fjall/util";import{ensureDependencyIntegrity as H}from"./dependencyIntegrityGate.js";function L(){try{const e=_(import.meta.url).resolve("aws-cdk/bin/cdk");return $({command:process.execPath,prefixArgs:[e]})}catch(m){return I.error("CdkService","Failed to resolve the bundled aws-cdk CLI",{error:p(M(m))}),n("Fjall could not locate its bundled aws-cdk CLI. The deploy toolchain looks misconfigured \u2014 reinstall dependencies (npm install) or reinstall the Fjall CLI, then try again.")}}P(L,"getCdkBinaryPath");const D=5e3,R=1800*1e3;function A(m,e){const i=e??(t=>{process.stderr.write(t)});for(const t of m)i(`[warn] ${t}
2
- `)}P(A,"emitGateWarnings");class Y{static{P(this,"CdkProcessManager")}runningProcesses=new Map;processCounter=0;argBuilder;abortSignal;exitHandler;sigintHandler;sigtermHandler;constructor(e,i){this.argBuilder=e,this.abortSignal=i,this.exitHandler=()=>this.cleanup(),this.sigintHandler=()=>{this.abortSignal===void 0&&(this.cleanup(),process.exit(130))},this.sigtermHandler=()=>{this.abortSignal===void 0&&(this.cleanup(),process.exit(143))},process.on("exit",this.exitHandler),process.on("SIGINT",this.sigintHandler),process.on("SIGTERM",this.sigtermHandler)}forceKillProcess(e){e.stdout?.destroy(),e.stderr?.destroy(),e.kill("SIGTERM");const i=setTimeout(()=>{e.exitCode===null&&e.kill("SIGKILL")},D);i.unref(),e.once("exit",()=>clearTimeout(i))}cleanup(){for(const[e,i]of this.runningProcesses)i.killed||(i.stdout?.destroy(),i.stderr?.destroy(),i.kill("SIGTERM"));this.runningProcesses.clear()}dispose(){this.cleanup(),process.removeListener("exit",this.exitHandler),process.removeListener("SIGINT",this.sigintHandler),process.removeListener("SIGTERM",this.sigtermHandler)}async runCdkCommandPassthrough(e,i,t){if(!E(e))return n(`Directory not found: ${e}`);const u=y(e,"cdk.json");if(!E(u))return n(`No CDK project found in ${e}`);const o=await H(e,{onOutput:t?.outputCallback??(a=>{process.stdout.write(a)}),...this.abortSignal!==void 0?{abortSignal:this.abortSignal}:{}});return o.success?(A(o.data.warnings,t?.outputCallback),new Promise(a=>{const f=L();if(!f.success){a(n(f.error));return}const h=f.data,C=this.argBuilder.buildContextArgs(t?.context),S=[...h.prefixArgs,...i,...C],k=this.argBuilder.buildCdkEnv(t),l=O(h.command,S,{cwd:e,env:k,stdio:"inherit",shell:!1,detached:!1,...this.abortSignal!==void 0?{signal:this.abortSignal,killSignal:"SIGTERM"}:{}});if(!l.pid){l.on("error",r=>{I.debug("CdkProcess","Spawn error on failed child process",{error:r.message})}),a(n(`Failed to spawn CDK process - no PID. cwd=${e}, args=${S.join(" ")}`));return}const c=`cdk-passthrough-${++this.processCounter}`;this.runningProcesses.set(c,l);let g=!1,d=!1;const T=t?.timeout??R,b=setTimeout(()=>{l.killed||(g=!0,this.forceKillProcess(l))},T);l.on("close",r=>{if(clearTimeout(b),this.runningProcesses.delete(c),!d){if(d=!0,g){a(n("CDK command timed out"));return}r===0||t?.ignoreExitCode?a($({exitCode:r||0})):a(n(`CDK command failed with exit code ${r}`))}}),l.on("error",r=>{clearTimeout(b),this.runningProcesses.delete(c),!(d||g)&&(d=!0,a(n(`Failed to run CDK command: ${r.message}`)))})})):n(o.error)}async runCdkCommand(e,i,t){if(!E(e))return n(`Directory not found: ${e}`);if(!t?.skipProjectCheck){const u=y(e,"cdk.json");if(!E(u))return n(`No CDK project found in ${e}`);const o=await H(e,{...t?.outputCallback!==void 0?{onOutput:t.outputCallback}:{},...this.abortSignal!==void 0?{abortSignal:this.abortSignal}:{}});if(!o.success)return n(o.error);A(o.data.warnings,t?.outputCallback)}return new Promise(u=>{let o="",a="",f=!1;const h=L();if(!h.success){u(n(h.error));return}const C=h.data,S=this.argBuilder.buildContextArgs(t?.context),k=[...C.prefixArgs,...i,...S],l={...this.argBuilder.buildCdkEnv(t),NO_COLOR:"1",...t?.extraEnv?N(t.extraEnv):{}};I.debug("CdkService","Spawning CDK process",{command:`${C.command} ${k.join(" ")}`,workingDir:e});const c=O(C.command,k,{cwd:e,env:l,stdio:["ignore","pipe","pipe"],shell:!1,detached:!1,...this.abortSignal!==void 0?{signal:this.abortSignal,killSignal:"SIGTERM"}:{}});if(!c.pid){const r=`Failed to spawn CDK process - no PID. cwd=${e}, args=${k.join(" ")}`;c.on("error",s=>{I.debug("CdkProcess","Deferred spawn error on failed child process",{error:s.message})}),u(n(r));return}const g=`cdk-${++this.processCounter}`;this.runningProcesses.set(g,c);let d=!1;const T=t?.timeout??R,b=setTimeout(()=>{c.killed||(f=!0,this.forceKillProcess(c))},T);c.stdout?.on("data",r=>{const s=r.toString();o+=s,t?.outputCallback&&t.outputCallback(p(s)),t?.cdkOutputLogger?.writeCdkOutput("stdout",p(s))}),c.stderr?.on("data",r=>{const s=r.toString();t?.cdkOutputLogger?.writeCdkOutput("stderr",p(s)),!s.includes("deprecated")&&!s.includes("npm WARN")&&!s.includes("ENOENT")&&!/\(node:\d+\)/.test(s)&&!s.includes("ExperimentalWarning")&&!s.includes("will no longer support")&&(a+=s),t?.errorCallback&&t.errorCallback(p(s))}),c.on("error",r=>{clearTimeout(b),this.runningProcesses.delete(g),!(d||f)&&(d=!0,u(n(M(r))))}),c.on("close",r=>{if(clearTimeout(b),this.runningProcesses.delete(g),d)return;if(d=!0,f){u(n("CDK command timed out"));return}const s=r===0||t?.ignoreExitCode===!0&&r===1,G=o+(a?`
3
- ${a}`:"");if(s){const x=t?.combineOutput?G:o;u($({output:p(x),exitCode:r||0}));return}let w=a;if(o){const x=o.match(/❌.*?Error:(.*)$/m);x&&(w=x[1]?.trim()??"")}const K=w||`CDK command failed with exit code ${r}`,j=o?`${K}
4
- ${o}`:K;u(n(p(j)))})})}}export{Y as CdkProcessManager};
1
+ var N=Object.defineProperty;var E=(m,e)=>N(m,"name",{value:e,configurable:!0});import{spawn as w}from"child_process";import{existsSync as I}from"fs";import{join as y}from"path";import{createRequire as _}from"module";import{logger as P}from"@fjall/util/logger";import{emitWarning as B}from"@fjall/util/diagnostics";import{filterDangerousEnvVars as D,maskSensitiveOutput as p}from"@fjall/util";import{success as $,failure as i}from"@fjall/generator";import{getErrorMessage as M}from"@fjall/util";import{ensureDependencyIntegrity as G}from"./dependencyIntegrityGate.js";import{ENGINE_DIAGNOSTIC_SCOPE as F}from"../../util/diagnosticScopes.js";function H(){try{const e=_(import.meta.url).resolve("aws-cdk/bin/cdk");return $({command:process.execPath,prefixArgs:[e]})}catch(m){return P.error("CdkService","Failed to resolve the bundled aws-cdk CLI",{error:p(M(m))}),i("Fjall could not locate its bundled aws-cdk CLI. The deploy toolchain looks misconfigured \u2014 reinstall dependencies (npm install) or reinstall the Fjall CLI, then try again.")}}E(H,"getCdkBinaryPath");const v=5e3,L=1800*1e3;function A(m,e){if(e===void 0){for(const s of m)B(s,{scope:F});return}for(const s of m)e(`[warn] ${s}
2
+ `)}E(A,"emitGateWarnings");class re{static{E(this,"CdkProcessManager")}runningProcesses=new Map;processCounter=0;argBuilder;abortSignal;exitHandler;sigintHandler;sigtermHandler;constructor(e,s){this.argBuilder=e,this.abortSignal=s,this.exitHandler=()=>this.cleanup(),this.sigintHandler=()=>{this.abortSignal===void 0&&(this.cleanup(),process.exit(130))},this.sigtermHandler=()=>{this.abortSignal===void 0&&(this.cleanup(),process.exit(143))},process.on("exit",this.exitHandler),process.on("SIGINT",this.sigintHandler),process.on("SIGTERM",this.sigtermHandler)}forceKillProcess(e){e.stdout?.destroy(),e.stderr?.destroy(),e.kill("SIGTERM");const s=setTimeout(()=>{e.exitCode===null&&e.kill("SIGKILL")},v);s.unref(),e.once("exit",()=>clearTimeout(s))}cleanup(){for(const[e,s]of this.runningProcesses)s.killed||(s.stdout?.destroy(),s.stderr?.destroy(),s.kill("SIGTERM"));this.runningProcesses.clear()}dispose(){this.cleanup(),process.removeListener("exit",this.exitHandler),process.removeListener("SIGINT",this.sigintHandler),process.removeListener("SIGTERM",this.sigtermHandler)}async runCdkCommandPassthrough(e,s,t){if(!I(e))return i(`Directory not found: ${e}`);const u=y(e,"cdk.json");if(!I(u))return i(`No CDK project found in ${e}`);const o=await G(e,{onOutput:t?.outputCallback??(a=>{process.stdout.write(a)}),...this.abortSignal!==void 0?{abortSignal:this.abortSignal}:{}});return o.success?(A(o.data.warnings,t?.outputCallback),new Promise(a=>{const f=H();if(!f.success){a(i(f.error));return}const h=f.data,C=this.argBuilder.buildContextArgs(t?.context),b=[...h.prefixArgs,...s,...C],S=this.argBuilder.buildCdkEnv(t),l=w(h.command,b,{cwd:e,env:S,stdio:"inherit",shell:!1,detached:!1,...this.abortSignal!==void 0?{signal:this.abortSignal,killSignal:"SIGTERM"}:{}});if(!l.pid){l.on("error",r=>{P.debug("CdkProcess","Spawn error on failed child process",{error:r.message})}),a(i(`Failed to spawn CDK process - no PID. cwd=${e}, args=${b.join(" ")}`));return}const c=`cdk-passthrough-${++this.processCounter}`;this.runningProcesses.set(c,l);let g=!1,d=!1;const T=t?.timeout??L,k=setTimeout(()=>{l.killed||(g=!0,this.forceKillProcess(l))},T);l.on("close",r=>{if(clearTimeout(k),this.runningProcesses.delete(c),!d){if(d=!0,g){a(i("CDK command timed out"));return}r===0||t?.ignoreExitCode?a($({exitCode:r||0})):a(i(`CDK command failed with exit code ${r}`))}}),l.on("error",r=>{clearTimeout(k),this.runningProcesses.delete(c),!(d||g)&&(d=!0,a(i(`Failed to run CDK command: ${r.message}`)))})})):i(o.error)}async runCdkCommand(e,s,t){if(!I(e))return i(`Directory not found: ${e}`);if(!t?.skipProjectCheck){const u=y(e,"cdk.json");if(!I(u))return i(`No CDK project found in ${e}`);const o=await G(e,{...t?.outputCallback!==void 0?{onOutput:t.outputCallback}:{},...this.abortSignal!==void 0?{abortSignal:this.abortSignal}:{}});if(!o.success)return i(o.error);A(o.data.warnings,t?.outputCallback)}return new Promise(u=>{let o="",a="",f=!1;const h=H();if(!h.success){u(i(h.error));return}const C=h.data,b=this.argBuilder.buildContextArgs(t?.context),S=[...C.prefixArgs,...s,...b],l={...this.argBuilder.buildCdkEnv(t),NO_COLOR:"1",...t?.extraEnv?D(t.extraEnv):{}};P.debug("CdkService","Spawning CDK process",{command:`${C.command} ${S.join(" ")}`,workingDir:e});const c=w(C.command,S,{cwd:e,env:l,stdio:["ignore","pipe","pipe"],shell:!1,detached:!1,...this.abortSignal!==void 0?{signal:this.abortSignal,killSignal:"SIGTERM"}:{}});if(!c.pid){const r=`Failed to spawn CDK process - no PID. cwd=${e}, args=${S.join(" ")}`;c.on("error",n=>{P.debug("CdkProcess","Deferred spawn error on failed child process",{error:n.message})}),u(i(r));return}const g=`cdk-${++this.processCounter}`;this.runningProcesses.set(g,c);let d=!1;const T=t?.timeout??L,k=setTimeout(()=>{c.killed||(f=!0,this.forceKillProcess(c))},T);c.stdout?.on("data",r=>{const n=r.toString();o+=n,t?.outputCallback&&t.outputCallback(p(n)),t?.cdkOutputLogger?.writeCdkOutput("stdout",p(n))}),c.stderr?.on("data",r=>{const n=r.toString();t?.cdkOutputLogger?.writeCdkOutput("stderr",p(n)),!n.includes("deprecated")&&!n.includes("npm WARN")&&!n.includes("ENOENT")&&!/\(node:\d+\)/.test(n)&&!n.includes("ExperimentalWarning")&&!n.includes("will no longer support")&&(a+=n),t?.errorCallback&&t.errorCallback(p(n))}),c.on("error",r=>{clearTimeout(k),this.runningProcesses.delete(g),!(d||f)&&(d=!0,u(i(M(r))))}),c.on("close",r=>{if(clearTimeout(k),this.runningProcesses.delete(g),d)return;if(d=!0,f){u(i("CDK command timed out"));return}const n=r===0||t?.ignoreExitCode===!0&&r===1,R=o+(a?`
3
+ ${a}`:"");if(n){const x=t?.combineOutput?R:o;u($({output:p(x),exitCode:r||0}));return}let O=a;if(o){const x=o.match(/❌.*?Error:(.*)$/m);x&&(O=x[1]?.trim()??"")}const K=O||`CDK command failed with exit code ${r}`,j=o?`${K}
4
+ ${o}`:K;u(i(p(j)))})})}}export{re as CdkProcessManager};
@@ -11,9 +11,9 @@
11
11
  import { z } from "zod";
12
12
  export declare const RemediationVerbSchema: z.ZodEnum<{
13
13
  abort: "abort";
14
- forget: "forget";
15
- recreate: "recreate";
16
14
  pin: "pin";
15
+ recreate: "recreate";
16
+ forget: "forget";
17
17
  repair: "repair";
18
18
  refactor: "refactor";
19
19
  }>;
@@ -99,9 +99,9 @@ export declare const DestructionTicketResourceSchema: z.ZodObject<{
99
99
  dataLossRisk: z.ZodBoolean;
100
100
  verbs: z.ZodArray<z.ZodEnum<{
101
101
  abort: "abort";
102
- forget: "forget";
103
- recreate: "recreate";
104
102
  pin: "pin";
103
+ recreate: "recreate";
104
+ forget: "forget";
105
105
  repair: "repair";
106
106
  refactor: "refactor";
107
107
  }>>;
@@ -139,9 +139,9 @@ export declare const DestructionTicketSchema: z.ZodObject<{
139
139
  dataLossRisk: z.ZodBoolean;
140
140
  verbs: z.ZodArray<z.ZodEnum<{
141
141
  abort: "abort";
142
- forget: "forget";
143
- recreate: "recreate";
144
142
  pin: "pin";
143
+ recreate: "recreate";
144
+ forget: "forget";
145
145
  repair: "repair";
146
146
  refactor: "refactor";
147
147
  }>>;
@@ -157,9 +157,9 @@ export declare const DestructionConsentSchema: z.ZodObject<{
157
157
  physicalName: z.ZodString;
158
158
  verb: z.ZodEnum<{
159
159
  abort: "abort";
160
- forget: "forget";
161
- recreate: "recreate";
162
160
  pin: "pin";
161
+ recreate: "recreate";
162
+ forget: "forget";
163
163
  repair: "repair";
164
164
  refactor: "refactor";
165
165
  }>;
@@ -13,8 +13,8 @@ import { z } from "zod";
13
13
  import { type RemediationVerb } from "./destruction.js";
14
14
  export declare const DRIFT_VERDICTS: readonly ["confirmed-deleted", "present", "unconfirmed", "stack-missing"];
15
15
  export declare const DriftVerdictSchema: z.ZodEnum<{
16
- "confirmed-deleted": "confirmed-deleted";
17
16
  present: "present";
17
+ "confirmed-deleted": "confirmed-deleted";
18
18
  unconfirmed: "unconfirmed";
19
19
  "stack-missing": "stack-missing";
20
20
  }>;
@@ -30,8 +30,8 @@ export declare const DriftSuspectSchema: z.ZodObject<{
30
30
  export type DriftSuspect = z.infer<typeof DriftSuspectSchema>;
31
31
  export declare const DriftFindingSchema: z.ZodObject<{
32
32
  verdict: z.ZodEnum<{
33
- "confirmed-deleted": "confirmed-deleted";
34
33
  present: "present";
34
+ "confirmed-deleted": "confirmed-deleted";
35
35
  unconfirmed: "unconfirmed";
36
36
  "stack-missing": "stack-missing";
37
37
  }>;
@@ -39,9 +39,9 @@ export declare const DriftFindingSchema: z.ZodObject<{
39
39
  probeMethod: z.ZodString;
40
40
  verbs: z.ZodArray<z.ZodEnum<{
41
41
  abort: "abort";
42
- forget: "forget";
43
- recreate: "recreate";
44
42
  pin: "pin";
43
+ recreate: "recreate";
44
+ forget: "forget";
45
45
  repair: "repair";
46
46
  refactor: "refactor";
47
47
  }>>;
@@ -21,11 +21,11 @@
21
21
  import { z } from "zod";
22
22
  export declare const REMEDIATION_PHASES: readonly ["captured", "flip-verified", "flip-applied", "removal-applied", "done"];
23
23
  export declare const RemediationPhaseSchema: z.ZodEnum<{
24
+ done: "done";
24
25
  captured: "captured";
25
26
  "flip-verified": "flip-verified";
26
27
  "flip-applied": "flip-applied";
27
28
  "removal-applied": "removal-applied";
28
- done: "done";
29
29
  }>;
30
30
  export type RemediationPhase = z.infer<typeof RemediationPhaseSchema>;
31
31
  /** Ordinal comparison for phase progression checks. */
@@ -73,8 +73,8 @@ export type RemediationFlipProof = z.infer<typeof RemediationFlipProofSchema>;
73
73
  * the journal they read, failing closed on a cross-verb collision.
74
74
  */
75
75
  export declare const RemediationVerbWithSurgerySchema: z.ZodEnum<{
76
- forget: "forget";
77
76
  recreate: "recreate";
77
+ forget: "forget";
78
78
  }>;
79
79
  export type RemediationVerbWithSurgery = z.infer<typeof RemediationVerbWithSurgerySchema>;
80
80
  /**
@@ -86,9 +86,9 @@ export type RemediationVerbWithSurgery = z.infer<typeof RemediationVerbWithSurge
86
86
  * journal can never wedge a later forget/recreate on the same resources.
87
87
  */
88
88
  export declare const RemediationJournalVerbSchema: z.ZodEnum<{
89
- forget: "forget";
90
- recreate: "recreate";
91
89
  pin: "pin";
90
+ recreate: "recreate";
91
+ forget: "forget";
92
92
  }>;
93
93
  export type RemediationJournalVerb = z.infer<typeof RemediationJournalVerbSchema>;
94
94
  /** One slot the identity-pin operation acted on (pin journal audit trail). */
@@ -103,9 +103,9 @@ export declare const RemediationJournalRecordSchema: z.ZodObject<{
103
103
  version: z.ZodLiteral<1>;
104
104
  opId: z.ZodString;
105
105
  verb: z.ZodEnum<{
106
- forget: "forget";
107
- recreate: "recreate";
108
106
  pin: "pin";
107
+ recreate: "recreate";
108
+ forget: "forget";
109
109
  }>;
110
110
  accountId: z.ZodString;
111
111
  region: z.ZodString;
@@ -117,11 +117,11 @@ export declare const RemediationJournalRecordSchema: z.ZodObject<{
117
117
  physicalId: z.ZodString;
118
118
  }, z.core.$strict>>;
119
119
  phase: z.ZodEnum<{
120
+ done: "done";
120
121
  captured: "captured";
121
122
  "flip-verified": "flip-verified";
122
123
  "flip-applied": "flip-applied";
123
124
  "removal-applied": "removal-applied";
124
- done: "done";
125
125
  }>;
126
126
  createdAt: z.ZodString;
127
127
  updatedAt: z.ZodString;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Scope constants for diagnostics-spine emissions (@fjall/util/diagnostics).
3
+ * Scope binding is explicit, never ambient: free-form scope literals are
4
+ * forbidden in production code, so every engine emitWarning site imports its
5
+ * scope from here. The CLI's intentionally-duplicated CdkProcessManager copy
6
+ * imports this constant via the package barrel so both copies spell the
7
+ * engine lane identically.
8
+ */
9
+ /**
10
+ * Engine-originated warnings emitted when no DeployCallbacks lane reaches
11
+ * the site (the external-boundary fallback): the spine's bound sink owns
12
+ * their visibility.
13
+ */
14
+ export declare const ENGINE_DIAGNOSTIC_SCOPE = "engine";
@@ -0,0 +1 @@
1
+ const e="engine";export{e as ENGINE_DIAGNOSTIC_SCOPE};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/deploy-core",
3
- "version": "12.2.0",
3
+ "version": "12.3.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/fjall-tech/fjall.git",
@@ -96,8 +96,8 @@
96
96
  "@aws-sdk/client-ssm": "^3.1098.0",
97
97
  "@aws-sdk/client-sso-admin": "^3.1098.0",
98
98
  "@aws-sdk/client-sts": "^3.1098.0",
99
- "@fjall/generator": "^12.2.0",
100
- "@fjall/util": "^12.2.0",
99
+ "@fjall/generator": "^12.3.0",
100
+ "@fjall/util": "^12.3.0",
101
101
  "@smithy/node-http-handler": "^4.9.13",
102
102
  "aws-cdk": "^2.1134.0",
103
103
  "tsx": "^4.23.1",