@fjall/deploy-core 2.25.0 → 2.29.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.
- package/dist/.minified +1 -1
- package/dist/src/aws/index.d.ts +1 -1
- package/dist/src/aws/index.js +1 -1
- package/dist/src/aws/organisations/backup.d.ts +7 -2
- package/dist/src/aws/organisations/backup.js +2 -2
- package/dist/src/aws/organisations/index.d.ts +2 -2
- package/dist/src/aws/organisations/index.js +1 -1
- package/dist/src/aws/organisations/oidcProvider.d.ts +37 -0
- package/dist/src/aws/organisations/oidcProvider.js +1 -1
- package/dist/src/aws/organisations/organisation.d.ts +21 -0
- package/dist/src/aws/organisations/organisation.js +1 -1
- package/dist/src/aws/organisations/organisationalUnits.d.ts +15 -0
- package/dist/src/aws/organisations/organisationalUnits.js +1 -1
- package/dist/src/aws/utils/cloudformationEventHelpers.d.ts +45 -0
- package/dist/src/aws/utils/cloudformationEventHelpers.js +1 -1
- package/dist/src/aws/utils/cloudformationEventTypes.d.ts +1 -1
- package/dist/src/aws/utils/cloudformationEvents.d.ts +2 -1
- package/dist/src/aws/utils/cloudformationEvents.js +1 -1
- package/dist/src/aws/utils/stackStatus.js +1 -1
- package/dist/src/index.d.ts +13 -2
- package/dist/src/index.js +1 -1
- package/dist/src/orchestration/activeDeploymentGuard.d.ts +41 -0
- package/dist/src/orchestration/activeDeploymentGuard.js +8 -4
- package/dist/src/orchestration/application/applicationDeploy.d.ts +9 -0
- package/dist/src/orchestration/application/applicationDeploy.js +1 -1
- package/dist/src/orchestration/application/applicationDeployHelpers.d.ts +20 -3
- package/dist/src/orchestration/application/applicationDeployHelpers.js +3 -3
- package/dist/src/orchestration/application/applicationDestroy.js +1 -1
- package/dist/src/orchestration/application/approvalGate.d.ts +15 -1
- package/dist/src/orchestration/application/approvalGate.js +1 -1
- package/dist/src/orchestration/application/databaseEndpointReconcile.d.ts +77 -0
- package/dist/src/orchestration/application/databaseEndpointReconcile.js +1 -0
- package/dist/src/orchestration/application/deploySessionPolicy.d.ts +9 -1
- package/dist/src/orchestration/application/deploySessionPolicy.js +1 -1
- package/dist/src/orchestration/application/destructionGate.d.ts +164 -0
- package/dist/src/orchestration/application/destructionGate.js +5 -0
- package/dist/src/orchestration/application/dockerBuildHelper.js +1 -1
- package/dist/src/orchestration/application/ecrCacheRepository.d.ts +14 -0
- package/dist/src/orchestration/application/ecrCacheRepository.js +1 -0
- package/dist/src/orchestration/application/leaseGate.d.ts +30 -0
- package/dist/src/orchestration/application/leaseGate.js +1 -0
- package/dist/src/orchestration/application/plan/approvalToken.d.ts +15 -0
- package/dist/src/orchestration/application/plan/approvalToken.js +1 -1
- package/dist/src/orchestration/application/plan/changeSetEscalation.d.ts +46 -0
- package/dist/src/orchestration/application/plan/changeSetEscalation.js +1 -0
- package/dist/src/orchestration/application/plan/computeDeployPlan.d.ts +13 -0
- package/dist/src/orchestration/application/plan/computeDeployPlan.js +1 -1
- package/dist/src/orchestration/application/plan/index.d.ts +4 -1
- package/dist/src/orchestration/application/plan/index.js +1 -1
- package/dist/src/orchestration/application/plan/loadDeployPlan.d.ts +32 -0
- package/dist/src/orchestration/application/plan/loadDeployPlan.js +1 -0
- package/dist/src/orchestration/application/plan/pinnedNames.d.ts +31 -0
- package/dist/src/orchestration/application/plan/pinnedNames.js +1 -0
- package/dist/src/orchestration/application/plan/registryOverlay.d.ts +83 -0
- package/dist/src/orchestration/application/plan/registryOverlay.js +1 -0
- package/dist/src/orchestration/application/plan/renderDeployPlan.d.ts +4 -1
- package/dist/src/orchestration/application/plan/renderDeployPlan.js +1 -1
- package/dist/src/orchestration/application/plan/types.d.ts +31 -0
- package/dist/src/orchestration/application/plan/types.js +1 -0
- package/dist/src/orchestration/contextHelpers.d.ts +37 -1
- package/dist/src/orchestration/contextHelpers.js +1 -1
- package/dist/src/orchestration/drift/classifyDriftFailure.d.ts +31 -0
- package/dist/src/orchestration/drift/classifyDriftFailure.js +1 -0
- package/dist/src/orchestration/drift/detectStackDrift.d.ts +37 -0
- package/dist/src/orchestration/drift/detectStackDrift.js +1 -0
- package/dist/src/orchestration/drift/driftPreFlight.d.ts +73 -0
- package/dist/src/orchestration/drift/driftPreFlight.js +7 -0
- package/dist/src/orchestration/drift/driftProbe.d.ts +113 -0
- package/dist/src/orchestration/drift/driftProbe.js +1 -0
- package/dist/src/orchestration/drift/driftSuspectJournal.d.ts +40 -0
- package/dist/src/orchestration/drift/driftSuspectJournal.js +1 -0
- package/dist/src/orchestration/drift/preFlightGate.d.ts +44 -0
- package/dist/src/orchestration/drift/preFlightGate.js +2 -0
- package/dist/src/orchestration/index.d.ts +19 -0
- package/dist/src/orchestration/index.js +1 -1
- package/dist/src/orchestration/organisation/cascadeDestroyHelpers.d.ts +7 -0
- package/dist/src/orchestration/organisation/cascadeDestroyHelpers.js +1 -1
- package/dist/src/orchestration/organisation/cascadeHelpers.js +1 -1
- package/dist/src/orchestration/organisation/organisationDestroy.js +3 -3
- package/dist/src/orchestration/organisationDeploy/infraSteps.d.ts +8 -1
- package/dist/src/orchestration/organisationDeploy/infraSteps.js +1 -1
- package/dist/src/orchestration/organisationDeploy/orgCascadeDeploy.js +5 -5
- package/dist/src/orchestration/organisationDeploy/orgContext.d.ts +28 -2
- package/dist/src/orchestration/organisationDeploy/orgContext.js +1 -1
- package/dist/src/orchestration/organisationDeploy/singleComponentDeploy.js +1 -1
- package/dist/src/orchestration/remediation/driftRepairGate.d.ts +66 -0
- package/dist/src/orchestration/remediation/driftRepairGate.js +1 -0
- package/dist/src/orchestration/remediation/forensicsCapture.d.ts +49 -0
- package/dist/src/orchestration/remediation/forensicsCapture.js +1 -0
- package/dist/src/orchestration/remediation/forgetResource.d.ts +423 -0
- package/dist/src/orchestration/remediation/forgetResource.js +1 -0
- package/dist/src/orchestration/remediation/pinRemediation.d.ts +121 -0
- package/dist/src/orchestration/remediation/pinRemediation.js +1 -0
- package/dist/src/orchestration/remediation/postFailureRepairOffer.d.ts +77 -0
- package/dist/src/orchestration/remediation/postFailureRepairOffer.js +14 -0
- package/dist/src/orchestration/remediation/recreatePreFlight.d.ts +47 -0
- package/dist/src/orchestration/remediation/recreatePreFlight.js +1 -0
- package/dist/src/orchestration/remediation/recreateResource.d.ts +110 -0
- package/dist/src/orchestration/remediation/recreateResource.js +1 -0
- package/dist/src/orchestration/remediation/remediationJournal.d.ts +88 -0
- package/dist/src/orchestration/remediation/remediationJournal.js +2 -0
- package/dist/src/orchestration/remediation/removalUpdate.d.ts +135 -0
- package/dist/src/orchestration/remediation/removalUpdate.js +1 -0
- package/dist/src/orchestration/remediation/retainFlip.d.ts +294 -0
- package/dist/src/orchestration/remediation/retainFlip.js +1 -0
- package/dist/src/services/application/ApplicationStackService.d.ts +5 -3
- package/dist/src/services/application/ApplicationStackService.js +1 -1
- package/dist/src/services/application/applicationStackHelpers.d.ts +8 -6
- package/dist/src/services/application/applicationStackHelpers.js +3 -3
- package/dist/src/services/index.d.ts +2 -2
- package/dist/src/services/index.js +1 -1
- package/dist/src/services/infrastructure/CdkArgumentBuilder.js +1 -1
- package/dist/src/services/infrastructure/CdkEventMonitoring.d.ts +15 -0
- package/dist/src/services/infrastructure/CdkEventMonitoring.js +1 -1
- package/dist/src/services/infrastructure/CdkOutputAnalyser.d.ts +8 -0
- package/dist/src/services/infrastructure/CdkOutputAnalyser.js +2 -1
- package/dist/src/services/infrastructure/CdkService.js +3 -3
- package/dist/src/services/infrastructure/CdkServiceTypes.d.ts +7 -0
- package/dist/src/services/infrastructure/CfnRegistryService.d.ts +68 -0
- package/dist/src/services/infrastructure/CfnRegistryService.js +1 -0
- package/dist/src/services/infrastructure/CloudFormationService.d.ts +5 -2
- package/dist/src/services/infrastructure/CloudFormationService.js +1 -1
- package/dist/src/services/infrastructure/EcsServiceResolver.d.ts +23 -3
- package/dist/src/services/infrastructure/EcsServiceResolver.js +1 -1
- package/dist/src/services/infrastructure/cdkServiceHelpers.js +1 -1
- package/dist/src/services/infrastructure/cfnRegistrySeed.d.ts +10 -0
- package/dist/src/services/infrastructure/cfnRegistrySeed.js +1 -0
- package/dist/src/services/infrastructure/changeSetProbe.d.ts +88 -0
- package/dist/src/services/infrastructure/changeSetProbe.js +1 -0
- package/dist/src/services/infrastructure/index.d.ts +2 -0
- package/dist/src/services/infrastructure/index.js +1 -1
- package/dist/src/services/supporting/CdkContextBuilder.d.ts +1 -0
- package/dist/src/services/supporting/CdkContextBuilder.js +1 -1
- package/dist/src/types/callbackKeys.d.ts +1 -1
- package/dist/src/types/callbackKeys.js +1 -1
- package/dist/src/types/callbacks.d.ts +22 -0
- package/dist/src/types/config/entitlements.d.ts +9 -0
- package/dist/src/types/config/orgConfig.d.ts +6 -0
- package/dist/src/types/deployment/DeploymentTypes.d.ts +1 -0
- package/dist/src/types/deploymentEventSchema.d.ts +1 -0
- package/dist/src/types/deploymentEventSchema.js +1 -1
- package/dist/src/types/destruction.d.ts +212 -0
- package/dist/src/types/destruction.js +1 -0
- package/dist/src/types/drift.d.ts +72 -0
- package/dist/src/types/drift.js +1 -0
- package/dist/src/types/index.d.ts +8 -2
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/params.d.ts +161 -0
- package/dist/src/types/remediation.d.ts +126 -0
- package/dist/src/types/remediation.js +1 -0
- package/package.json +5 -4
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
213 files minified at 2026-07-13T22:22:04.195Z
|
package/dist/src/aws/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { buildTargetSetUnreadyAdvisory } from "./targetSetAdvisory.js";
|
|
|
6
6
|
export type { TargetSetUnreadyAdvisoryParams } from "./targetSetAdvisory.js";
|
|
7
7
|
export { checkRegionEnabled, regionDisabledMessage } from "./regions/regionOptStatus.js";
|
|
8
8
|
export type { RegionAvailability } from "./regions/regionOptStatus.js";
|
|
9
|
-
export { ensureOrganisationExists, describeOrganisation, enablePolicyTypes, enableServiceAccess, SERVICE_PRINCIPALS, enableRamSharing, activateTrustedAccess, enableIpamDelegatedAdmin, updateBackupGlobalSettings, listAccounts, findAccount, createAccount, ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap, activateCostAllocationTags, checkIdentityCentreStatus, snapshotIdentityCentre, composeSdkAbortSignal, extractErrorName, isAborted, isOULeaf, DEFAULT_MAX_PAGES, IDENTITY_STORE_PAGE_SIZE, drainPages, registerSecurityDelegates, SECURITY_SERVICE_PRINCIPALS, enableCentralisedRootAccess, ROOT_ACCESS_FEATURES, RootAccessEnablementError } from "./organisations/index.js";
|
|
9
|
+
export { ensureOrganisationExists, describeOrganisation, enablePolicyTypes, enableServiceAccess, SERVICE_PRINCIPALS, enableRamSharing, activateTrustedAccess, enableIpamDelegatedAdmin, updateBackupGlobalSettings, listAccounts, findAccount, createAccount, ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap, findDevelopmentOuId, activateCostAllocationTags, checkIdentityCentreStatus, snapshotIdentityCentre, composeSdkAbortSignal, extractErrorName, isAborted, isOULeaf, DEFAULT_MAX_PAGES, IDENTITY_STORE_PAGE_SIZE, drainPages, registerSecurityDelegates, SECURITY_SERVICE_PRINCIPALS, enableCentralisedRootAccess, ROOT_ACCESS_FEATURES, RootAccessEnablementError } from "./organisations/index.js";
|
|
10
10
|
export type { OrgDetails, OUMap, OUTree, AccountPlacementResult, AccountInfo, DrainPagesOptions, PagedResult, IdentityCentreStatus, IdentityCentreSnapshot, IdentityCentreSnapshotGroup, IdentityCentreSnapshotOptions, IdentityCentreSnapshotResult, IdentityCentreSnapshotUser, BackupGlobalSettings, CostAllocationTag, CreateAccountResult, RootAccessFeature, RootAccessEnablementSummary } from "./organisations/index.js";
|
|
11
11
|
export { CloudFormationEventMonitor } from "./utils/cloudformationEvents.js";
|
|
12
12
|
export type { AwsClientLike, EventLogWriter, EventFailureAnalyser, EventLogWriterFactory, EventMonitorDeps } from "./utils/cloudformationEvents.js";
|
package/dist/src/aws/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SimpleAwsProvider as a}from"./SimpleAwsProvider.js";import{checkTargetReadiness as
|
|
1
|
+
import{SimpleAwsProvider as a}from"./SimpleAwsProvider.js";import{checkTargetReadiness as o,describeTargetReadinessReason as s,buildTargetUnreadyAdvisory as n,probeAccountStackExists as i}from"./targetReadiness.js";import{buildTargetSetUnreadyAdvisory as d}from"./targetSetAdvisory.js";import{checkRegionEnabled as A,regionDisabledMessage as E}from"./regions/regionOptStatus.js";import{ensureOrganisationExists as g,describeOrganisation as u,enablePolicyTypes as b,enableServiceAccess as p,SERVICE_PRINCIPALS as m,enableRamSharing as I,activateTrustedAccess as R,enableIpamDelegatedAdmin as T,updateBackupGlobalSettings as C,listAccounts as x,findAccount as O,createAccount as _,ensureOrganisationalUnitsExist as f,placeAccountsInOUs as y,buildAccountToOUMap as P,findDevelopmentOuId as U,activateCostAllocationTags as v,checkIdentityCentreStatus as k,snapshotIdentityCentre as D,composeSdkAbortSignal as h,extractErrorName as L,isAborted as M,isOULeaf as N,DEFAULT_MAX_PAGES as F,IDENTITY_STORE_PAGE_SIZE as G,drainPages as V,registerSecurityDelegates as Y,SECURITY_SERVICE_PRINCIPALS as w,enableCentralisedRootAccess as B,ROOT_ACCESS_FEATURES as X,RootAccessEnablementError as Z}from"./organisations/index.js";import{CloudFormationEventMonitor as q}from"./utils/cloudformationEvents.js";export{q as CloudFormationEventMonitor,F as DEFAULT_MAX_PAGES,G as IDENTITY_STORE_PAGE_SIZE,X as ROOT_ACCESS_FEATURES,Z as RootAccessEnablementError,w as SECURITY_SERVICE_PRINCIPALS,m as SERVICE_PRINCIPALS,a as SimpleAwsProvider,v as activateCostAllocationTags,R as activateTrustedAccess,P as buildAccountToOUMap,d as buildTargetSetUnreadyAdvisory,n as buildTargetUnreadyAdvisory,k as checkIdentityCentreStatus,A as checkRegionEnabled,o as checkTargetReadiness,h as composeSdkAbortSignal,_ as createAccount,u as describeOrganisation,s as describeTargetReadinessReason,V as drainPages,B as enableCentralisedRootAccess,T as enableIpamDelegatedAdmin,b as enablePolicyTypes,I as enableRamSharing,p as enableServiceAccess,g as ensureOrganisationExists,f as ensureOrganisationalUnitsExist,L as extractErrorName,O as findAccount,U as findDevelopmentOuId,M as isAborted,N as isOULeaf,x as listAccounts,y as placeAccountsInOUs,i as probeAccountStackExists,E as regionDisabledMessage,Y as registerSecurityDelegates,D as snapshotIdentityCentre,C as updateBackupGlobalSettings};
|
|
@@ -29,8 +29,13 @@ export declare function accountHasDisasterRecovery(environment: string | null |
|
|
|
29
29
|
* account/region, to decide adopt-vs-create. A retained, vault-locked DR vault
|
|
30
30
|
* survives stack teardown and collides on the next CREATE.
|
|
31
31
|
*
|
|
32
|
-
* Returns success(true) when present
|
|
33
|
-
*
|
|
32
|
+
* Returns success(true) when present. DescribeBackupVault on an ABSENT vault
|
|
33
|
+
* throws AccessDeniedException ("Insufficient privileges to perform this
|
|
34
|
+
* action.") rather than ResourceNotFoundException — even for admin
|
|
35
|
+
* credentials in accounts that have never used AWS Backup — so an
|
|
36
|
+
* AccessDenied is disambiguated via ListBackupVaults, which answers cleanly:
|
|
37
|
+
* vault named in the list → exists; absent from a successful listing → does
|
|
38
|
+
* not. Every other error (throttling, and a listing that is itself denied)
|
|
34
39
|
* propagates as failure — a mis-read "exists" would flip a vault-less region
|
|
35
40
|
* into a broken by-reference deploy.
|
|
36
41
|
*/
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{DescribeBackupVaultCommand as
|
|
2
|
-
`)}export{
|
|
1
|
+
import{DescribeBackupVaultCommand as p,ListBackupVaultsCommand as m,UpdateGlobalSettingsCommand as k}from"@aws-sdk/client-backup";import{success as i,failure as c}from"@fjall/generator";import{BACKUP_VAULT_NAME as o,getErrorMessage as u,maskSensitiveOutput as d}from"@fjall/util";import{composeSdkAbortSignal as s,isAborted as f}from"./types.js";const b={enableCrossAccountBackup:!0,enableDelegatedAdministrator:!0,enableMpa:!1};async function B(e,r,t){try{const n={...b,...r},a={isCrossAccountBackupEnabled:n.enableCrossAccountBackup.toString(),isDelegatedAdministratorEnabled:n.enableDelegatedAdministrator.toString(),isMpaEnabled:n.enableMpa.toString()};return await e.send(new k({GlobalSettings:a}),{abortSignal:s(t)}),i(void 0)}catch(n){return c(new Error(`Failed to update backup global settings: ${u(n)}`))}}function v(e,r){return r===void 0||r===""?!1:e==="production"||e==="compliance"}async function N(e,r){try{return await e.send(new p({BackupVaultName:o}),{abortSignal:s(r)}),i(!0)}catch(t){return t instanceof Error&&t.name==="ResourceNotFoundException"?i(!1):t instanceof Error&&t.name==="AccessDeniedException"?g(e,r):c(new Error(`Failed to describe backup vault "${o}": ${d(u(t))}`))}}async function g(e,r){try{let t;do{if(f(r))return c(new Error("Backup vault probe aborted"));const n=await e.send(new m({NextToken:t}),{abortSignal:s(r)});if((n.BackupVaultList??[]).some(l=>l.BackupVaultName===o))return i(!0);t=n.NextToken}while(t!==void 0);return i(!1)}catch(t){return c(new Error(`Failed to list backup vaults probing "${o}": ${d(u(t))}`))}}async function w(e,r,t){try{const n=await e.send(new p({BackupVaultName:o}),{abortSignal:s(t)}),a=n.LockDate,l=a!==void 0&&a.getTime()<=Date.now();return i({vaultName:n.BackupVaultName??o,region:r,locked:n.Locked??!1,...a!==void 0&&{lockDate:a},lockPermanent:l,recoveryPointCount:n.NumberOfRecoveryPoints??0,...n.EncryptionKeyArn!==void 0&&{encryptionKeyArn:n.EncryptionKeyArn}})}catch(n){return n instanceof Error&&n.name==="ResourceNotFoundException"?i(null):c(new Error(`Failed to describe surviving backup vault "${o}": ${d(u(n))}`))}}function x(e){const r=e.locked?e.lockPermanent?"compliance-locked, PERMANENT \u2014 cannot be removed by anyone, including AWS or the root user":e.lockDate!==void 0?`compliance-locked, immutable from ${e.lockDate.toISOString().slice(0,10)}`:"governance-locked \u2014 removable by privileged IAM":"unlocked";return[`Backup vault "${e.vaultName}" in ${e.region} SURVIVES this destroy.`,` \u2022 Lock: ${r}`,` \u2022 Recovery points retained: ${e.recoveryPointCount}`,...e.encryptionKeyArn!==void 0?[` \u2022 Retained KMS key (also orphaned): ${e.encryptionKeyArn}`]:[]," The vault and its KMS key are RemovalPolicy.RETAIN \u2014 destroy cannot delete them."].join(`
|
|
2
|
+
`)}export{o as BACKUP_VAULT_NAME,v as accountHasDisasterRecovery,N as describeBackupVaultExists,w as describeSurvivingBackupVault,x as formatSurvivingVaultWarning,B as updateBackupGlobalSettings};
|
|
@@ -6,7 +6,7 @@ export type { BackupGlobalSettings } from "./backup.js";
|
|
|
6
6
|
export type { CostAllocationTag } from "./costAllocation.js";
|
|
7
7
|
export type { CreateAccountResult } from "./accounts.js";
|
|
8
8
|
export type { RootAccessFeature, RootAccessEnablementSummary } from "./rootAccess.js";
|
|
9
|
-
export { ensureOrganisationExists, describeOrganisation } from "./organisation.js";
|
|
9
|
+
export { ensureOrganisationExists, describeOrganisation, describeOrganisationAsMember, type MemberOrgDetails } from "./organisation.js";
|
|
10
10
|
export { enablePolicyTypes } from "./policies.js";
|
|
11
11
|
export { enableServiceAccess, SERVICE_PRINCIPALS } from "./serviceAccess.js";
|
|
12
12
|
export { enableRamSharing } from "./ram.js";
|
|
@@ -14,7 +14,7 @@ export { activateTrustedAccess } from "./trustedAccess.js";
|
|
|
14
14
|
export { enableIpamDelegatedAdmin } from "./ipam.js";
|
|
15
15
|
export { updateBackupGlobalSettings } from "./backup.js";
|
|
16
16
|
export { listAccounts, findAccount, createAccount } from "./accounts.js";
|
|
17
|
-
export { ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap } from "./organisationalUnits.js";
|
|
17
|
+
export { ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap, findDevelopmentOuId } from "./organisationalUnits.js";
|
|
18
18
|
export { activateCostAllocationTags } from "./costAllocation.js";
|
|
19
19
|
export { checkIdentityCentreStatus } from "./identityCentre.js";
|
|
20
20
|
export { snapshotIdentityCentre } from "./identityCentreSnapshot.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{composeSdkAbortSignal as r,extractErrorName as o,isAborted as a,isOULeaf as s}from"./types.js";import{DEFAULT_MAX_PAGES as
|
|
1
|
+
import{composeSdkAbortSignal as r,extractErrorName as o,isAborted as a,isOULeaf as s}from"./types.js";import{DEFAULT_MAX_PAGES as i,IDENTITY_STORE_PAGE_SIZE as c,drainPages as p}from"./pagination.js";import{ensureOrganisationExists as A,describeOrganisation as l,describeOrganisationAsMember as f}from"./organisation.js";import{enablePolicyTypes as E}from"./policies.js";import{enableServiceAccess as d,SERVICE_PRINCIPALS as I}from"./serviceAccess.js";import{enableRamSharing as b}from"./ram.js";import{activateTrustedAccess as C}from"./trustedAccess.js";import{enableIpamDelegatedAdmin as R}from"./ipam.js";import{updateBackupGlobalSettings as _}from"./backup.js";import{listAccounts as U,findAccount as y,createAccount as D}from"./accounts.js";import{ensureOrganisationalUnitsExist as L,placeAccountsInOUs as N,buildAccountToOUMap as h,findDevelopmentOuId as k}from"./organisationalUnits.js";import{activateCostAllocationTags as M}from"./costAllocation.js";import{checkIdentityCentreStatus as V}from"./identityCentre.js";import{snapshotIdentityCentre as B}from"./identityCentreSnapshot.js";import{registerSecurityDelegates as Z,SECURITY_SERVICE_PRINCIPALS as j}from"./delegatedAdmin.js";import{enableCentralisedRootAccess as w,ROOT_ACCESS_FEATURES as z,RootAccessEnablementError as H}from"./rootAccess.js";export{i as DEFAULT_MAX_PAGES,c as IDENTITY_STORE_PAGE_SIZE,z as ROOT_ACCESS_FEATURES,H as RootAccessEnablementError,j as SECURITY_SERVICE_PRINCIPALS,I as SERVICE_PRINCIPALS,M as activateCostAllocationTags,C as activateTrustedAccess,h as buildAccountToOUMap,V as checkIdentityCentreStatus,r as composeSdkAbortSignal,D as createAccount,l as describeOrganisation,f as describeOrganisationAsMember,p as drainPages,w as enableCentralisedRootAccess,R as enableIpamDelegatedAdmin,E as enablePolicyTypes,b as enableRamSharing,d as enableServiceAccess,A as ensureOrganisationExists,L as ensureOrganisationalUnitsExist,o as extractErrorName,y as findAccount,k as findDevelopmentOuId,a as isAborted,s as isOULeaf,U as listAccounts,N as placeAccountsInOUs,Z as registerSecurityDelegates,B as snapshotIdentityCentre,_ as updateBackupGlobalSettings};
|
|
@@ -20,6 +20,43 @@ export interface OidcProviderTeardownResult {
|
|
|
20
20
|
* Failure messages stay raw — callers mask at their output boundary.
|
|
21
21
|
*/
|
|
22
22
|
export declare function deleteOidcProviderIfUnreferenced(client: IAMClient, abortSignal?: AbortSignal): Promise<Result<OidcProviderTeardownResult>>;
|
|
23
|
+
export interface OidcProviderEnsureResult {
|
|
24
|
+
status: "present" | "recreated" | "aborted";
|
|
25
|
+
providerArn?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Adopt-or-create guard for the account-global `https://fjall.io` OIDC
|
|
29
|
+
* provider, run after an Account/Platform stack deploy completes.
|
|
30
|
+
*
|
|
31
|
+
* Why this exists: pre-2.20.0 Account stacks owned the provider through CDK's
|
|
32
|
+
* L2 `iam.OpenIdConnectProvider` custom resource. The first redeploy on
|
|
33
|
+
* ≥2.20.0 replaces it with the adopt-or-create `Custom::FjallOidcProvider`
|
|
34
|
+
* resource under a NEW logical ID, so CloudFormation creates the new resource
|
|
35
|
+
* (which adopts the existing provider) and then — in the cleanup phase, after
|
|
36
|
+
* every in-template resource has run — deletes the old L2 resource, whose
|
|
37
|
+
* handler issues a real DeleteOpenIDConnectProvider on the same physical
|
|
38
|
+
* provider. The update completes green while the account's web-identity trust
|
|
39
|
+
* anchor is destroyed: every subsequent scan AND OIDC-authenticated deploy
|
|
40
|
+
* fails with InvalidIdentityToken (2026-07-07 fjall-org incident). Because
|
|
41
|
+
* cleanup runs last, no in-template fix can win; this reconcile runs after
|
|
42
|
+
* CloudFormation returns, inside the same deploy session, so the account is
|
|
43
|
+
* healed before the deploy that broke it reports success.
|
|
44
|
+
*
|
|
45
|
+
* The created provider mirrors the OidcConnector handler byte-for-byte via
|
|
46
|
+
* the shared `@fjall/generator` spec constants. EntityAlreadyExists from a
|
|
47
|
+
* concurrent creator (parallel cascade region, Quick-Create) is success.
|
|
48
|
+
*
|
|
49
|
+
* Failure messages stay raw — callers mask at their output boundary.
|
|
50
|
+
*/
|
|
51
|
+
export declare function ensureOidcProviderPresent(client: IAMClient, abortSignal?: AbortSignal): Promise<Result<OidcProviderEnsureResult>>;
|
|
52
|
+
/**
|
|
53
|
+
* Best-effort wrapper around {@link ensureOidcProviderPresent}: surfaces the
|
|
54
|
+
* outcome via callbacks/logger and never fails the deploy — the stack deploy
|
|
55
|
+
* itself succeeded, and a reconcile miss must not convert that into a failure.
|
|
56
|
+
* A recreation is reported at warn level because it means the deletion class
|
|
57
|
+
* fired and the operator should know the trust anchor was briefly absent.
|
|
58
|
+
*/
|
|
59
|
+
export declare function reconcileOidcProviderAfterDeploy(client: IAMClient, callbacks: DeployCallbacks, abortSignal?: AbortSignal): Promise<void>;
|
|
23
60
|
/**
|
|
24
61
|
* Best-effort wrapper around {@link deleteOidcProviderIfUnreferenced}: surfaces
|
|
25
62
|
* the outcome via callbacks/logger and swallows failures. A cleanup miss leaves
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ListOpenIDConnectProvidersCommand as
|
|
1
|
+
import{ListOpenIDConnectProvidersCommand as l,ListRolesCommand as D,CreateOpenIDConnectProviderCommand as O,DeleteOpenIDConnectProviderCommand as w}from"@aws-sdk/client-iam";import{FJALL_OIDC_AUDIENCE as g,FJALL_OIDC_ISSUER_DOMAIN as f,FJALL_OIDC_PLACEHOLDER_THUMBPRINT as y,success as i,failure as v}from"@fjall/generator";import{maskSensitiveOutput as m,getErrorMessage as I}from"@fjall/util";import{logger as s}from"@fjall/util/logger";import{composeSdkAbortSignal as a,isAborted as c}from"./types.js";const C=`:oidc-provider/${f}`;async function A(d,r){try{if(c(r))return i({deleted:!1,reason:"aborted"});const e=((await d.send(new l({}),{abortSignal:a(r)})).OpenIDConnectProviderList??[]).map(o=>o.Arn).find(o=>typeof o=="string"&&o.endsWith(C));if(e===void 0)return i({deleted:!1,reason:"provider not present"});let t;do{if(c(r))return i({deleted:!1,reason:"aborted"});const o=await d.send(new D({Marker:t}),{abortSignal:a(r)});for(const p of o.Roles??[]){const u=p.AssumeRolePolicyDocument;if(typeof u=="string"&&decodeURIComponent(u).includes(e))return i({deleted:!1,reason:`still referenced by role ${p.RoleName??"(unknown)"}`})}t=o.IsTruncated===!0?o.Marker:void 0}while(t!==void 0);return await d.send(new w({OpenIDConnectProviderArn:e}),{abortSignal:a(r)}),i({deleted:!0,reason:"deleted orphaned provider"})}catch(n){return n instanceof Error&&n.name==="NoSuchEntityException"?i({deleted:!1,reason:"provider not present"}):v(new Error(`Failed to evaluate OIDC provider teardown: ${I(n)}`))}}async function h(d,r){try{if(c(r))return i({status:"aborted"});const e=((await d.send(new l({}),{abortSignal:a(r)})).OpenIDConnectProviderList??[]).map(o=>o.Arn).find(o=>typeof o=="string"&&o.endsWith(C));if(e!==void 0)return i({status:"present",providerArn:e});const t=await d.send(new O({Url:`https://${f}`,ClientIDList:[g],ThumbprintList:[y]}),{abortSignal:a(r)});return i({status:"recreated",...t.OpenIDConnectProviderArn!==void 0&&{providerArn:t.OpenIDConnectProviderArn}})}catch(n){return n instanceof Error&&n.name==="EntityAlreadyExistsException"?i({status:"present"}):v(new Error(`Failed to ensure OIDC provider presence: ${I(n)}`))}}async function F(d,r,n){const e=await h(d,n);if(!e.success){const t=m(e.error.message);s.debug("oidcReconcile","OIDC provider ensure probe failed",{error:t}),r.onLog?.(`Could not verify the Fjall OIDC provider after deploy: ${t}. If scans or deploys later fail with InvalidIdentityToken, re-run this deploy or reconnect the account.`,"warn");return}if(e.data.status==="recreated"){s.info("oidcReconcile","Recreated missing account-global OIDC provider",{providerArn:e.data.providerArn}),r.onLog?.("The Fjall OIDC provider was missing after the stack deploy and has been restored","warn");return}s.debug("oidcReconcile","OIDC provider verified after deploy",{status:e.data.status})}async function _(d,r,n){const e=await A(d,n);if(!e.success){const t=m(e.error.message);s.debug("oidcTeardown","OIDC provider teardown probe failed",{error:t}),r.onLog?.(`OIDC provider cleanup skipped: ${t}`,"warn");return}if(e.data.deleted){s.info("oidcTeardown","Deleted orphaned account-global OIDC provider"),r.onLog?.("Removed the orphaned Fjall OIDC provider","info");return}s.debug("oidcTeardown","OIDC provider retained",{reason:e.data.reason})}export{_ as cleanupOrphanedOidcProvider,A as deleteOidcProviderIfUnreferenced,h as ensureOidcProviderPresent,F as reconcileOidcProviderAfterDeploy};
|
|
@@ -19,3 +19,24 @@ export declare function ensureOrganisationExists(client: OrganizationsClient, ab
|
|
|
19
19
|
export declare function describeOrganisation(client: OrganizationsClient, abortSignal?: AbortSignal, opts?: {
|
|
20
20
|
tolerateAccessDenied?: boolean;
|
|
21
21
|
}): Promise<Result<OrgDetails | null>>;
|
|
22
|
+
/**
|
|
23
|
+
* Org details visible to member-account credentials. rootId is present only
|
|
24
|
+
* when the caller can ListRoots (management account or delegated
|
|
25
|
+
* administrator).
|
|
26
|
+
*/
|
|
27
|
+
export interface MemberOrgDetails {
|
|
28
|
+
orgId: string;
|
|
29
|
+
managementAccountId: string;
|
|
30
|
+
rootId?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Describe the organisation with credentials that may belong to a member
|
|
34
|
+
* account. DescribeOrganization is callable from any account in an
|
|
35
|
+
* organisation, but ListRoots only from the management account (or a
|
|
36
|
+
* delegated administrator) — the root id resolves best-effort and is omitted
|
|
37
|
+
* when credentials cannot list roots. Read-only: never creates. Returns null
|
|
38
|
+
* when the account is not in an organisation. A DescribeOrganization denial
|
|
39
|
+
* still fails: the caller needs orgId (the Account stack exports it), so a
|
|
40
|
+
* silent fall-through would strip an exported output on redeploy.
|
|
41
|
+
*/
|
|
42
|
+
export declare function describeOrganisationAsMember(client: OrganizationsClient, abortSignal?: AbortSignal): Promise<Result<MemberOrgDetails | null>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DescribeOrganizationCommand as
|
|
1
|
+
import{DescribeOrganizationCommand as l,CreateOrganizationCommand as m,ListRootsCommand as w}from"@aws-sdk/client-organizations";import{success as s,failure as a}from"@fjall/generator";import{getErrorMessage as d}from"@fjall/util";import{extractErrorName as i,isAccessDenied as g,composeSdkAbortSignal as f,AWS_ERROR_NAMES as A}from"./types.js";async function M(n,o){try{let e=!1,r=await c(n,o);if(!r)try{r=(await n.send(new m({FeatureSet:"ALL"}),{abortSignal:f(o)})).Organization??null,e=!0}catch(u){if(i(u)==="AlreadyInOrganizationException"){if(r=await c(n,o),!r)return a(new Error("Account is already in an organisation but DescribeOrganization returned nothing"))}else throw u}if(!r?.Id||!r.MasterAccountId)return a(new Error("Organisation is missing required fields (Id or MasterAccountId)"));const t=await I(n,o);return t.success?s({orgId:r.Id,rootId:t.data,managementAccountId:r.MasterAccountId,created:e}):t}catch(e){return a(new Error(`Failed to ensure organisation exists: ${d(e)}`))}}async function h(n,o,e){try{const r=await c(n,o,e);if(!r)return s(null);if(!r.Id||!r.MasterAccountId)return a(new Error("Organisation is missing required fields (Id or MasterAccountId)"));const t=await I(n,o);return t.success?s({orgId:r.Id,rootId:t.data,managementAccountId:r.MasterAccountId,created:!1}):t}catch(r){return e?.tolerateAccessDenied===!0&&g(i(r))?s(null):a(new Error(`Failed to describe organisation: ${d(r)}`))}}async function b(n,o){try{const e=await c(n,o);if(!e)return s(null);if(!e.Id||!e.MasterAccountId)return a(new Error("Organisation is missing required fields (Id or MasterAccountId)"));let r;try{const t=await I(n,o);t.success&&(r=t.data)}catch(t){if(!g(i(t)))throw t}return s({orgId:e.Id,managementAccountId:e.MasterAccountId,...r!==void 0?{rootId:r}:{}})}catch(e){return a(new Error(`Failed to describe organisation: ${d(e)}`))}}async function I(n,o){const r=(await n.send(new w({}),{abortSignal:f(o)})).Roots??[];return r.length===0||!r[0]?.Id?a(new Error("No organisation root found")):s(r[0].Id)}async function c(n,o,e){try{return(await n.send(new l({}),{abortSignal:f(o)})).Organization??null}catch(r){const t=i(r);if(t===A.ORGS_NOT_IN_USE||e?.tolerateAccessDenied===!0&&g(t))return null;throw r}}export{h as describeOrganisation,b as describeOrganisationAsMember,M as ensureOrganisationExists};
|
|
@@ -37,3 +37,18 @@ export declare function buildAccountToOUMap(tree: OUTree, ouMap: OUMap, prefix?:
|
|
|
37
37
|
* Idempotent — accounts already in the correct OU are counted but not moved.
|
|
38
38
|
*/
|
|
39
39
|
export declare function placeAccountsInOUs(client: OrganizationsClient, ouMap: OUMap, accounts: AccountInfo[], accountToOU?: Record<string, string>, abortSignal?: AbortSignal): Promise<Result<AccountPlacementResult>>;
|
|
40
|
+
/**
|
|
41
|
+
* Find the id of the organisational unit named "development" (case-insensitive),
|
|
42
|
+
* searching breadth-first from the root up to DEV_OU_SEARCH_MAX_DEPTH levels.
|
|
43
|
+
* Supports both OU shapes ensureOrganisationalUnitsExist creates: flat
|
|
44
|
+
* (development at root) and nested (workloads.development).
|
|
45
|
+
*
|
|
46
|
+
* Collects EVERY match rather than returning the shallowest one: a flat→nested
|
|
47
|
+
* migration leaves a stray empty "development" OU at the root alongside the
|
|
48
|
+
* real nested one, and silently attaching the dev-isolation SCP to the stray
|
|
49
|
+
* would isolate nothing. Exactly one match → its id; zero → `undefined` (the
|
|
50
|
+
* org has no development OU — the caller treats that as "nothing to isolate",
|
|
51
|
+
* not an error); two or more → a loud failure naming the ids so the operator
|
|
52
|
+
* disambiguates, because a security backstop must never attach to the wrong OU.
|
|
53
|
+
*/
|
|
54
|
+
export declare function findDevelopmentOuId(client: OrganizationsClient, rootId: string, abortSignal?: AbortSignal): Promise<Result<string | undefined>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CreateOrganizationalUnitCommand as
|
|
1
|
+
import{CreateOrganizationalUnitCommand as x,ListOrganizationalUnitsForParentCommand as C,ListParentsCommand as b,MoveAccountCommand as _}from"@aws-sdk/client-organizations";import{success as f,failure as u}from"@fjall/generator";import{extractErrorName as N,isOULeaf as A,composeSdkAbortSignal as m,isAborted as p,AWS_ERROR_NAMES as E}from"./types.js";import{accountTier as v,getErrorMessage as y}from"@fjall/util";async function U(o,s,t){const e=await o.send(new C({ParentId:s}),{abortSignal:m(t)});let n=e.OrganizationalUnits??[],a=e.NextToken;for(;a;){if(p(t))throw new Error("Aborted: OU listing cancelled by shutdown signal");const r=await o.send(new C({ParentId:s,NextToken:a}),{abortSignal:m(t)});n=n.concat(r.OrganizationalUnits??[]),a=r.NextToken}return n}async function F(o,s,t){try{return(await o.send(new b({ChildId:s}),{abortSignal:m(t)})).Parents?.[0]?.Id}catch(e){if(N(e)===E.CHILD_NOT_FOUND)return;throw e}}async function L(o,s,t,e,n){const a=e.find(r=>r.Name===t);if(a?.Id)return f(a.Id);try{const c=(await o.send(new x({Name:t,ParentId:s}),{abortSignal:m(n)})).OrganizationalUnit;return c?.Id?f(c.Id):u(new Error(`OU "${t}" was created but has no ID`))}catch(r){return u(new Error(`Failed to create OU "${t}": ${y(r)}`))}}function P(o){return o.charAt(0).toUpperCase()+o.slice(1)}async function D(o,s,t,e){const n={};if(t.length===0)return f(n);const a=await U(o,s,e);for(const r of t){const c=P(r),i=await L(o,s,c,a,e);if(!i.success)return u(i.error);n[r.toLowerCase()]=i.data,a.push({Id:i.data,Name:c})}return f(n)}async function $(o,s,t,e,n,a,r){const c=await U(o,s,r);for(const[i,d]of Object.entries(t)){const l=P(i),h=await L(o,s,l,c,r);if(!h.success)return u(h.error);const O=h.data,g=n?`${n}.${i.toLowerCase()}`:i.toLowerCase();if(e[g]=O,n){const w=i.toLowerCase();a.has(w)||(e[w]=O)}if(c.push({Id:O,Name:l}),!A(d)){const w=await $(o,O,d,e,g,a,r);if(!w.success)return w}}return f(void 0)}async function H(o,s,t,e){if(p(e))return u(new Error("Aborted: OU reconciliation cancelled by shutdown signal"));try{if(Array.isArray(t))return await D(o,s,t,e);const n={},a=new Set(Object.keys(t).map(c=>c.toLowerCase())),r=await $(o,s,t,n,"",a,e);return r.success?f(n):u(r.error)}catch(n){return u(new Error(`Failed to ensure OUs exist: ${y(n)}`))}}function T(o,s,t=""){const e={};for(const[n,a]of Object.entries(o)){const r=t?`${t}.${n.toLowerCase()}`:n.toLowerCase(),c=s[r];if(A(a)){if(c)for(const i of a)e[i.toLowerCase()]=c}else Object.assign(e,T(a,s,r))}return e}async function S(o,s,t,e,n){try{if(t.length===0)return f({moved:0,alreadyPlaced:0});let a=0,r=0;for(const c of t){if(p(n))return u(new Error("Aborted: account placement cancelled by shutdown signal"));if(v(c)==="organisation")continue;const i=e?e[c.name.toLowerCase()]:s[c.environment.toLowerCase()];if(!i)continue;const d=await F(o,c.id,n);if(d){if(d===i){r++;continue}try{await o.send(new _({AccountId:c.id,SourceParentId:d,DestinationParentId:i}),{abortSignal:m(n)}),a++}catch(l){if(N(l)===E.ACCOUNT_NOT_FOUND)continue;throw l}}}return f({moved:a,alreadyPlaced:r})}catch(a){return u(new Error(`Failed to place accounts in OUs: ${y(a)}`))}}const I="development",k=3;async function K(o,s,t){try{const e=[];let n=[s];for(let a=0;a<k;a++){const r=[];for(const c of n){if(p(t))return u(new Error("Aborted: development-OU lookup cancelled by shutdown signal"));const i=await U(o,c,t);for(const d of i)if(d.Id!==void 0){if(d.Name?.toLowerCase()===I){e.push(d.Id);continue}r.push(d.Id)}}if(r.length===0)break;n=r}return e.length===0?f(void 0):e.length>1?u(new Error(`Found ${e.length} organisational units named "${I}" (${e.join(", ")}); cannot safely target the dev-isolation SCP. A flat\u2192nested migration can leave a stray empty "${I}" OU at the root \u2014 remove the duplicate so exactly one remains.`)):f(e[0])}catch(e){return u(new Error(`Failed to locate development OU: ${y(e)}`))}}export{T as buildAccountToOUMap,H as ensureOrganisationalUnitsExist,K as findDevelopmentOuId,S as placeAccountsInOUs};
|
|
@@ -15,6 +15,34 @@ export declare class IpamConcurrencyTracker {
|
|
|
15
15
|
*/
|
|
16
16
|
trackEvent(event: ResourceEvent, eventLogger: EventLogWriter | null): void;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Clock-skew allowance subtracted from the monitor start time to form the
|
|
20
|
+
* event cutoff (F-F8). CloudFormation event timestamps come from AWS clocks;
|
|
21
|
+
* two minutes comfortably covers client/AWS drift (SigV4 itself tolerates
|
|
22
|
+
* five) without re-admitting a previous operation's history.
|
|
23
|
+
*
|
|
24
|
+
* Accepted residual (F-R11, narrowed by F-X9): after a FAILED prime poll, a
|
|
25
|
+
* previous operation's events inside the skew window (terminal within 120s
|
|
26
|
+
* of startMonitoring, same stack) are admitted for DISPATCH and terminal
|
|
27
|
+
* detection. Tightening those to an unskewed `>= monitorStart` bound would
|
|
28
|
+
* fail CLOSED under a fast client clock (this operation's own terminal event
|
|
29
|
+
* skipped → event-driven completion silently disabled), and an
|
|
30
|
+
* AWS-clock-only discriminator (terminal newer than the newest observed
|
|
31
|
+
* stack-level IN_PROGRESS) hangs any monitor attached to an
|
|
32
|
+
* already-in-flight operation. That residual is bounded: the completion
|
|
33
|
+
* verdict is re-read from live DescribeStacks in handleStackCompletion and
|
|
34
|
+
* the deploy result derives from the CDK subprocess lifecycle.
|
|
35
|
+
*
|
|
36
|
+
* The ClientRequestToken is NOT part of the residual (F-X9): the latched
|
|
37
|
+
* token becomes the webapp reconciler's §5.4 adoption comparand (heartbeat →
|
|
38
|
+
* Deployment.clientRequestToken → matchesToken/deriveAdoption), where a
|
|
39
|
+
* previous operation's token would corroborate the WRONG operation's
|
|
40
|
+
* outcome. Skew-window events are therefore dispatched with the token
|
|
41
|
+
* withheld (`tokenLatchCutoffMs`, unskewed) — an absent comparand merely
|
|
42
|
+
* skips adoption assist, and CFN's own ClientRequestToken remains the §5.3
|
|
43
|
+
* fencing backstop.
|
|
44
|
+
*/
|
|
45
|
+
export declare const EVENT_CUTOFF_SKEW_MS = 120000;
|
|
18
46
|
/** Mutable state passed into pollStackEvents from the monitor class */
|
|
19
47
|
export interface PollContext {
|
|
20
48
|
aws: AwsClientLike;
|
|
@@ -25,6 +53,23 @@ export interface PollContext {
|
|
|
25
53
|
maxHistorySize: number;
|
|
26
54
|
ipamTracker: IpamConcurrencyTracker;
|
|
27
55
|
eventLogger: EventLogWriter | null;
|
|
56
|
+
/**
|
|
57
|
+
* Epoch ms below which events belong to a PREVIOUS operation and are
|
|
58
|
+
* absorbed (marked seen, never processed or dispatched). Guards the case
|
|
59
|
+
* where the prime poll fails (throttle/network), leaving seenEventIds
|
|
60
|
+
* empty so the first live poll walks the stack's full prior history (F-F8).
|
|
61
|
+
*/
|
|
62
|
+
eventCutoffMs: number;
|
|
63
|
+
/**
|
|
64
|
+
* Epoch ms of startMonitoring, UNSKEWED (F-X9). Events at/after this bound
|
|
65
|
+
* carry their ClientRequestToken; events inside the skew window
|
|
66
|
+
* (eventCutoffMs ≤ t < tokenLatchCutoffMs) are dispatched with the token
|
|
67
|
+
* withheld — the token feeds the tracker's §5.9 latch and thence the
|
|
68
|
+
* reconciler's adoption comparand, where a previous operation's token
|
|
69
|
+
* corroborates the wrong operation. Dispatch and terminal detection keep
|
|
70
|
+
* the skewed cutoff.
|
|
71
|
+
*/
|
|
72
|
+
tokenLatchCutoffMs: number;
|
|
28
73
|
}
|
|
29
74
|
/** Poll CloudFormation for new stack events and dispatch them to the callback */
|
|
30
75
|
export declare function pollStackEvents(ctx: PollContext, stackName: string, onResourceUpdate: (event: ResourceEvent) => void): Promise<boolean | "throttled">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CloudFormationClient as
|
|
1
|
+
import{CloudFormationClient as R,DescribeStackEventsCommand as y,DescribeStacksCommand as L}from"@aws-sdk/client-cloudformation";import{logger as T}from"@fjall/util/logger";import{getErrorMessage as f,maskSensitiveOutput as P}from"@fjall/util";import{STACK_NOT_FOUND_PATTERN as S,maskFailureAnalysis as k}from"@fjall/util/aws";import{CF_STACK_RESOURCE_TYPE as g}from"./cloudformationEventTypes.js";import{extractErrorName as A}from"../organisations/types.js";const h=["CREATE_COMPLETE","CREATE_FAILED","DELETE_COMPLETE","DELETE_FAILED","UPDATE_COMPLETE","UPDATE_FAILED","UPDATE_ROLLBACK_COMPLETE","UPDATE_ROLLBACK_FAILED","ROLLBACK_COMPLETE","ROLLBACK_FAILED","IMPORT_COMPLETE","IMPORT_ROLLBACK_COMPLETE","IMPORT_ROLLBACK_FAILED"],_=["CREATE_COMPLETE","UPDATE_COMPLETE","DELETE_COMPLETE","IMPORT_COMPLETE"];function M(t){return h.includes(t)}function b(t){return _.includes(t)}const O=new Set(["AWS::EC2::IPAMPool","AWS::EC2::IPAMPoolCidr","AWS::EC2::IPAM"]);function F(t){return O.has(t)}class ${inProgress=new Map;get size(){return this.inProgress.size}clear(){this.inProgress.clear()}trackEvent(e,i){if(e.status.includes("IN_PROGRESS")){this.inProgress.set(e.logicalId,{resourceType:e.resourceType,startTime:e.timestamp});const o=Array.from(this.inProgress.entries()).map(([n,r])=>`${n} (${r.resourceType.split("::").pop()}, started ${r.startTime.toISOString()})`);T.debug("CloudFormation","IPAM resource started",{logicalId:e.logicalId,resourceType:e.resourceType,concurrentIpamCount:this.inProgress.size,concurrentIpamResources:o}),i&&i.writeEvent(e,{phase:"ipam_concurrency",isMainStack:!0,parentStack:`concurrent=${this.inProgress.size}: ${o.join(", ")}`})}else if(e.status.includes("COMPLETE")||e.status.includes("FAILED")){const o=this.inProgress.has(e.logicalId),n=this.inProgress.get(e.logicalId);this.inProgress.delete(e.logicalId);const r=n?e.timestamp.getTime()-n.startTime.getTime():void 0;if(T.debug("CloudFormation",`IPAM resource ${e.status}`,{logicalId:e.logicalId,resourceType:e.resourceType,status:e.status,statusReason:e.statusReason,durationMs:r,wasTracked:o,remainingIpamCount:this.inProgress.size,remainingIpamResources:Array.from(this.inProgress.keys())}),e.status.includes("FAILED")&&i){const u=Array.from(this.inProgress.entries()).map(([a,c])=>({logicalId:a,resourceType:c.resourceType,startTime:c.startTime.toISOString(),inFlightDurationMs:e.timestamp.getTime()-c.startTime.getTime()}));i.writeEvent(e,{phase:"ipam_failure_snapshot",isMainStack:!0,parentStack:JSON.stringify({failedResource:e.logicalId,reason:e.statusReason,durationMs:r,concurrentIpamAtFailure:u})})}}}}const H=12e4;async function B(t,e,i){try{const o=t.aws.getClient(R);let n,r=!1,u=!1;do{const a=new y({StackName:e,...n?{NextToken:n}:{}}),c=await o.send(a);if(!c.StackEvents)break;for(const s of c.StackEvents){const m=`${s.EventId}`;if(t.seenEventIds.has(m)){u=!0;continue}if(t.seenEventIds.add(m),s.Timestamp!==void 0&&s.Timestamp.getTime()<t.eventCutoffMs){u=!0;continue}if(s.ResourceType===g&&s.LogicalResourceId!==e){const E=s.ResourceStatus||"",p=s.LogicalResourceId||"";E.includes("IN_PROGRESS")?t.activeNestedStacks.set(p,E):(E.includes("COMPLETE")||E.includes("FAILED"))&&t.activeNestedStacks.delete(p)}if(s.LogicalResourceId===e&&s.ResourceType===g){const E=s.ResourceStatus||"";M(E)&&(r=!0)}s.ResourceStatus&&s.ResourceStatus.includes("FAILED")&&s.ResourceStatusReason&&(t.failureReasons.set(s.LogicalResourceId||"unknown",s.ResourceStatusReason),T.debug("CloudFormation",`Captured failure: ${s.LogicalResourceId} - ${s.ResourceStatusReason}`));const l=s.Timestamp===void 0||s.Timestamp.getTime()>=t.tokenLatchCutoffMs,d={logicalId:s.LogicalResourceId||"",physicalId:s.PhysicalResourceId,resourceType:s.ResourceType||"",status:s.ResourceStatus||"",statusReason:s.ResourceStatusReason,timestamp:s.Timestamp||new Date,clientRequestToken:l?s.ClientRequestToken:void 0},I=d.logicalId,C=t.eventHistory.get(I)??[];if(C.push(d),t.eventHistory.set(I,C),t.eventHistory.size>t.maxHistorySize){const E=[...t.eventHistory.keys()].slice(0,t.eventHistory.size-t.maxHistorySize);for(const p of E)t.eventHistory.delete(p)}F(d.resourceType)&&t.ipamTracker.trackEvent(d,t.eventLogger),t.eventLogger&&t.eventLogger.writeEvent(d),T.debug("CloudFormation","pollEvents delivering event",{stackName:e,logicalId:d.logicalId,status:d.status,resourceType:d.resourceType}),i(d)}n=u?void 0:c.NextToken}while(n);return r&&t.activeNestedStacks.size>0?!1:r}catch(o){const n=A(o),r=f(o);return n==="ValidationError"&&r.includes(S)?!1:n==="Throttling"||n==="TooManyRequestsException"||n==="ThrottlingException"?"throttled":(r.includes(S)||T.error("CloudFormation","Unexpected polling error",{error:P(r)}),!1)}}async function W(t,e,i,o,n,r){const u=await D(t,e),a=u?.status||"UNKNOWN",c=a.endsWith("_COMPLETE")&&!a.includes("ROLLBACK")&&!a.includes("FAILED");let s=u?.statusReason;!c&&i.size>0&&(s=(Array.from(i.values())[0]??s)||s);let m=null;if(!c&&n){const l=n.analyseFailure(r,e);m=l===null?null:k(l)}return o&&(o.writeDeploymentEnd(c,a,s),!c&&i.size>0&&o.writeFailureSummary(Array.from(i.entries()).map(([l,d])=>({logicalId:l,reason:d}))),m&&o.writeFailureAnalysis({rootCause:m.rootCause.reason,failedResources:m.affectedResources.map(l=>({logicalId:l.logicalId,resourceType:l.resourceType,reason:l.statusReason||"Unknown reason"})),dependencyChain:m.dependencyChain,remediation:m.remediation})),{success:c,failureMessage:s,analysis:m}}async function D(t,e){try{const i=new L({StackName:e}),r=(await t.getClient(R).send(i)).Stacks?.[0];return r?{status:r.StackStatus||"UNKNOWN",statusReason:r.StackStatusReason}:null}catch(i){return T.debug("CloudFormation","getStackStatus failed",{error:f(i)}),null}}async function q(t,e){const i=[];try{const o=new y({StackName:e}),r=await t.getClient(R).send(o);if(!r.StackEvents)return i;const u=new Map;for(const a of r.StackEvents){const c=a.LogicalResourceId||"";if(c===e&&a.ResourceType===g)continue;const s=u.get(c);(!s||a.Timestamp&&s.timestamp<a.Timestamp)&&u.set(c,{logicalId:c,physicalId:a.PhysicalResourceId,resourceType:a.ResourceType||"",status:a.ResourceStatus||"",statusReason:a.ResourceStatusReason,timestamp:a.Timestamp||new Date,clientRequestToken:a.ClientRequestToken})}return Array.from(u.values())}catch(o){const n=A(o),r=f(o);return n==="ValidationError"&&r.includes(S)||r.includes(S)||T.error("CloudFormation","Error getting current resources",{error:P(f(o))}),i}}export{H as EVENT_CUTOFF_SKEW_MS,$ as IpamConcurrencyTracker,q as fetchCurrentResources,D as fetchStackStatus,W as handleStackCompletion,F as isIpamResource,b as isSuccessState,M as isTerminalState,B as pollStackEvents};
|
|
@@ -32,7 +32,7 @@ export interface EventLogWriter {
|
|
|
32
32
|
}
|
|
33
33
|
/** Interface for failure analysis — decouples from concrete CloudFormationFailureAnalyser */
|
|
34
34
|
export interface EventFailureAnalyser {
|
|
35
|
-
analyseFailure(eventHistory: Map<string, ResourceEvent[]
|
|
35
|
+
analyseFailure(eventHistory: Map<string, ResourceEvent[]>, stackName?: string): FailureAnalysis | null;
|
|
36
36
|
}
|
|
37
37
|
/** Factory to create an EventLogWriter for a specific deployment */
|
|
38
38
|
export type EventLogWriterFactory = (deploymentId: string, stackName: string, region: string, deploymentName?: string) => EventLogWriter;
|
|
@@ -15,10 +15,11 @@ export declare class CloudFormationEventMonitor {
|
|
|
15
15
|
private eventLogWriterFactory;
|
|
16
16
|
private onFailureAnalysis;
|
|
17
17
|
private lastAnalysis;
|
|
18
|
-
private deploymentStartTime;
|
|
19
18
|
private maxHistorySize;
|
|
20
19
|
private maxSeenEventIds;
|
|
21
20
|
private ipamTracker;
|
|
21
|
+
private eventCutoffMs;
|
|
22
|
+
private tokenLatchCutoffMs;
|
|
22
23
|
constructor(aws: AwsClientLike, deps?: EventMonitorDeps);
|
|
23
24
|
enableLogging(deploymentId: string, stackName: string, region: string, deploymentName?: string): void;
|
|
24
25
|
startMonitoring(stackName: string, onResourceUpdate: (event: ResourceEvent) => void, onStackComplete?: (success: boolean, message?: string) => void): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as
|
|
1
|
+
import{logger as c}from"@fjall/util/logger";import{getErrorMessage as v,sleep as m}from"@fjall/util";import{STACK_NOT_FOUND_PATTERN as S}from"@fjall/util/aws";import{isResourceEvent as K,STACK_NOT_FOUND_PATTERN as O,CDK_NO_STACKS_MATCH as b}from"@fjall/util/aws";import{CF_STACK_RESOURCE_TYPE as p}from"./cloudformationEventTypes.js";import{isTerminalState as d,isSuccessState as M,IpamConcurrencyTracker as C,pollStackEvents as w,handleStackCompletion as E,fetchStackStatus as F,fetchCurrentResources as L,EVENT_CUTOFF_SKEW_MS as T}from"./cloudformationEventHelpers.js";class D{aws;seenEventIds=new Set;isMonitoring=!1;pollInterval=null;activeNestedStacks=new Map;failureReasons=new Map;eventHistory=new Map;eventLogger=null;failureAnalyser;eventLogWriterFactory;onFailureAnalysis;lastAnalysis=null;maxHistorySize=1e3;maxSeenEventIds=1e4;ipamTracker=new C;eventCutoffMs=0;tokenLatchCutoffMs=0;constructor(t,e){this.aws=t,this.failureAnalyser=e?.failureAnalyser??null,this.eventLogWriterFactory=e?.eventLogWriterFactory,this.onFailureAnalysis=e?.onFailureAnalysis}enableLogging(t,e,r,a){this.eventLogWriterFactory&&(this.eventLogger=this.eventLogWriterFactory(t,e,r,a))}async startMonitoring(t,e,r){if(this.isMonitoring){c.debug("CloudFormation","startMonitoring SKIPPED - already monitoring",{stackName:t});return}c.debug("CloudFormation","startMonitoring STARTED",{stackName:t}),this.isMonitoring=!0,this.seenEventIds.clear(),this.eventHistory.clear();const a=Date.now();this.eventCutoffMs=a-T,this.tokenLatchCutoffMs=a;try{await this.pollEvents(t,()=>{})}catch(o){const h=v(o);h.includes(S)||c.debug("CloudFormation","Initial poll failed",{error:h})}let s=5e3;const n=1e4;let g=0,l=0;const u=async()=>{if(this.isMonitoring)try{const o=await this.pollEvents(t,e);g++,o==="throttled"?(l++,s=Math.min(3e4,5e3*Math.pow(2,l-1))):(l=0,g>20&&s<n?s=Math.min(n,s+1e3):g<=20&&(s=5e3)),o===!0?await this.handleStackComplete(t,r):this.pollInterval=setTimeout(u,s)}catch(o){c.debug("CloudFormation","Polling iteration error (continuing)",{error:v(o)}),this.pollInterval=setTimeout(u,s)}};this.pollInterval=setTimeout(u,s)}stopMonitoring(){c.debug("CloudFormation","stopMonitoring called",{wasMonitoring:this.isMonitoring,seenEventCount:this.seenEventIds.size}),this.isMonitoring=!1,this.pollInterval&&(clearTimeout(this.pollInterval),this.pollInterval=null),this.cleanup()}cleanup(){if(this.activeNestedStacks.clear(),this.failureReasons.clear(),this.eventHistory.clear(),this.ipamTracker.clear(),this.seenEventIds.size>this.maxSeenEventIds){const t=Array.from(this.seenEventIds),e=Math.floor(this.maxSeenEventIds/2);this.seenEventIds=new Set(t.slice(-e))}this.eventLogger&&(this.eventLogger=null)}async handleStackComplete(t,e){const r=new Map(this.failureReasons),a=new Map(this.eventHistory),s=this.eventLogger;this.stopMonitoring();const n=await E(this.aws,t,r,s,this.failureAnalyser,a);this.lastAnalysis=n.analysis,n.analysis&&this.onFailureAnalysis&&this.onFailureAnalysis(n.analysis),e&&e(n.success,n.failureMessage)}getResourceHistory(t){return this.eventHistory.get(t)||[]}getEventHistory(){return new Map(this.eventHistory)}getFailureAnalysis(){return this.lastAnalysis}getFirstFailureReason(){return this.failureReasons.size>0?Array.from(this.failureReasons.values())[0]??null:null}getEventLogger(){return this.eventLogger}getEventLogPath(){return this.eventLogger?.getLogPath()||null}getLogSummary(){return this.eventLogger?.getLogSummary()||null}async waitForStackComplete(t,e={}){const{timeout:r=1800*1e3,pollInterval:a=2e3,onResourceUpdate:s,onStackComplete:n}=e,g=Date.now();let l,u=!1,o=!1,h;c.debug("CloudFormation","waitForStackComplete called",{stackName:t,timeout:r,pollInterval:a,hasOnResourceUpdate:!!s}),await this.startMonitoring(t,i=>{s&&s(i),i.resourceType===p&&i.logicalId===t&&(l=i.status,d(i.status)&&(u=!0,o=M(i.status),o||(h=this.getFirstFailureReason()||i.statusReason||"Stack operation failed")))},(i,f)=>{n&&n(i,f)});try{let i=!1,f=!1;for(;!u&&this.isMonitoring&&Date.now()-g<r;)await m(a),!i&&Date.now()-g>3e4&&!f&&(f=!0,await this.getStackStatus(t)||c.debug("CloudFormation","Stack not found after 30s, continuing to wait (CDK may be uploading assets)",{stackName:t})),l&&(i=!0);if(this.stopMonitoring(),!u){if(h)return{success:!1,status:"FAILED",failureReason:h,logPath:this.getLogSummary()||void 0};const y=await this.getStackStatus(t);return{success:!1,status:y?.status||"UNKNOWN",failureReason:`Deployment timed out after ${r/1e3} seconds. Stack status: ${y?.status||"UNKNOWN"}`,logPath:this.getLogSummary()||void 0}}return{success:o,status:l,failureReason:h,logPath:this.getLogSummary()||void 0}}catch(i){return this.stopMonitoring(),{success:!1,failureReason:`Monitoring error: ${v(i)}`,logPath:this.getLogSummary()||void 0}}}pollContext(){return{aws:this.aws,seenEventIds:this.seenEventIds,activeNestedStacks:this.activeNestedStacks,failureReasons:this.failureReasons,eventHistory:this.eventHistory,maxHistorySize:this.maxHistorySize,ipamTracker:this.ipamTracker,eventLogger:this.eventLogger,eventCutoffMs:this.eventCutoffMs,tokenLatchCutoffMs:this.tokenLatchCutoffMs}}async pollEvents(t,e){return w(this.pollContext(),t,e)}async getStackStatus(t){return F(this.aws,t)}async getCurrentResources(t){return L(this.aws,t)}}export{b as CDK_NO_STACKS_MATCH,D as CloudFormationEventMonitor,O as STACK_NOT_FOUND_PATTERN,K as isResourceEvent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e={CREATE_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is busy with creation"},CREATE_COMPLETE:{safeToRedeploy:"Yes",description:"Stack was successfully created"},CREATE_FAILED:{safeToRedeploy:"Maybe",description:"Stack creation failed - fix issues before redeploying"},DELETE_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is busy with deletion"},DELETE_COMPLETE:{safeToRedeploy:"Yes",description:"Stack was successfully deleted"},DELETE_FAILED:{safeToRedeploy:"Maybe",description:"Stack deletion failed - investigate before redeploying"},ROLLBACK_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is rolling back due to failure"},ROLLBACK_COMPLETE:{safeToRedeploy:"Yes",description:"Stack rolled back due to failure - fix issues before redeploying"},ROLLBACK_FAILED:{safeToRedeploy:"No",description:"Rollback failed - manual intervention needed"},UPDATE_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack update is in progress"},UPDATE_COMPLETE:{safeToRedeploy:"Yes",description:"Stack update completed successfully"},UPDATE_FAILED:{safeToRedeploy:"Maybe",description:"Stack update failed - fix issues before redeploying"},UPDATE_ROLLBACK_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is rolling back an update"},UPDATE_ROLLBACK_COMPLETE:{safeToRedeploy:"Yes",description:"Stack update rolled back successfully"},UPDATE_ROLLBACK_FAILED:{safeToRedeploy:"No",description:"Update rollback failed - manual fix needed"},IMPORT_IN_PROGRESS:{safeToRedeploy:"No",description:"Resource import in progress"},IMPORT_COMPLETE:{safeToRedeploy:"Yes",description:"Resource import completed successfully"},IMPORT_ROLLBACK_IN_PROGRESS:{safeToRedeploy:"No",description:"Import rollback in progress"},IMPORT_ROLLBACK_COMPLETE:{safeToRedeploy:"Yes",description:"Import rollback completed"},IMPORT_ROLLBACK_FAILED:{safeToRedeploy:"No",description:"Import rollback failed - manual fix needed"},REVIEW_IN_PROGRESS:{safeToRedeploy:"Yes",description:"Stack is in review mode"},UNKNOWN:{safeToRedeploy:"Maybe",description:"Unknown stack status"}};export{e as stackStatusMap};
|
|
1
|
+
const e={CREATE_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is busy with creation"},CREATE_COMPLETE:{safeToRedeploy:"Yes",description:"Stack was successfully created"},CREATE_FAILED:{safeToRedeploy:"Maybe",description:"Stack creation failed - fix issues before redeploying"},DELETE_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is busy with deletion"},DELETE_COMPLETE:{safeToRedeploy:"Yes",description:"Stack was successfully deleted"},DELETE_FAILED:{safeToRedeploy:"Maybe",description:"Stack deletion failed - investigate before redeploying"},ROLLBACK_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is rolling back due to failure"},ROLLBACK_COMPLETE:{safeToRedeploy:"Yes",description:"Stack rolled back due to failure - fix issues before redeploying"},ROLLBACK_FAILED:{safeToRedeploy:"No",description:"Rollback failed - manual intervention needed"},UPDATE_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack update is in progress"},UPDATE_COMPLETE_CLEANUP_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack update is finalising - old resources being cleaned up"},UPDATE_COMPLETE:{safeToRedeploy:"Yes",description:"Stack update completed successfully"},UPDATE_FAILED:{safeToRedeploy:"Maybe",description:"Stack update failed - fix issues before redeploying"},UPDATE_ROLLBACK_IN_PROGRESS:{safeToRedeploy:"No",description:"Stack is rolling back an update"},UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS:{safeToRedeploy:"No",description:"Update rollback is finalising - old resources being cleaned up"},UPDATE_ROLLBACK_COMPLETE:{safeToRedeploy:"Yes",description:"Stack update rolled back successfully"},UPDATE_ROLLBACK_FAILED:{safeToRedeploy:"No",description:"Update rollback failed - manual fix needed"},IMPORT_IN_PROGRESS:{safeToRedeploy:"No",description:"Resource import in progress"},IMPORT_COMPLETE:{safeToRedeploy:"Yes",description:"Resource import completed successfully"},IMPORT_ROLLBACK_IN_PROGRESS:{safeToRedeploy:"No",description:"Import rollback in progress"},IMPORT_ROLLBACK_COMPLETE:{safeToRedeploy:"Yes",description:"Import rollback completed"},IMPORT_ROLLBACK_FAILED:{safeToRedeploy:"No",description:"Import rollback failed - manual fix needed"},REVIEW_IN_PROGRESS:{safeToRedeploy:"Yes",description:"Stack is in review mode"},UNKNOWN:{safeToRedeploy:"Maybe",description:"Unknown stack status"}};export{e as stackStatusMap};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -15,16 +15,21 @@ export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURC
|
|
|
15
15
|
export type { DeploymentEvent, DeploymentEventType, DeploymentEventResourceCategory, DeploymentEventCascadePhase, DeploymentEventCascadeAccountStatus } from "./types/index.js";
|
|
16
16
|
export { DeployEventSchema, StepProgressSchema, DeployResourceSchema, PlanChangeSchema, PlanPropertyChangeSchema, ChangeCountsSchema, DEPLOY_EVENT_CONTRACT, DEPLOY_EVENT_CONTRACT_MAJOR, DEPLOY_EVENT_CONTRACT_MINOR, SUPPORTED_CONTRACT_MARKERS, DEPLOY_EVENT_ID_MAX, DEPLOY_EVENT_NAME_MAX, DEPLOY_EVENT_MESSAGE_MAX, DEPLOY_EVENT_STATUS_REASON_MAX, DEPLOY_EVENT_ERROR_MESSAGE_MAX, DEPLOY_EVENT_TRAIL_DETAIL_MAX, DEPLOY_EVENT_OUTPUT_MAX, DEPLOY_EVENT_ARN_MAX, DEPLOY_EVENT_URL_MAX, STEP_COMPLETE_STATUSES, LOG_LEVELS, STACK_CLEANUP_PHASES, CASCADE_ACCOUNT_PHASES, DEPLOY_RESULTS, DETECTION_PHASES, PHASE_STATUSES, BUILDERS, CASCADE_OUTCOME_RESULTS, PLAN_ACTIONS, REPLACEMENT_MODES, APPROVAL_KINDS, APPROVAL_DECISIONS, ALL_PROGRESS_KINDS, createDeployEmitter, parseDeployEvent, parseDeployContractVersion } from "./types/index.js";
|
|
17
17
|
export type { DeployEvent, ProgressKind, StepProgress, DeployResource, PlanChange, PlanPropertyChange, ChangeCounts, PlanAction, ReplacementMode, ApprovalKind, ApprovalDecision, DeployRunResult, DeployEmitter, CreateDeployEmitterOptions, ParsedDeployEvent, StackCleanupPhase, CascadeAccountPhase, LogLevel } from "./types/index.js";
|
|
18
|
-
export type { AwsCredentials, DeployIdentity, ScopedBuildSecretSessionMinter, DeployCallbacks, StepCompleteStatus, StackCleanupQuarantineDetail, StackCleanupRetainedBucketsDetail, ProgressEvent, ProgressEventType, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhase, TrailMigrationStatus, TrailMigrationPhaseEvent, ApiClientInterface, EntitlementsData, DeployParams, DeployOptions, DeploymentType, DeployResult, DestroyParams, DestroyOptions, DestroyResult, ApprovalGate, ApprovalGatePlanDetail, ApprovalRequest, GateResolution, OrgConfig, ProviderAccount, RootAccessManagementMode, SSOSession, Entitlements } from "./types/index.js";
|
|
18
|
+
export type { AwsCredentials, DeployIdentity, ScopedBuildSecretSessionMinter, DeployCallbacks, StepCompleteStatus, StackCleanupQuarantineDetail, StackCleanupRetainedBucketsDetail, StackTarget, ProgressEvent, ProgressEventType, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhase, TrailMigrationStatus, TrailMigrationPhaseEvent, ApiClientInterface, EntitlementsData, DeployParams, DeployOptions, DatabaseEndpointRestartRequest, InfrastructureSource, DeploymentType, DeployResult, DestroyParams, DestroyOptions, DestroyResult, StackLeaseVerdict, ApprovalGate, ApprovalGatePlanDetail, ApprovalRequest, GateResolution, RemediationVerb, DestructionFinding, DestructionTicketResource, DestructionTicket, DestructionConsent, ConsentVerdict, ConsentVerdictRow, DestructionConsentReport, DestructionConsentRequest, DestructionConsentResolution, DestructionConsentGate, DestructionOutcome, TicketVerdictSource, RemediationPhase, RemediationTarget, RemediationFlipProof, RemediationJournalRecord, OrgConfig, ProviderAccount, RootAccessManagementMode, SSOSession, Entitlements } from "./types/index.js";
|
|
19
19
|
export type { AwsProvider, AwsProviderCredentials, AwsSdkClientConstructor } from "./aws/index.js";
|
|
20
20
|
export { SimpleAwsProvider } from "./aws/index.js";
|
|
21
21
|
export { checkTargetReadiness, describeTargetReadinessReason, buildTargetUnreadyAdvisory, buildTargetSetUnreadyAdvisory, probeAccountStackExists } from "./aws/index.js";
|
|
22
22
|
export type { TargetReadinessAccount, TargetReadinessClients, TargetReadinessReason, TargetReadinessVerdict, TargetSetUnreadyAdvisoryParams } from "./aws/index.js";
|
|
23
23
|
export { checkRegionEnabled, regionDisabledMessage } from "./aws/index.js";
|
|
24
24
|
export type { RegionAvailability } from "./aws/index.js";
|
|
25
|
-
export { ensureOrganisationExists, describeOrganisation, enablePolicyTypes, enableServiceAccess, SERVICE_PRINCIPALS, enableRamSharing, activateTrustedAccess, enableIpamDelegatedAdmin, updateBackupGlobalSettings, listAccounts, findAccount, createAccount, ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap, activateCostAllocationTags, checkIdentityCentreStatus, snapshotIdentityCentre, composeSdkAbortSignal, extractErrorName, isAborted, DEFAULT_MAX_PAGES, IDENTITY_STORE_PAGE_SIZE, drainPages, isOULeaf, registerSecurityDelegates, SECURITY_SERVICE_PRINCIPALS, enableCentralisedRootAccess, ROOT_ACCESS_FEATURES, RootAccessEnablementError } from "./aws/index.js";
|
|
25
|
+
export { ensureOrganisationExists, describeOrganisation, enablePolicyTypes, enableServiceAccess, SERVICE_PRINCIPALS, enableRamSharing, activateTrustedAccess, enableIpamDelegatedAdmin, updateBackupGlobalSettings, listAccounts, findAccount, createAccount, ensureOrganisationalUnitsExist, placeAccountsInOUs, buildAccountToOUMap, findDevelopmentOuId, activateCostAllocationTags, checkIdentityCentreStatus, snapshotIdentityCentre, composeSdkAbortSignal, extractErrorName, isAborted, DEFAULT_MAX_PAGES, IDENTITY_STORE_PAGE_SIZE, drainPages, isOULeaf, registerSecurityDelegates, SECURITY_SERVICE_PRINCIPALS, enableCentralisedRootAccess, ROOT_ACCESS_FEATURES, RootAccessEnablementError } from "./aws/index.js";
|
|
26
26
|
export type { OrgDetails, OUMap, OUTree, AccountPlacementResult, AccountInfo, DrainPagesOptions, PagedResult, IdentityCentreStatus, IdentityCentreSnapshot, IdentityCentreSnapshotGroup, IdentityCentreSnapshotOptions, IdentityCentreSnapshotResult, IdentityCentreSnapshotUser, BackupGlobalSettings, CostAllocationTag, CreateAccountResult, RootAccessFeature, RootAccessEnablementSummary } from "./aws/index.js";
|
|
27
27
|
export { STEP_IDS, STEP_NAMES, INFRASTRUCTURE_STEP_NAMES, INFRA_STEP_NAME } from "./types/index.js";
|
|
28
|
+
export { RemediationVerbSchema, REMEDIATION_VERB_GLOSS, DestructionFindingSchema, DestructionTicketResourceSchema, DestructionTicketSchema, DestructionConsentSchema, DestructionOutcomeSchema, DESTRUCTION_FINDINGS, CONSENT_VERDICTS, TICKET_VERDICT_SOURCES, TicketVerdictSourceSchema } from "./types/index.js";
|
|
29
|
+
export { DRIFT_VERDICTS, DriftVerdictSchema, DriftSuspectSchema, DriftFindingSchema, DriftJournalRecordSchema, verbsForDriftVerdict } from "./types/index.js";
|
|
30
|
+
export { REMEDIATION_PHASES, RemediationPhaseSchema, RemediationTargetSchema, RemediationFlipProofSchema, RemediationJournalRecordSchema, RemediationVerbWithSurgerySchema, remediationPhaseRank, remediationPlaceholderPhysicalId, isRemediationPlaceholderPhysicalId } from "./types/index.js";
|
|
31
|
+
export type { RemediationVerbWithSurgery } from "./types/index.js";
|
|
32
|
+
export type { DriftVerdict, DriftSuspect, DriftFinding, DriftJournalRecord } from "./types/index.js";
|
|
28
33
|
export type { StepId, InfrastructureStepName, StepDefinition, StepDeploymentType, Operation, StepContext } from "./types/index.js";
|
|
29
34
|
export type { DeploymentContext, StepOutput, ApplicationDeploymentContext, CallerIdentity, StackOutput, StackOutputsRecord, ValidationResult, DetectionResult, ProgressCallbacks, ApplicationStack, OrganisationType, DeploymentOperation, ApplicationOperation, OrganisationOperation, DeployOrderOptions, ParallelDeployGroupKey, ParallelDestroyGroupKey, OpenNextPattern, AppResourceFlags, ParallelDeploymentResult, ParallelDeployGroup, ParallelOperation, ParallelOperationType, ParallelOperationState, ApplicationErrorType, StackDeploymentData, StackDeploymentOptions, ApplicationDeploymentData, ApplicationDestructionData, FjallStateFile, TemplateHashEntry } from "./types/index.js";
|
|
30
35
|
export { ProgressReporter, APPLICATION_STACKS, ORGANISATION_TYPES, APPLICATION_DEPLOY_ORDER, APPLICATION_DESTROY_ORDER, OPENNEXT_DEPLOY_ORDER, OPENNEXT_DESTROY_ORDER, PARALLEL_DEPLOY_GROUPS, PARALLEL_DESTROY_GROUPS, OPENNEXT_PARALLEL_GROUPS, PARALLEL_OPERATION_TYPES, isApplicationOperation, isOrganisationOperation, getParallelDeployGroups, getParallelDestroyGroups, getApplicationDeployOrder, getApplicationDestroyOrder, getApplicationStackName, getOrganisationStackName, isApplicationStack, isQuarantineDetail, isRetainedBucketsDetail, getApplicationStepName, getApplicationStepId, toPascalCase, isOpenNextPattern, OPENNEXT_PATTERNS, deriveResourcesFromManifestStacks, STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME, ApplicationError, wrapApplicationError, FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, stubCallerIdentity } from "./types/index.js";
|
|
@@ -55,6 +60,10 @@ export { reconcileProviderAccounts, mergeReconciledProviderAccounts } from "./or
|
|
|
55
60
|
export type { ReconcileResult } from "./orchestration/index.js";
|
|
56
61
|
export { decideNextTransition, reconcileTrailMigration, decommissionMemberTrailStorage, ORG_TRAIL_BUCKET_OUTPUT_KEY, TRAIL_BUCKET_OUTPUT_KEY, TRAIL_KEY_ARN_OUTPUT_KEY } from "./orchestration/index.js";
|
|
57
62
|
export type { MemberTrailFacts, TrailMigrationTransition, TrailMigrationOutcome, DecommissionClients, DecommissionInput, DecommissionOutcome } from "./orchestration/index.js";
|
|
63
|
+
export { classifyDriftFailure, fetchLastOperationEvents, DriftProbe, clearDriftSuspects, defaultDriftJournalDir, readDriftSuspects, recordDriftSuspects, detectStackDrift, runDriftPreFlight, formatDriftPreFlightBlock, DRIFT_PREFLIGHT_TRIGGER_STATUSES, DRIFT_PREFLIGHT_BUDGET_MS } from "./orchestration/index.js";
|
|
64
|
+
export type { DriftProbeOptions, DriftProbeRunner, ProbeDriftSuspectsParams, DriftJournalOptions, RecordDriftSuspectsParams, DetectStackDriftDeps, DetectStackDriftParams, StackDriftReport, RunDriftPreFlightParams, DriftPreFlightBlockExtras, DriftPreFlightOutcome } from "./orchestration/index.js";
|
|
65
|
+
export { archiveCompletedRemediationJournal, computeRemediationOpId, defaultRemediationJournalDir, findRemediationJournalByOpId, listActiveRemediationOps, listActiveRemediationOpsForContext, readRemediationJournal, sweepExpiredRemediationJournals, writeRemediationJournal, REMEDIATION_JOURNAL_RETENTION_DAYS, captureRemediationForensics, defaultRemediationForensicsDir, applyRetainFlip, composeFlipCapabilities, computeTemplateDigest, deriveRetainFlipTemplate, findMarkedResourcesByOpId, proveFlipMetadataOnly, readRetainFlipState, verifyRetainFlipDiff, FORGET_MARKER_KEY, FORGET_FLIP_SPEC, RECREATE_MARKER_KEY, assessForgetResumability, completeForgetAfterConverge, completeForgetAfterDeploy, formatRecreateInFlightCures, partitionPreFlightByRemediation, runForgetSurgery, synthTemplateDeclaresResource, runRecreateSurgery, snapshotPolicyForType, SNAPSHOT_CAPABLE_RESOURCE_TYPES, runRecreatePreFlight, deriveRemovalTemplate, findRemovalDeletionFailures, proveRemovalTargetsOnly, advertisableDriftVerbs, buildDriftRepairTicket, runDriftRepairGate, formatPinOutcomeDetail, pinProbeCoverage, renderPinReportLines, runPinRemediation, composePostFailureRepairOffer, formatDriftRepairOffer, DriftRepairAvailableError, checkDeployPathStackAvailability, isDeployPathBlockingStatus, StackUnavailableError, assertLeaseBeforeStack, LeaseDeniedError } from "./orchestration/index.js";
|
|
66
|
+
export type { RemediationJournalContext, RemediationJournalOptions, CaptureRemediationForensicsParams, ForensicsCaptureOptions, RemediationForensicsBundle, ApplyRetainFlipOutcome, ApplyRetainFlipParams, DeriveRetainFlipParams, FlipDeletionPolicy, FlipProofResult, FlipSpec, RetainFlipDerivation, RetainFlipState, RecreateOrchestrationOptions, RecreateSurgeryParams, RecreateSurgeryReport, RecreatePreFlightStack, RunRecreatePreFlightParams, ProveRemovalTargetsOnlyParams, RemovalDeletionFailure, RemovalDerivation, RemovalProofResult, StrippedExport, CompleteForgetAfterDeployParams, CompleteForgetOutcome, CompleteForgetParams, ForeignMarkerOperation, ForgetOrchestrationOptions, ForgetResumeAssessment, ForgetResumeSource, ForgetSurgeryParams, ForgetSurgeryReport, PreFlightRemediationDeps, PreFlightRemediationPartition, DriftRepairGateOutcome, RunDriftRepairGateParams, ComposePostFailureRepairOfferParams, PinnedProperty, PinProbeCoverage, PinRemediationReport, PinReportOnlyReason, PinResourceOutcome, PinTarget, RunPinRemediationParams } from "./orchestration/index.js";
|
|
58
67
|
export { unlockBucket, unlockQueue } from "./orchestration/index.js";
|
|
59
68
|
export type { UnlockBucketInput, UnlockBucketReport, UnlockQueueInput, UnlockQueueReport } from "./orchestration/index.js";
|
|
60
69
|
export { triageBucketPolicy, isEnforceSslStatement, toResourcePolicyStatements, restoreBucketPolicy, synthesiseEnforceSslDocument, ensureEnforceSsl, restoreAndReconcileQuarantinedBucket } from "./orchestration/index.js";
|
|
@@ -76,3 +85,5 @@ export { openNextBuilder, dockerBuilder } from "./orchestration/index.js";
|
|
|
76
85
|
export { StepRegistry, getDestroyStepId } from "./steps/index.js";
|
|
77
86
|
export { buildDeployPlan, computeDeployPlan, computeAssemblyDigest, digestHead, classifyImpact, derivePropertyChanges, isDataLoss, isStatefulResourceType, renderPlanSummary, renderPlanLines, toWirePlanChanges, signApprovalToken, verifyApprovalToken, DEFAULT_APPROVAL_TTL_MS, APPROVAL_TOKEN_PATTERN, runApprovalGate } from "./orchestration/index.js";
|
|
78
87
|
export type { DeployPlan, DeployPlanResourceChange, StackTemplatePair, CfnTemplateReader, ComputeDeployPlanParams, ComputeDeployPlanStack, ImpactClassification, SignApprovalTokenOptions, SignedApprovalToken, VerifyApprovalTokenOptions, VerifyApprovalTokenResult, RunApprovalGateParams, ApprovalGateOutcome } from "./orchestration/index.js";
|
|
88
|
+
export { runDestructionGate, buildDestructionTicket, evaluateDestructionConsents, computeTicketDigest, legalRemediationVerbs, executableRemediationVerbs, advertisableRemediationVerbs, renderDestructionTicketLines, renderConsentVerdictLines, loadDeployPlan, createMemoisedPlanLoader } from "./orchestration/index.js";
|
|
89
|
+
export type { RunDestructionGateParams, DestructionGateOutcome, EvaluateDestructionConsentsParams, LoadDeployPlanParams, DeployPlanLoader } from "./orchestration/index.js";
|