@fjall/deploy-core 3.5.2 → 3.6.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/index.d.ts +4 -1
- package/dist/src/index.js +1 -1
- package/dist/src/orchestration/application/approvalGate.d.ts +11 -0
- package/dist/src/orchestration/application/approvalGate.js +1 -1
- package/dist/src/orchestration/domain/index.d.ts +2 -0
- package/dist/src/orchestration/domain/index.js +1 -1
- package/dist/src/orchestration/domain/route53Delegation.d.ts +23 -0
- package/dist/src/orchestration/domain/route53Delegation.js +1 -0
- package/dist/src/orchestration/domain/types.d.ts +6 -6
- package/dist/src/orchestration/domain/zoneClassifier.d.ts +201 -0
- package/dist/src/orchestration/domain/zoneClassifier.js +1 -0
- package/dist/src/orchestration/drift/route53RecordPreflight.d.ts +6 -0
- package/dist/src/orchestration/drift/route53RecordPreflight.js +2 -2
- package/dist/src/orchestration/index.d.ts +1 -1
- package/dist/src/orchestration/index.js +1 -1
- package/dist/src/types/config/DomainState.d.ts +82 -0
- package/dist/src/types/config/DomainState.js +2 -0
- package/dist/src/types/config/FjallState.d.ts +11 -1
- package/dist/src/types/config/FjallState.js +1 -1
- package/package.json +5 -4
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
230 files minified at 2026-07-19T21:13:20.771Z
|
package/dist/src/index.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export type { DeploymentContext, StepOutput, ApplicationDeploymentContext, Calle
|
|
|
35
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, STACK_NOT_FOUND_PATTERN, STACK_FAILED_STATE_PATTERN, CDK_NO_STACKS_MATCH, INFRASTRUCTURE_FILENAME, ApplicationError, wrapApplicationError, stubCallerIdentity } from "./types/index.js";
|
|
36
36
|
export { deriveResourcesFromManifestStacks } from "./types/detection/patternDetection.js";
|
|
37
37
|
export { FjallStateFileSchema, readStateFile, writeStateFile, createEmptyState, deleteStateFile, updateTemplateHash, getStateFilePath, regionSuffix } from "./types/config/FjallState.js";
|
|
38
|
+
export { readDomainState, writeDomainState, recordDomainDeployState, deleteDomainState, hashDomainDirectory, LEGACY_DOMAIN_STATE_FILENAME, type DomainDeployState } from "./types/config/DomainState.js";
|
|
38
39
|
export { CloudFormationEventMonitor } from "./aws/index.js";
|
|
39
40
|
export type { AwsClientLike, EventLogWriter, EventFailureAnalyser, EventLogWriterFactory, EventMonitorDeps } from "./aws/index.js";
|
|
40
41
|
export { CdkService, CdkArgumentBuilder, CdkProcessManager, CdkEventMonitor, startStackMonitoring, DEFAULT_DEPLOY_TIMEOUT_MS, isCdkError, formatInfrastructureError, getStructuralHint, getSourceContext, hasCdkDifferences, parseDiffOutput, CloudFormationService, CloudFormationError, EcsService, EcsError, EcsServiceResolver, type CfnExportsClient, TemplateHashService, TemplateHashError, type TemplateComparisonResult, CdkContextBuilder, emitProgress, PROGRESS_MESSAGES, parseBuildPhase, buildStepContextBuildConfig, convertCloudFormationOutputsToRecord, type CloudFormationOutput, ApplicationStackService } from "./services/index.js";
|
|
@@ -81,13 +82,15 @@ export { runOrganisationSetup, ORG_SETUP_PHASES } from "./orchestration/index.js
|
|
|
81
82
|
export type { OrgSetupPhase, OrgSetupCallbacks, OrgSetupConfig, OrgSetupResult, DockerProvider, DockerProgressCallback, DockerBuildParams, DockerBuildResult, ResolvedBuildSecret, ResolvedBuildSecrets, ECRInitParams, ECRInitResult, TagImagesParams, TagImagesResult, TagByDigestParams, DomainDeployProvider, DomainConfig, DomainDeployResult, DeployServices } from "./orchestration/index.js";
|
|
82
83
|
export { DOMAIN_DELEGATION_ERROR_TYPES, DomainDelegationError, DEFAULT_PUBLIC_RESOLVER_ADDRESSES, PUBLIC_DNS_QUERY_TIMEOUT_MS, createPublicResolvers, NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS, NS_PROPAGATION_DEFAULT_INTERVAL_MS, waitForNsPropagation, ACM_CAA_ISSUERS, runCaaPreflight, deployDelegatedDomain, CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE, templateOwnsDelegationRecord, deleteChildNsFromParent, nsDelegationPhysicalName, runDelegatedDomainDestroy } from "./orchestration/index.js";
|
|
83
84
|
export type { DomainDeployPhase, DomainDelegationErrorType, PublicCaaRecord, PublicDnsResolver, NsPropagationGateParams, NsPropagationVerdict, CaaPreflightParams, CaaPreflightVerdict, DelegatedDomainDeployer, DelegatedZonePhaseState, DeployDelegatedDomainParams, DelegatedDomainDeployOutcome, NsDeleteOutcome, DeleteChildNsParams, DelegationDestroyNsOutcome, DelegatedDomainDestroyOutcome, DelegatedDomainDestroyParams } from "./orchestration/index.js";
|
|
85
|
+
export { classifyZoneRecords, buildSatelliteRecordIndex, createSystemDnsNameProbe, systemDnsNameProbe, normaliseRecordName, isRoute53NameServer, isDelegatedToRoute53 } from "./orchestration/index.js";
|
|
86
|
+
export type { RecordClassification, ClassifiedRecord, ZoneClassificationReport, ZoneClassifierClients, ZoneClassifierPhase, ClassifyZoneOptions, SatelliteRecordIndex, AwsSdkClientLike, DnsProbeVerdict, DnsNameProbe } from "./orchestration/index.js";
|
|
84
87
|
export { resolveBuildSecrets, resolveSecretRefValue, resolveBuildSecretSessionProvider, sourcedRefsFromBuildArgs, resolveBuildArgs, buildBuildSecretSessionPolicy, buildDeploySessionPolicy, partitionForRegion, validateBuildGroup } from "./orchestration/index.js";
|
|
85
88
|
export type { ResolveBuildArgsContext, ResolveBuildArgsResult, SourcedBuildArgResolver, BuildSecretRef, BuildSecretSessionContext, DeploySessionContext, ValidateBuildGroupInput, BuildGroupMemberInputs } from "./orchestration/index.js";
|
|
86
89
|
export type { FrameworkBuilder, FrameworkDetection, BuildPlan, BuildCommand, BuildCallbacks, DetectionContext, BuildOptions } from "./types/index.js";
|
|
87
90
|
export { FrameworkRegistry, type ResolvedBuilder } from "./orchestration/index.js";
|
|
88
91
|
export { openNextBuilder, staticSiteBuilder, dockerBuilder } from "./orchestration/index.js";
|
|
89
92
|
export { StepRegistry, getDestroyStepId } from "./steps/index.js";
|
|
90
|
-
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";
|
|
93
|
+
export { buildDeployPlan, computeDeployPlan, computeAssemblyDigest, digestHead, classifyImpact, derivePropertyChanges, isDataLoss, isStatefulResourceType, renderPlanSummary, renderPlanLines, toWirePlanChanges, signApprovalToken, verifyApprovalToken, DEFAULT_APPROVAL_TTL_MS, APPROVAL_TOKEN_PATTERN, runApprovalGate, approvalRefusalReason } from "./orchestration/index.js";
|
|
91
94
|
export type { DeployPlan, DeployPlanResourceChange, StackTemplatePair, CfnTemplateReader, ComputeDeployPlanParams, ComputeDeployPlanStack, ImpactClassification, SignApprovalTokenOptions, SignedApprovalToken, VerifyApprovalTokenOptions, VerifyApprovalTokenResult, RunApprovalGateParams, ApprovalGateOutcome } from "./orchestration/index.js";
|
|
92
95
|
export { runDestructionGate, buildDestructionTicket, evaluateDestructionConsents, computeTicketDigest, legalRemediationVerbs, executableRemediationVerbs, advertisableRemediationVerbs, renderDestructionTicketLines, renderConsentVerdictLines, loadDeployPlan, createMemoisedPlanLoader } from "./orchestration/index.js";
|
|
93
96
|
export type { RunDestructionGateParams, DestructionGateOutcome, EvaluateDestructionConsentsParams, LoadDeployPlanParams, DeployPlanLoader } from "./orchestration/index.js";
|
package/dist/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as o,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as i,DEPLOYMENT_EVENT_STATUS_REASON_MAX as a,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as n,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as s,CASCADE_PHASES as E,CASCADE_ACCOUNT_STATUSES as c}from"./types/index.js";import{DeployEventSchema as l,StepProgressSchema as T,DeployResourceSchema as A,PlanChangeSchema as R,PlanPropertyChangeSchema as _,ChangeCountsSchema as p,DEPLOY_EVENT_CONTRACT as m,DEPLOY_EVENT_CONTRACT_MAJOR as u,DEPLOY_EVENT_CONTRACT_MINOR as d,SUPPORTED_CONTRACT_MARKERS as P,DEPLOY_EVENT_ID_MAX as O,DEPLOY_EVENT_NAME_MAX as D,DEPLOY_EVENT_MESSAGE_MAX as f,DEPLOY_EVENT_STATUS_REASON_MAX as C,DEPLOY_EVENT_ERROR_MESSAGE_MAX as N,DEPLOY_EVENT_TRAIL_DETAIL_MAX as g,DEPLOY_EVENT_OUTPUT_MAX as L,DEPLOY_EVENT_ARN_MAX as I,DEPLOY_EVENT_URL_MAX as y,STEP_COMPLETE_STATUSES as h,LOG_LEVELS as F,STACK_CLEANUP_PHASES as U,CASCADE_ACCOUNT_PHASES as v,DEPLOY_RESULTS as x,DETECTION_PHASES as M,PHASE_STATUSES as k,BUILDERS as b,CASCADE_OUTCOME_RESULTS as V,PLAN_ACTIONS as Y,REPLACEMENT_MODES as B,APPROVAL_KINDS as G,APPROVAL_DECISIONS as K,ALL_PROGRESS_KINDS as X,createDeployEmitter as H,parseDeployEvent as w,parseDeployContractVersion as J}from"./types/index.js";import{SimpleAwsProvider as j}from"./aws/index.js";import{checkTargetReadiness as q,describeTargetReadinessReason as Z,buildTargetUnreadyAdvisory as z,buildTargetSetUnreadyAdvisory as $,probeAccountStackExists as ee}from"./aws/index.js";import{checkRegionEnabled as te,regionDisabledMessage as oe}from"./aws/index.js";import{ensureOrganisationExists as ae,describeOrganisation as ne,enablePolicyTypes as se,enableServiceAccess as Ee,SERVICE_PRINCIPALS as ce,enableRamSharing as Se,activateTrustedAccess as le,enableIpamDelegatedAdmin as Te,updateBackupGlobalSettings as Ae,listAccounts as Re,findAccount as _e,createAccount as pe,ensureOrganisationalUnitsExist as me,placeAccountsInOUs as ue,buildAccountToOUMap as de,findDevelopmentOuId as Pe,activateCostAllocationTags as Oe,checkIdentityCentreStatus as De,snapshotIdentityCentre as fe,composeSdkAbortSignal as Ce,extractErrorName as Ne,isAborted as ge,DEFAULT_MAX_PAGES as Le,IDENTITY_STORE_PAGE_SIZE as Ie,drainPages as ye,isOULeaf as he,registerSecurityDelegates as Fe,SECURITY_SERVICE_PRINCIPALS as Ue,enableCentralisedRootAccess as ve,ROOT_ACCESS_FEATURES as xe,RootAccessEnablementError as Me}from"./aws/index.js";import{STEP_IDS as be,STEP_NAMES as Ve,INFRASTRUCTURE_STEP_NAMES as Ye,INFRA_STEP_NAME as Be}from"./types/index.js";import{RemediationVerbSchema as Ke,REMEDIATION_VERB_GLOSS as Xe,DestructionFindingSchema as He,DestructionTicketResourceSchema as we,DestructionTicketSchema as Je,DestructionConsentSchema as Qe,DestructionOutcomeSchema as je,DESTRUCTION_FINDINGS as We,CONSENT_VERDICTS as qe,TICKET_VERDICT_SOURCES as Ze,TicketVerdictSourceSchema as ze}from"./types/index.js";import{DRIFT_VERDICTS as er,DriftVerdictSchema as rr,DriftSuspectSchema as tr,DriftFindingSchema as or,DriftJournalRecordSchema as ir,verbsForDriftVerdict as ar}from"./types/index.js";import{REMEDIATION_PHASES as sr,RemediationPhaseSchema as Er,RemediationTargetSchema as cr,RemediationFlipProofSchema as Sr,RemediationJournalRecordSchema as lr,RemediationVerbWithSurgerySchema as Tr,remediationPhaseRank as Ar,remediationPlaceholderPhysicalId as Rr,isRemediationPlaceholderPhysicalId as _r}from"./types/index.js";import{ProgressReporter as mr,APPLICATION_STACKS as ur,ORGANISATION_TYPES as dr,APPLICATION_DEPLOY_ORDER as Pr,APPLICATION_DESTROY_ORDER as Or,OPENNEXT_DEPLOY_ORDER as Dr,OPENNEXT_DESTROY_ORDER as fr,PARALLEL_DEPLOY_GROUPS as Cr,PARALLEL_DESTROY_GROUPS as Nr,OPENNEXT_PARALLEL_GROUPS as gr,PARALLEL_OPERATION_TYPES as Lr,isApplicationOperation as Ir,isOrganisationOperation as yr,getParallelDeployGroups as hr,getParallelDestroyGroups as Fr,getApplicationDeployOrder as Ur,getApplicationDestroyOrder as vr,getApplicationStackName as xr,getOrganisationStackName as Mr,isApplicationStack as kr,isQuarantineDetail as br,isRetainedBucketsDetail as Vr,getApplicationStepName as Yr,getApplicationStepId as Br,toPascalCase as Gr,isOpenNextPattern as Kr,OPENNEXT_PATTERNS as Xr,STACK_NOT_FOUND_PATTERN as Hr,STACK_FAILED_STATE_PATTERN as wr,CDK_NO_STACKS_MATCH as Jr,INFRASTRUCTURE_FILENAME as Qr,ApplicationError as jr,wrapApplicationError as Wr,stubCallerIdentity as qr}from"./types/index.js";import{deriveResourcesFromManifestStacks as zr}from"./types/detection/patternDetection.js";import{FjallStateFileSchema as et,readStateFile as rt,writeStateFile as tt,createEmptyState as ot,deleteStateFile as it,updateTemplateHash as at,getStateFilePath as nt,regionSuffix as st}from"./types/config/FjallState.js";import{CloudFormationEventMonitor as ct}from"./aws/index.js";import{CdkService as lt,CdkArgumentBuilder as Tt,CdkProcessManager as At,CdkEventMonitor as Rt,startStackMonitoring as _t,DEFAULT_DEPLOY_TIMEOUT_MS as pt,isCdkError as mt,formatInfrastructureError as ut,getStructuralHint as dt,getSourceContext as Pt,hasCdkDifferences as Ot,parseDiffOutput as Dt,CloudFormationService as ft,CloudFormationError as Ct,EcsService as Nt,EcsError as gt,EcsServiceResolver as Lt,TemplateHashService as It,TemplateHashError as yt,CdkContextBuilder as ht,emitProgress as Ft,PROGRESS_MESSAGES as Ut,parseBuildPhase as vt,buildStepContextBuildConfig as xt,convertCloudFormationOutputsToRecord as Mt,ApplicationStackService as kt}from"./services/index.js";import{CdkError as Vt}from"./types/errors/index.js";import{BaseServiceError as Bt,ValidationError as Gt,AuthError as Kt,AwsError as Xt,DeploymentError as Ht,NetworkError as wt,FileSystemError as Jt,ConfigError as Qt,toServiceError as jt}from"./types/errors/index.js";import{filterDangerousEnvVars as qt,maskSensitiveOutput as Zt,parseShellArgs as zt,sleep as $t}from"@fjall/util";import{artefactOutputKey as ro,DeployModeSchema as to,ServiceArtefactSchema as oo,ServiceArtefactsSchema as io}from"@fjall/util";import{hasDockerfile as no}from"./util/dockerfileDetection.js";import{sleepAbortable as Eo}from"./util/sleepAbortable.js";import{createSequencedCallbacks as So}from"./util/sequencedCallbacks.js";import{fileExists as To}from"@fjall/util/fsHelpers";import{success as Ro,failure as _o,isSuccess as po,isFailure as mo}from"@fjall/generator";import{deploy as Po}from"./orchestration/index.js";import{destroy as Do}from"./orchestration/index.js";import{restart as Co,probeSecretsDrift as No,computeSecretsDrift as go,deriveStaleParameters as Lo,extractConsumedSsmParameters as Io}from"./orchestration/index.js";import{partitionAccounts as ho}from"./orchestration/index.js";import{buildRegionList as Uo,buildAccountRegionPairs as vo,cascadeHomeRegion as xo,cascadeOperationKey as Mo}from"./orchestration/index.js";import{projectScalarSummary as bo,projectAccountRows as Vo}from"./orchestration/index.js";import{reconcileProviderAccounts as Bo,mergeReconciledProviderAccounts as Go}from"./orchestration/index.js";import{decideNextTransition as Xo,reconcileTrailMigration as Ho,decommissionMemberTrailStorage as wo,ORG_TRAIL_BUCKET_OUTPUT_KEY as Jo,TRAIL_BUCKET_OUTPUT_KEY as Qo,TRAIL_KEY_ARN_OUTPUT_KEY as jo}from"./orchestration/index.js";import{classifyDriftFailure as qo,fetchLastOperationEvents as Zo,DriftProbe as zo,clearDriftSuspects as $o,defaultDriftJournalDir as ei,readDriftSuspects as ri,recordDriftSuspects as ti,detectStackDrift as oi,runDriftPreFlight as ii,formatDriftPreFlightBlock as ai,DRIFT_PREFLIGHT_TRIGGER_STATUSES as ni,DRIFT_PREFLIGHT_BUDGET_MS as si,runRoute53RecordPreflight as Ei}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as Si,computeRemediationOpId as li,defaultRemediationJournalDir as Ti,findRemediationJournalByOpId as Ai,listActiveRemediationOps as Ri,listActiveRemediationOpsForContext as _i,readRemediationJournal as pi,sweepExpiredRemediationJournals as mi,writeRemediationJournal as ui,REMEDIATION_JOURNAL_RETENTION_DAYS as di,captureRemediationForensics as Pi,defaultRemediationForensicsDir as Oi,applyRetainFlip as Di,composeFlipCapabilities as fi,computeTemplateDigest as Ci,deriveRetainFlipTemplate as Ni,findMarkedResourcesByOpId as gi,proveFlipMetadataOnly as Li,readRetainFlipState as Ii,verifyRetainFlipDiff as yi,FORGET_MARKER_KEY as hi,FORGET_FLIP_SPEC as Fi,RECREATE_MARKER_KEY as Ui,assessForgetResumability as vi,completeForgetAfterConverge as xi,completeForgetAfterDeploy as Mi,formatRecreateInFlightCures as ki,partitionPreFlightByRemediation as bi,runForgetSurgery as Vi,synthTemplateDeclaresResource as Yi,runRecreateSurgery as Bi,snapshotPolicyForType as Gi,SNAPSHOT_CAPABLE_RESOURCE_TYPES as Ki,runRecreatePreFlight as Xi,deriveRemovalTemplate as Hi,findRemovalDeletionFailures as wi,findResourcesPresent as Ji,proveRemovalTargetsOnly as Qi,advertisableDriftVerbs as ji,buildDriftRepairTicket as Wi,runDriftRepairGate as qi,formatPinOutcomeDetail as Zi,pinProbeCoverage as zi,renderPinReportLines as $i,runPinRemediation as ea,composePostFailureRepairOffer as ra,formatDriftRepairOffer as ta,DriftRepairAvailableError as oa,checkDeployPathStackAvailability as ia,isDeployPathBlockingStatus as aa,StackUnavailableError as na,assertLeaseBeforeStack as sa,LeaseDeniedError as Ea}from"./orchestration/index.js";import{unlockBucket as Sa,unlockQueue as la}from"./orchestration/index.js";import{triageBucketPolicy as Aa,isEnforceSslStatement as Ra,toResourcePolicyStatements as _a,restoreBucketPolicy as pa,synthesiseEnforceSslDocument as ma,ensureEnforceSsl as ua,restoreAndReconcileQuarantinedBucket as da}from"./orchestration/index.js";import{verifyOrgTrailDelivery as Oa}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as fa,isRootTaskPolicyArn as Ca,ROOT_TASK_POLICY_ARNS as Na,MAX_ROOT_SESSION_SECONDS as ga}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as Ia,flattenAccountsToEnvironments as ya,extractAllAccountNames as ha,accountsConfigToOUTree as Fa,isStringArray as Ua,isAccountsConfig as va,isOuOnlyAccountBucket as xa,OU_ONLY_ACCOUNT_BUCKETS as Ma}from"./orchestration/index.js";import{runOpenNextBuild as ba}from"./orchestration/index.js";import{runOrganisationSetup as Ya,ORG_SETUP_PHASES as Ba}from"./orchestration/index.js";import{DOMAIN_DELEGATION_ERROR_TYPES as Ka,DomainDelegationError as Xa,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as Ha,PUBLIC_DNS_QUERY_TIMEOUT_MS as wa,createPublicResolvers as Ja,NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS as Qa,NS_PROPAGATION_DEFAULT_INTERVAL_MS as ja,waitForNsPropagation as Wa,ACM_CAA_ISSUERS as qa,runCaaPreflight as Za,deployDelegatedDomain as za,CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as $a,templateOwnsDelegationRecord as en,deleteChildNsFromParent as rn,nsDelegationPhysicalName as tn,runDelegatedDomainDestroy as on}from"./orchestration/index.js";import{resolveBuildSecrets as nn,resolveSecretRefValue as sn,resolveBuildSecretSessionProvider as En,sourcedRefsFromBuildArgs as cn,resolveBuildArgs as Sn,buildBuildSecretSessionPolicy as ln,buildDeploySessionPolicy as Tn,partitionForRegion as An,validateBuildGroup as Rn}from"./orchestration/index.js";import{FrameworkRegistry as pn}from"./orchestration/index.js";import{openNextBuilder as un,staticSiteBuilder as dn,dockerBuilder as Pn}from"./orchestration/index.js";import{StepRegistry as Dn,getDestroyStepId as fn}from"./steps/index.js";import{buildDeployPlan as Nn,computeDeployPlan as gn,computeAssemblyDigest as Ln,digestHead as In,classifyImpact as yn,derivePropertyChanges as hn,isDataLoss as Fn,isStatefulResourceType as Un,renderPlanSummary as vn,renderPlanLines as xn,toWirePlanChanges as Mn,signApprovalToken as kn,verifyApprovalToken as bn,DEFAULT_APPROVAL_TTL_MS as Vn,APPROVAL_TOKEN_PATTERN as Yn,runApprovalGate as Bn}from"./orchestration/index.js";import{runDestructionGate as Kn,buildDestructionTicket as Xn,evaluateDestructionConsents as Hn,computeTicketDigest as wn,legalRemediationVerbs as Jn,executableRemediationVerbs as Qn,advertisableRemediationVerbs as jn,renderDestructionTicketLines as Wn,renderConsentVerdictLines as qn,loadDeployPlan as Zn,createMemoisedPlanLoader as zn}from"./orchestration/index.js";export{qa as ACM_CAA_ISSUERS,X as ALL_PROGRESS_KINDS,Pr as APPLICATION_DEPLOY_ORDER,Or as APPLICATION_DESTROY_ORDER,ur as APPLICATION_STACKS,K as APPROVAL_DECISIONS,G as APPROVAL_KINDS,Yn as APPROVAL_TOKEN_PATTERN,jr as ApplicationError,kt as ApplicationStackService,Kt as AuthError,Xt as AwsError,b as BUILDERS,Bt as BaseServiceError,v as CASCADE_ACCOUNT_PHASES,c as CASCADE_ACCOUNT_STATUSES,V as CASCADE_OUTCOME_RESULTS,E as CASCADE_PHASES,Jr as CDK_NO_STACKS_MATCH,qe as CONSENT_VERDICTS,$a as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,Tt as CdkArgumentBuilder,ht as CdkContextBuilder,Vt as CdkError,Rt as CdkEventMonitor,At as CdkProcessManager,lt as CdkService,p as ChangeCountsSchema,Ct as CloudFormationError,ct as CloudFormationEventMonitor,ft as CloudFormationService,Qt as ConfigError,Vn as DEFAULT_APPROVAL_TTL_MS,pt as DEFAULT_DEPLOY_TIMEOUT_MS,Le as DEFAULT_MAX_PAGES,Ha as DEFAULT_PUBLIC_RESOLVER_ADDRESSES,n as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,i as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,a as DEPLOYMENT_EVENT_STATUS_REASON_MAX,s as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,o as DEPLOYMENT_EVENT_TYPES,I as DEPLOY_EVENT_ARN_MAX,m as DEPLOY_EVENT_CONTRACT,u as DEPLOY_EVENT_CONTRACT_MAJOR,d as DEPLOY_EVENT_CONTRACT_MINOR,N as DEPLOY_EVENT_ERROR_MESSAGE_MAX,O as DEPLOY_EVENT_ID_MAX,f as DEPLOY_EVENT_MESSAGE_MAX,D as DEPLOY_EVENT_NAME_MAX,L as DEPLOY_EVENT_OUTPUT_MAX,C as DEPLOY_EVENT_STATUS_REASON_MAX,g as DEPLOY_EVENT_TRAIL_DETAIL_MAX,y as DEPLOY_EVENT_URL_MAX,x as DEPLOY_RESULTS,We as DESTRUCTION_FINDINGS,M as DETECTION_PHASES,Ka as DOMAIN_DELEGATION_ERROR_TYPES,si as DRIFT_PREFLIGHT_BUDGET_MS,ni as DRIFT_PREFLIGHT_TRIGGER_STATUSES,er as DRIFT_VERDICTS,l as DeployEventSchema,to as DeployModeSchema,A as DeployResourceSchema,Ht as DeploymentError,t as DeploymentEventSchema,Qe as DestructionConsentSchema,He as DestructionFindingSchema,je as DestructionOutcomeSchema,we as DestructionTicketResourceSchema,Je as DestructionTicketSchema,Xa as DomainDelegationError,or as DriftFindingSchema,ir as DriftJournalRecordSchema,zo as DriftProbe,oa as DriftRepairAvailableError,tr as DriftSuspectSchema,rr as DriftVerdictSchema,gt as EcsError,Nt as EcsService,Lt as EcsServiceResolver,Fi as FORGET_FLIP_SPEC,hi as FORGET_MARKER_KEY,Jt as FileSystemError,et as FjallStateFileSchema,pn as FrameworkRegistry,Ie as IDENTITY_STORE_PAGE_SIZE,Qr as INFRASTRUCTURE_FILENAME,Ye as INFRASTRUCTURE_STEP_NAMES,Be as INFRA_STEP_NAME,F as LOG_LEVELS,Ea as LeaseDeniedError,ga as MAX_ROOT_SESSION_SECONDS,ja as NS_PROPAGATION_DEFAULT_INTERVAL_MS,Qa as NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS,wt as NetworkError,Dr as OPENNEXT_DEPLOY_ORDER,fr as OPENNEXT_DESTROY_ORDER,gr as OPENNEXT_PARALLEL_GROUPS,Xr as OPENNEXT_PATTERNS,dr as ORGANISATION_TYPES,Ba as ORG_SETUP_PHASES,Jo as ORG_TRAIL_BUCKET_OUTPUT_KEY,Ma as OU_ONLY_ACCOUNT_BUCKETS,Cr as PARALLEL_DEPLOY_GROUPS,Nr as PARALLEL_DESTROY_GROUPS,Lr as PARALLEL_OPERATION_TYPES,k as PHASE_STATUSES,Y as PLAN_ACTIONS,Ut as PROGRESS_MESSAGES,wa as PUBLIC_DNS_QUERY_TIMEOUT_MS,R as PlanChangeSchema,_ as PlanPropertyChangeSchema,mr as ProgressReporter,Ui as RECREATE_MARKER_KEY,di as REMEDIATION_JOURNAL_RETENTION_DAYS,sr as REMEDIATION_PHASES,Xe as REMEDIATION_VERB_GLOSS,B as REPLACEMENT_MODES,xe as ROOT_ACCESS_FEATURES,Na as ROOT_TASK_POLICY_ARNS,Sr as RemediationFlipProofSchema,lr as RemediationJournalRecordSchema,Er as RemediationPhaseSchema,cr as RemediationTargetSchema,Ke as RemediationVerbSchema,Tr as RemediationVerbWithSurgerySchema,Me as RootAccessEnablementError,Ue as SECURITY_SERVICE_PRINCIPALS,ce as SERVICE_PRINCIPALS,Ki as SNAPSHOT_CAPABLE_RESOURCE_TYPES,U as STACK_CLEANUP_PHASES,wr as STACK_FAILED_STATE_PATTERN,Hr as STACK_NOT_FOUND_PATTERN,h as STEP_COMPLETE_STATUSES,be as STEP_IDS,Ve as STEP_NAMES,P as SUPPORTED_CONTRACT_MARKERS,oo as ServiceArtefactSchema,io as ServiceArtefactsSchema,j as SimpleAwsProvider,na as StackUnavailableError,T as StepProgressSchema,Dn as StepRegistry,Ze as TICKET_VERDICT_SOURCES,Qo as TRAIL_BUCKET_OUTPUT_KEY,jo as TRAIL_KEY_ARN_OUTPUT_KEY,yt as TemplateHashError,It as TemplateHashService,ze as TicketVerdictSourceSchema,Gt as ValidationError,Fa as accountsConfigToOUTree,Oe as activateCostAllocationTags,le as activateTrustedAccess,ji as advertisableDriftVerbs,jn as advertisableRemediationVerbs,Di as applyRetainFlip,Si as archiveCompletedRemediationJournal,ro as artefactOutputKey,sa as assertLeaseBeforeStack,vi as assessForgetResumability,fa as assumeRootForTask,vo as buildAccountRegionPairs,de as buildAccountToOUMap,ln as buildBuildSecretSessionPolicy,Nn as buildDeployPlan,Tn as buildDeploySessionPolicy,Xn as buildDestructionTicket,Wi as buildDriftRepairTicket,Uo as buildRegionList,xt as buildStepContextBuildConfig,$ as buildTargetSetUnreadyAdvisory,z as buildTargetUnreadyAdvisory,Pi as captureRemediationForensics,xo as cascadeHomeRegion,Mo as cascadeOperationKey,ia as checkDeployPathStackAvailability,De as checkIdentityCentreStatus,te as checkRegionEnabled,q as checkTargetReadiness,qo as classifyDriftFailure,yn as classifyImpact,$o as clearDriftSuspects,xi as completeForgetAfterConverge,Mi as completeForgetAfterDeploy,fi as composeFlipCapabilities,ra as composePostFailureRepairOffer,Ce as composeSdkAbortSignal,Ln as computeAssemblyDigest,gn as computeDeployPlan,li as computeRemediationOpId,go as computeSecretsDrift,Ci as computeTemplateDigest,wn as computeTicketDigest,Mt as convertCloudFormationOutputsToRecord,pe as createAccount,H as createDeployEmitter,ot as createEmptyState,zn as createMemoisedPlanLoader,Ja as createPublicResolvers,So as createSequencedCallbacks,Xo as decideNextTransition,wo as decommissionMemberTrailStorage,ei as defaultDriftJournalDir,Oi as defaultRemediationForensicsDir,Ti as defaultRemediationJournalDir,rn as deleteChildNsFromParent,it as deleteStateFile,Po as deploy,za as deployDelegatedDomain,hn as derivePropertyChanges,Hi as deriveRemovalTemplate,zr as deriveResourcesFromManifestStacks,Ni as deriveRetainFlipTemplate,Lo as deriveStaleParameters,ne as describeOrganisation,Z as describeTargetReadinessReason,Do as destroy,oi as detectStackDrift,In as digestHead,Pn as dockerBuilder,ye as drainPages,Ft as emitProgress,ve as enableCentralisedRootAccess,Te as enableIpamDelegatedAdmin,se as enablePolicyTypes,Se as enableRamSharing,Ee as enableServiceAccess,ua as ensureEnforceSsl,ae as ensureOrganisationExists,me as ensureOrganisationalUnitsExist,Hn as evaluateDestructionConsents,Qn as executableRemediationVerbs,ha as extractAllAccountNames,Io as extractConsumedSsmParameters,Ne as extractErrorName,_o as failure,Zo as fetchLastOperationEvents,To as fileExists,qt as filterDangerousEnvVars,_e as findAccount,Pe as findDevelopmentOuId,gi as findMarkedResourcesByOpId,Ai as findRemediationJournalByOpId,wi as findRemovalDeletionFailures,Ji as findResourcesPresent,ya as flattenAccountsToEnvironments,ai as formatDriftPreFlightBlock,ta as formatDriftRepairOffer,ut as formatInfrastructureError,Zi as formatPinOutcomeDetail,ki as formatRecreateInFlightCures,Ur as getApplicationDeployOrder,vr as getApplicationDestroyOrder,xr as getApplicationStackName,Br as getApplicationStepId,Yr as getApplicationStepName,fn as getDestroyStepId,Mr as getOrganisationStackName,hr as getParallelDeployGroups,Fr as getParallelDestroyGroups,Pt as getSourceContext,nt as getStateFilePath,dt as getStructuralHint,Ot as hasCdkDifferences,no as hasDockerfile,ge as isAborted,va as isAccountsConfig,Ir as isApplicationOperation,kr as isApplicationStack,mt as isCdkError,Fn as isDataLoss,aa as isDeployPathBlockingStatus,Ra as isEnforceSslStatement,mo as isFailure,he as isOULeaf,Kr as isOpenNextPattern,yr as isOrganisationOperation,xa as isOuOnlyAccountBucket,br as isQuarantineDetail,_r as isRemediationPlaceholderPhysicalId,Vr as isRetainedBucketsDetail,Ca as isRootTaskPolicyArn,Un as isStatefulResourceType,Ua as isStringArray,po as isSuccess,Jn as legalRemediationVerbs,Re as listAccounts,Ri as listActiveRemediationOps,_i as listActiveRemediationOpsForContext,Zn as loadDeployPlan,Zt as maskSensitiveOutput,Go as mergeReconciledProviderAccounts,tn as nsDelegationPhysicalName,un as openNextBuilder,Ia as parseAccountsConfiguration,vt as parseBuildPhase,J as parseDeployContractVersion,w as parseDeployEvent,Dt as parseDiffOutput,zt as parseShellArgs,ho as partitionAccounts,An as partitionForRegion,bi as partitionPreFlightByRemediation,zi as pinProbeCoverage,ue as placeAccountsInOUs,ee as probeAccountStackExists,No as probeSecretsDrift,Vo as projectAccountRows,bo as projectScalarSummary,Li as proveFlipMetadataOnly,Qi as proveRemovalTargetsOnly,ri as readDriftSuspects,pi as readRemediationJournal,Ii as readRetainFlipState,rt as readStateFile,Bo as reconcileProviderAccounts,Ho as reconcileTrailMigration,ti as recordDriftSuspects,oe as regionDisabledMessage,st as regionSuffix,Fe as registerSecurityDelegates,Ar as remediationPhaseRank,Rr as remediationPlaceholderPhysicalId,qn as renderConsentVerdictLines,Wn as renderDestructionTicketLines,$i as renderPinReportLines,xn as renderPlanLines,vn as renderPlanSummary,Sn as resolveBuildArgs,En as resolveBuildSecretSessionProvider,nn as resolveBuildSecrets,sn as resolveSecretRefValue,Co as restart,da as restoreAndReconcileQuarantinedBucket,pa as restoreBucketPolicy,Bn as runApprovalGate,Za as runCaaPreflight,on as runDelegatedDomainDestroy,Kn as runDestructionGate,ii as runDriftPreFlight,qi as runDriftRepairGate,Vi as runForgetSurgery,ba as runOpenNextBuild,Ya as runOrganisationSetup,ea as runPinRemediation,Xi as runRecreatePreFlight,Bi as runRecreateSurgery,Ei as runRoute53RecordPreflight,kn as signApprovalToken,$t as sleep,Eo as sleepAbortable,fe as snapshotIdentityCentre,Gi as snapshotPolicyForType,cn as sourcedRefsFromBuildArgs,_t as startStackMonitoring,dn as staticSiteBuilder,qr as stubCallerIdentity,Ro as success,mi as sweepExpiredRemediationJournals,Yi as synthTemplateDeclaresResource,ma as synthesiseEnforceSslDocument,en as templateOwnsDelegationRecord,Gr as toPascalCase,_a as toResourcePolicyStatements,jt as toServiceError,Mn as toWirePlanChanges,Aa as triageBucketPolicy,Sa as unlockBucket,la as unlockQueue,Ae as updateBackupGlobalSettings,at as updateTemplateHash,Rn as validateBuildGroup,ar as verbsForDriftVerdict,bn as verifyApprovalToken,Oa as verifyOrgTrailDelivery,yi as verifyRetainFlipDiff,Wa as waitForNsPropagation,Wr as wrapApplicationError,ui as writeRemediationJournal,tt as writeStateFile};
|
|
1
|
+
import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as o,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as i,DEPLOYMENT_EVENT_STATUS_REASON_MAX as a,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as s,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as n,CASCADE_PHASES as E,CASCADE_ACCOUNT_STATUSES as c}from"./types/index.js";import{DeployEventSchema as l,StepProgressSchema as A,DeployResourceSchema as T,PlanChangeSchema as R,PlanPropertyChangeSchema as _,ChangeCountsSchema as p,DEPLOY_EVENT_CONTRACT as m,DEPLOY_EVENT_CONTRACT_MAJOR as d,DEPLOY_EVENT_CONTRACT_MINOR as u,SUPPORTED_CONTRACT_MARKERS as D,DEPLOY_EVENT_ID_MAX as P,DEPLOY_EVENT_NAME_MAX as O,DEPLOY_EVENT_MESSAGE_MAX as f,DEPLOY_EVENT_STATUS_REASON_MAX as C,DEPLOY_EVENT_ERROR_MESSAGE_MAX as N,DEPLOY_EVENT_TRAIL_DETAIL_MAX as g,DEPLOY_EVENT_OUTPUT_MAX as L,DEPLOY_EVENT_ARN_MAX as I,DEPLOY_EVENT_URL_MAX as y,STEP_COMPLETE_STATUSES as h,LOG_LEVELS as x,STACK_CLEANUP_PHASES as v,CASCADE_ACCOUNT_PHASES as F,DEPLOY_RESULTS as M,DETECTION_PHASES as U,PHASE_STATUSES as k,BUILDERS as b,CASCADE_OUTCOME_RESULTS as V,PLAN_ACTIONS as Y,REPLACEMENT_MODES as B,APPROVAL_KINDS as G,APPROVAL_DECISIONS as K,ALL_PROGRESS_KINDS as X,createDeployEmitter as H,parseDeployEvent as w,parseDeployContractVersion as J}from"./types/index.js";import{SimpleAwsProvider as j}from"./aws/index.js";import{checkTargetReadiness as Z,describeTargetReadinessReason as q,buildTargetUnreadyAdvisory as z,buildTargetSetUnreadyAdvisory as $,probeAccountStackExists as ee}from"./aws/index.js";import{checkRegionEnabled as te,regionDisabledMessage as oe}from"./aws/index.js";import{ensureOrganisationExists as ae,describeOrganisation as se,enablePolicyTypes as ne,enableServiceAccess as Ee,SERVICE_PRINCIPALS as ce,enableRamSharing as Se,activateTrustedAccess as le,enableIpamDelegatedAdmin as Ae,updateBackupGlobalSettings as Te,listAccounts as Re,findAccount as _e,createAccount as pe,ensureOrganisationalUnitsExist as me,placeAccountsInOUs as de,buildAccountToOUMap as ue,findDevelopmentOuId as De,activateCostAllocationTags as Pe,checkIdentityCentreStatus as Oe,snapshotIdentityCentre as fe,composeSdkAbortSignal as Ce,extractErrorName as Ne,isAborted as ge,DEFAULT_MAX_PAGES as Le,IDENTITY_STORE_PAGE_SIZE as Ie,drainPages as ye,isOULeaf as he,registerSecurityDelegates as xe,SECURITY_SERVICE_PRINCIPALS as ve,enableCentralisedRootAccess as Fe,ROOT_ACCESS_FEATURES as Me,RootAccessEnablementError as Ue}from"./aws/index.js";import{STEP_IDS as be,STEP_NAMES as Ve,INFRASTRUCTURE_STEP_NAMES as Ye,INFRA_STEP_NAME as Be}from"./types/index.js";import{RemediationVerbSchema as Ke,REMEDIATION_VERB_GLOSS as Xe,DestructionFindingSchema as He,DestructionTicketResourceSchema as we,DestructionTicketSchema as Je,DestructionConsentSchema as Qe,DestructionOutcomeSchema as je,DESTRUCTION_FINDINGS as We,CONSENT_VERDICTS as Ze,TICKET_VERDICT_SOURCES as qe,TicketVerdictSourceSchema as ze}from"./types/index.js";import{DRIFT_VERDICTS as er,DriftVerdictSchema as rr,DriftSuspectSchema as tr,DriftFindingSchema as or,DriftJournalRecordSchema as ir,verbsForDriftVerdict as ar}from"./types/index.js";import{REMEDIATION_PHASES as nr,RemediationPhaseSchema as Er,RemediationTargetSchema as cr,RemediationFlipProofSchema as Sr,RemediationJournalRecordSchema as lr,RemediationVerbWithSurgerySchema as Ar,remediationPhaseRank as Tr,remediationPlaceholderPhysicalId as Rr,isRemediationPlaceholderPhysicalId as _r}from"./types/index.js";import{ProgressReporter as mr,APPLICATION_STACKS as dr,ORGANISATION_TYPES as ur,APPLICATION_DEPLOY_ORDER as Dr,APPLICATION_DESTROY_ORDER as Pr,OPENNEXT_DEPLOY_ORDER as Or,OPENNEXT_DESTROY_ORDER as fr,PARALLEL_DEPLOY_GROUPS as Cr,PARALLEL_DESTROY_GROUPS as Nr,OPENNEXT_PARALLEL_GROUPS as gr,PARALLEL_OPERATION_TYPES as Lr,isApplicationOperation as Ir,isOrganisationOperation as yr,getParallelDeployGroups as hr,getParallelDestroyGroups as xr,getApplicationDeployOrder as vr,getApplicationDestroyOrder as Fr,getApplicationStackName as Mr,getOrganisationStackName as Ur,isApplicationStack as kr,isQuarantineDetail as br,isRetainedBucketsDetail as Vr,getApplicationStepName as Yr,getApplicationStepId as Br,toPascalCase as Gr,isOpenNextPattern as Kr,OPENNEXT_PATTERNS as Xr,STACK_NOT_FOUND_PATTERN as Hr,STACK_FAILED_STATE_PATTERN as wr,CDK_NO_STACKS_MATCH as Jr,INFRASTRUCTURE_FILENAME as Qr,ApplicationError as jr,wrapApplicationError as Wr,stubCallerIdentity as Zr}from"./types/index.js";import{deriveResourcesFromManifestStacks as zr}from"./types/detection/patternDetection.js";import{FjallStateFileSchema as et,readStateFile as rt,writeStateFile as tt,createEmptyState as ot,deleteStateFile as it,updateTemplateHash as at,getStateFilePath as st,regionSuffix as nt}from"./types/config/FjallState.js";import{readDomainState as ct,writeDomainState as St,recordDomainDeployState as lt,deleteDomainState as At,hashDomainDirectory as Tt,LEGACY_DOMAIN_STATE_FILENAME as Rt}from"./types/config/DomainState.js";import{CloudFormationEventMonitor as pt}from"./aws/index.js";import{CdkService as dt,CdkArgumentBuilder as ut,CdkProcessManager as Dt,CdkEventMonitor as Pt,startStackMonitoring as Ot,DEFAULT_DEPLOY_TIMEOUT_MS as ft,isCdkError as Ct,formatInfrastructureError as Nt,getStructuralHint as gt,getSourceContext as Lt,hasCdkDifferences as It,parseDiffOutput as yt,CloudFormationService as ht,CloudFormationError as xt,EcsService as vt,EcsError as Ft,EcsServiceResolver as Mt,TemplateHashService as Ut,TemplateHashError as kt,CdkContextBuilder as bt,emitProgress as Vt,PROGRESS_MESSAGES as Yt,parseBuildPhase as Bt,buildStepContextBuildConfig as Gt,convertCloudFormationOutputsToRecord as Kt,ApplicationStackService as Xt}from"./services/index.js";import{CdkError as wt}from"./types/errors/index.js";import{BaseServiceError as Qt,ValidationError as jt,AuthError as Wt,AwsError as Zt,DeploymentError as qt,NetworkError as zt,FileSystemError as $t,ConfigError as eo,toServiceError as ro}from"./types/errors/index.js";import{filterDangerousEnvVars as oo,maskSensitiveOutput as io,parseShellArgs as ao,sleep as so}from"@fjall/util";import{artefactOutputKey as Eo,DeployModeSchema as co,ServiceArtefactSchema as So,ServiceArtefactsSchema as lo}from"@fjall/util";import{hasDockerfile as To}from"./util/dockerfileDetection.js";import{sleepAbortable as _o}from"./util/sleepAbortable.js";import{createSequencedCallbacks as mo}from"./util/sequencedCallbacks.js";import{fileExists as Do}from"@fjall/util/fsHelpers";import{success as Oo,failure as fo,isSuccess as Co,isFailure as No}from"@fjall/generator";import{deploy as Lo}from"./orchestration/index.js";import{destroy as yo}from"./orchestration/index.js";import{restart as xo,probeSecretsDrift as vo,computeSecretsDrift as Fo,deriveStaleParameters as Mo,extractConsumedSsmParameters as Uo}from"./orchestration/index.js";import{partitionAccounts as bo}from"./orchestration/index.js";import{buildRegionList as Yo,buildAccountRegionPairs as Bo,cascadeHomeRegion as Go,cascadeOperationKey as Ko}from"./orchestration/index.js";import{projectScalarSummary as Ho,projectAccountRows as wo}from"./orchestration/index.js";import{reconcileProviderAccounts as Qo,mergeReconciledProviderAccounts as jo}from"./orchestration/index.js";import{decideNextTransition as Zo,reconcileTrailMigration as qo,decommissionMemberTrailStorage as zo,ORG_TRAIL_BUCKET_OUTPUT_KEY as $o,TRAIL_BUCKET_OUTPUT_KEY as ei,TRAIL_KEY_ARN_OUTPUT_KEY as ri}from"./orchestration/index.js";import{classifyDriftFailure as oi,fetchLastOperationEvents as ii,DriftProbe as ai,clearDriftSuspects as si,defaultDriftJournalDir as ni,readDriftSuspects as Ei,recordDriftSuspects as ci,detectStackDrift as Si,runDriftPreFlight as li,formatDriftPreFlightBlock as Ai,DRIFT_PREFLIGHT_TRIGGER_STATUSES as Ti,DRIFT_PREFLIGHT_BUDGET_MS as Ri,runRoute53RecordPreflight as _i}from"./orchestration/index.js";import{archiveCompletedRemediationJournal as mi,computeRemediationOpId as di,defaultRemediationJournalDir as ui,findRemediationJournalByOpId as Di,listActiveRemediationOps as Pi,listActiveRemediationOpsForContext as Oi,readRemediationJournal as fi,sweepExpiredRemediationJournals as Ci,writeRemediationJournal as Ni,REMEDIATION_JOURNAL_RETENTION_DAYS as gi,captureRemediationForensics as Li,defaultRemediationForensicsDir as Ii,applyRetainFlip as yi,composeFlipCapabilities as hi,computeTemplateDigest as xi,deriveRetainFlipTemplate as vi,findMarkedResourcesByOpId as Fi,proveFlipMetadataOnly as Mi,readRetainFlipState as Ui,verifyRetainFlipDiff as ki,FORGET_MARKER_KEY as bi,FORGET_FLIP_SPEC as Vi,RECREATE_MARKER_KEY as Yi,assessForgetResumability as Bi,completeForgetAfterConverge as Gi,completeForgetAfterDeploy as Ki,formatRecreateInFlightCures as Xi,partitionPreFlightByRemediation as Hi,runForgetSurgery as wi,synthTemplateDeclaresResource as Ji,runRecreateSurgery as Qi,snapshotPolicyForType as ji,SNAPSHOT_CAPABLE_RESOURCE_TYPES as Wi,runRecreatePreFlight as Zi,deriveRemovalTemplate as qi,findRemovalDeletionFailures as zi,findResourcesPresent as $i,proveRemovalTargetsOnly as ea,advertisableDriftVerbs as ra,buildDriftRepairTicket as ta,runDriftRepairGate as oa,formatPinOutcomeDetail as ia,pinProbeCoverage as aa,renderPinReportLines as sa,runPinRemediation as na,composePostFailureRepairOffer as Ea,formatDriftRepairOffer as ca,DriftRepairAvailableError as Sa,checkDeployPathStackAvailability as la,isDeployPathBlockingStatus as Aa,StackUnavailableError as Ta,assertLeaseBeforeStack as Ra,LeaseDeniedError as _a}from"./orchestration/index.js";import{unlockBucket as ma,unlockQueue as da}from"./orchestration/index.js";import{triageBucketPolicy as Da,isEnforceSslStatement as Pa,toResourcePolicyStatements as Oa,restoreBucketPolicy as fa,synthesiseEnforceSslDocument as Ca,ensureEnforceSsl as Na,restoreAndReconcileQuarantinedBucket as ga}from"./orchestration/index.js";import{verifyOrgTrailDelivery as Ia}from"./aws/cloudtrail/orgTrailDelivery.js";import{assumeRootForTask as ha,isRootTaskPolicyArn as xa,ROOT_TASK_POLICY_ARNS as va,MAX_ROOT_SESSION_SECONDS as Fa}from"./aws/sts/assumeRoot.js";import{parseAccountsConfiguration as Ua,flattenAccountsToEnvironments as ka,extractAllAccountNames as ba,accountsConfigToOUTree as Va,isStringArray as Ya,isAccountsConfig as Ba,isOuOnlyAccountBucket as Ga,OU_ONLY_ACCOUNT_BUCKETS as Ka}from"./orchestration/index.js";import{runOpenNextBuild as Ha}from"./orchestration/index.js";import{runOrganisationSetup as Ja,ORG_SETUP_PHASES as Qa}from"./orchestration/index.js";import{DOMAIN_DELEGATION_ERROR_TYPES as Wa,DomainDelegationError as Za,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as qa,PUBLIC_DNS_QUERY_TIMEOUT_MS as za,createPublicResolvers as $a,NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS as es,NS_PROPAGATION_DEFAULT_INTERVAL_MS as rs,waitForNsPropagation as ts,ACM_CAA_ISSUERS as os,runCaaPreflight as is,deployDelegatedDomain as as,CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as ss,templateOwnsDelegationRecord as ns,deleteChildNsFromParent as Es,nsDelegationPhysicalName as cs,runDelegatedDomainDestroy as Ss}from"./orchestration/index.js";import{classifyZoneRecords as As,buildSatelliteRecordIndex as Ts,createSystemDnsNameProbe as Rs,systemDnsNameProbe as _s,normaliseRecordName as ps,isRoute53NameServer as ms,isDelegatedToRoute53 as ds}from"./orchestration/index.js";import{resolveBuildSecrets as Ds,resolveSecretRefValue as Ps,resolveBuildSecretSessionProvider as Os,sourcedRefsFromBuildArgs as fs,resolveBuildArgs as Cs,buildBuildSecretSessionPolicy as Ns,buildDeploySessionPolicy as gs,partitionForRegion as Ls,validateBuildGroup as Is}from"./orchestration/index.js";import{FrameworkRegistry as hs}from"./orchestration/index.js";import{openNextBuilder as vs,staticSiteBuilder as Fs,dockerBuilder as Ms}from"./orchestration/index.js";import{StepRegistry as ks,getDestroyStepId as bs}from"./steps/index.js";import{buildDeployPlan as Ys,computeDeployPlan as Bs,computeAssemblyDigest as Gs,digestHead as Ks,classifyImpact as Xs,derivePropertyChanges as Hs,isDataLoss as ws,isStatefulResourceType as Js,renderPlanSummary as Qs,renderPlanLines as js,toWirePlanChanges as Ws,signApprovalToken as Zs,verifyApprovalToken as qs,DEFAULT_APPROVAL_TTL_MS as zs,APPROVAL_TOKEN_PATTERN as $s,runApprovalGate as en,approvalRefusalReason as rn}from"./orchestration/index.js";import{runDestructionGate as on,buildDestructionTicket as an,evaluateDestructionConsents as sn,computeTicketDigest as nn,legalRemediationVerbs as En,executableRemediationVerbs as cn,advertisableRemediationVerbs as Sn,renderDestructionTicketLines as ln,renderConsentVerdictLines as An,loadDeployPlan as Tn,createMemoisedPlanLoader as Rn}from"./orchestration/index.js";export{os as ACM_CAA_ISSUERS,X as ALL_PROGRESS_KINDS,Dr as APPLICATION_DEPLOY_ORDER,Pr as APPLICATION_DESTROY_ORDER,dr as APPLICATION_STACKS,K as APPROVAL_DECISIONS,G as APPROVAL_KINDS,$s as APPROVAL_TOKEN_PATTERN,jr as ApplicationError,Xt as ApplicationStackService,Wt as AuthError,Zt as AwsError,b as BUILDERS,Qt as BaseServiceError,F as CASCADE_ACCOUNT_PHASES,c as CASCADE_ACCOUNT_STATUSES,V as CASCADE_OUTCOME_RESULTS,E as CASCADE_PHASES,Jr as CDK_NO_STACKS_MATCH,Ze as CONSENT_VERDICTS,ss as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,ut as CdkArgumentBuilder,bt as CdkContextBuilder,wt as CdkError,Pt as CdkEventMonitor,Dt as CdkProcessManager,dt as CdkService,p as ChangeCountsSchema,xt as CloudFormationError,pt as CloudFormationEventMonitor,ht as CloudFormationService,eo as ConfigError,zs as DEFAULT_APPROVAL_TTL_MS,ft as DEFAULT_DEPLOY_TIMEOUT_MS,Le as DEFAULT_MAX_PAGES,qa as DEFAULT_PUBLIC_RESOLVER_ADDRESSES,s as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,i as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,a as DEPLOYMENT_EVENT_STATUS_REASON_MAX,n as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,o as DEPLOYMENT_EVENT_TYPES,I as DEPLOY_EVENT_ARN_MAX,m as DEPLOY_EVENT_CONTRACT,d as DEPLOY_EVENT_CONTRACT_MAJOR,u as DEPLOY_EVENT_CONTRACT_MINOR,N as DEPLOY_EVENT_ERROR_MESSAGE_MAX,P as DEPLOY_EVENT_ID_MAX,f as DEPLOY_EVENT_MESSAGE_MAX,O as DEPLOY_EVENT_NAME_MAX,L as DEPLOY_EVENT_OUTPUT_MAX,C as DEPLOY_EVENT_STATUS_REASON_MAX,g as DEPLOY_EVENT_TRAIL_DETAIL_MAX,y as DEPLOY_EVENT_URL_MAX,M as DEPLOY_RESULTS,We as DESTRUCTION_FINDINGS,U as DETECTION_PHASES,Wa as DOMAIN_DELEGATION_ERROR_TYPES,Ri as DRIFT_PREFLIGHT_BUDGET_MS,Ti as DRIFT_PREFLIGHT_TRIGGER_STATUSES,er as DRIFT_VERDICTS,l as DeployEventSchema,co as DeployModeSchema,T as DeployResourceSchema,qt as DeploymentError,t as DeploymentEventSchema,Qe as DestructionConsentSchema,He as DestructionFindingSchema,je as DestructionOutcomeSchema,we as DestructionTicketResourceSchema,Je as DestructionTicketSchema,Za as DomainDelegationError,or as DriftFindingSchema,ir as DriftJournalRecordSchema,ai as DriftProbe,Sa as DriftRepairAvailableError,tr as DriftSuspectSchema,rr as DriftVerdictSchema,Ft as EcsError,vt as EcsService,Mt as EcsServiceResolver,Vi as FORGET_FLIP_SPEC,bi as FORGET_MARKER_KEY,$t as FileSystemError,et as FjallStateFileSchema,hs as FrameworkRegistry,Ie as IDENTITY_STORE_PAGE_SIZE,Qr as INFRASTRUCTURE_FILENAME,Ye as INFRASTRUCTURE_STEP_NAMES,Be as INFRA_STEP_NAME,Rt as LEGACY_DOMAIN_STATE_FILENAME,x as LOG_LEVELS,_a as LeaseDeniedError,Fa as MAX_ROOT_SESSION_SECONDS,rs as NS_PROPAGATION_DEFAULT_INTERVAL_MS,es as NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS,zt as NetworkError,Or as OPENNEXT_DEPLOY_ORDER,fr as OPENNEXT_DESTROY_ORDER,gr as OPENNEXT_PARALLEL_GROUPS,Xr as OPENNEXT_PATTERNS,ur as ORGANISATION_TYPES,Qa as ORG_SETUP_PHASES,$o as ORG_TRAIL_BUCKET_OUTPUT_KEY,Ka as OU_ONLY_ACCOUNT_BUCKETS,Cr as PARALLEL_DEPLOY_GROUPS,Nr as PARALLEL_DESTROY_GROUPS,Lr as PARALLEL_OPERATION_TYPES,k as PHASE_STATUSES,Y as PLAN_ACTIONS,Yt as PROGRESS_MESSAGES,za as PUBLIC_DNS_QUERY_TIMEOUT_MS,R as PlanChangeSchema,_ as PlanPropertyChangeSchema,mr as ProgressReporter,Yi as RECREATE_MARKER_KEY,gi as REMEDIATION_JOURNAL_RETENTION_DAYS,nr as REMEDIATION_PHASES,Xe as REMEDIATION_VERB_GLOSS,B as REPLACEMENT_MODES,Me as ROOT_ACCESS_FEATURES,va as ROOT_TASK_POLICY_ARNS,Sr as RemediationFlipProofSchema,lr as RemediationJournalRecordSchema,Er as RemediationPhaseSchema,cr as RemediationTargetSchema,Ke as RemediationVerbSchema,Ar as RemediationVerbWithSurgerySchema,Ue as RootAccessEnablementError,ve as SECURITY_SERVICE_PRINCIPALS,ce as SERVICE_PRINCIPALS,Wi as SNAPSHOT_CAPABLE_RESOURCE_TYPES,v as STACK_CLEANUP_PHASES,wr as STACK_FAILED_STATE_PATTERN,Hr as STACK_NOT_FOUND_PATTERN,h as STEP_COMPLETE_STATUSES,be as STEP_IDS,Ve as STEP_NAMES,D as SUPPORTED_CONTRACT_MARKERS,So as ServiceArtefactSchema,lo as ServiceArtefactsSchema,j as SimpleAwsProvider,Ta as StackUnavailableError,A as StepProgressSchema,ks as StepRegistry,qe as TICKET_VERDICT_SOURCES,ei as TRAIL_BUCKET_OUTPUT_KEY,ri as TRAIL_KEY_ARN_OUTPUT_KEY,kt as TemplateHashError,Ut as TemplateHashService,ze as TicketVerdictSourceSchema,jt as ValidationError,Va as accountsConfigToOUTree,Pe as activateCostAllocationTags,le as activateTrustedAccess,ra as advertisableDriftVerbs,Sn as advertisableRemediationVerbs,yi as applyRetainFlip,rn as approvalRefusalReason,mi as archiveCompletedRemediationJournal,Eo as artefactOutputKey,Ra as assertLeaseBeforeStack,Bi as assessForgetResumability,ha as assumeRootForTask,Bo as buildAccountRegionPairs,ue as buildAccountToOUMap,Ns as buildBuildSecretSessionPolicy,Ys as buildDeployPlan,gs as buildDeploySessionPolicy,an as buildDestructionTicket,ta as buildDriftRepairTicket,Yo as buildRegionList,Ts as buildSatelliteRecordIndex,Gt as buildStepContextBuildConfig,$ as buildTargetSetUnreadyAdvisory,z as buildTargetUnreadyAdvisory,Li as captureRemediationForensics,Go as cascadeHomeRegion,Ko as cascadeOperationKey,la as checkDeployPathStackAvailability,Oe as checkIdentityCentreStatus,te as checkRegionEnabled,Z as checkTargetReadiness,oi as classifyDriftFailure,Xs as classifyImpact,As as classifyZoneRecords,si as clearDriftSuspects,Gi as completeForgetAfterConverge,Ki as completeForgetAfterDeploy,hi as composeFlipCapabilities,Ea as composePostFailureRepairOffer,Ce as composeSdkAbortSignal,Gs as computeAssemblyDigest,Bs as computeDeployPlan,di as computeRemediationOpId,Fo as computeSecretsDrift,xi as computeTemplateDigest,nn as computeTicketDigest,Kt as convertCloudFormationOutputsToRecord,pe as createAccount,H as createDeployEmitter,ot as createEmptyState,Rn as createMemoisedPlanLoader,$a as createPublicResolvers,mo as createSequencedCallbacks,Rs as createSystemDnsNameProbe,Zo as decideNextTransition,zo as decommissionMemberTrailStorage,ni as defaultDriftJournalDir,Ii as defaultRemediationForensicsDir,ui as defaultRemediationJournalDir,Es as deleteChildNsFromParent,At as deleteDomainState,it as deleteStateFile,Lo as deploy,as as deployDelegatedDomain,Hs as derivePropertyChanges,qi as deriveRemovalTemplate,zr as deriveResourcesFromManifestStacks,vi as deriveRetainFlipTemplate,Mo as deriveStaleParameters,se as describeOrganisation,q as describeTargetReadinessReason,yo as destroy,Si as detectStackDrift,Ks as digestHead,Ms as dockerBuilder,ye as drainPages,Vt as emitProgress,Fe as enableCentralisedRootAccess,Ae as enableIpamDelegatedAdmin,ne as enablePolicyTypes,Se as enableRamSharing,Ee as enableServiceAccess,Na as ensureEnforceSsl,ae as ensureOrganisationExists,me as ensureOrganisationalUnitsExist,sn as evaluateDestructionConsents,cn as executableRemediationVerbs,ba as extractAllAccountNames,Uo as extractConsumedSsmParameters,Ne as extractErrorName,fo as failure,ii as fetchLastOperationEvents,Do as fileExists,oo as filterDangerousEnvVars,_e as findAccount,De as findDevelopmentOuId,Fi as findMarkedResourcesByOpId,Di as findRemediationJournalByOpId,zi as findRemovalDeletionFailures,$i as findResourcesPresent,ka as flattenAccountsToEnvironments,Ai as formatDriftPreFlightBlock,ca as formatDriftRepairOffer,Nt as formatInfrastructureError,ia as formatPinOutcomeDetail,Xi as formatRecreateInFlightCures,vr as getApplicationDeployOrder,Fr as getApplicationDestroyOrder,Mr as getApplicationStackName,Br as getApplicationStepId,Yr as getApplicationStepName,bs as getDestroyStepId,Ur as getOrganisationStackName,hr as getParallelDeployGroups,xr as getParallelDestroyGroups,Lt as getSourceContext,st as getStateFilePath,gt as getStructuralHint,It as hasCdkDifferences,To as hasDockerfile,Tt as hashDomainDirectory,ge as isAborted,Ba as isAccountsConfig,Ir as isApplicationOperation,kr as isApplicationStack,Ct as isCdkError,ws as isDataLoss,ds as isDelegatedToRoute53,Aa as isDeployPathBlockingStatus,Pa as isEnforceSslStatement,No as isFailure,he as isOULeaf,Kr as isOpenNextPattern,yr as isOrganisationOperation,Ga as isOuOnlyAccountBucket,br as isQuarantineDetail,_r as isRemediationPlaceholderPhysicalId,Vr as isRetainedBucketsDetail,xa as isRootTaskPolicyArn,ms as isRoute53NameServer,Js as isStatefulResourceType,Ya as isStringArray,Co as isSuccess,En as legalRemediationVerbs,Re as listAccounts,Pi as listActiveRemediationOps,Oi as listActiveRemediationOpsForContext,Tn as loadDeployPlan,io as maskSensitiveOutput,jo as mergeReconciledProviderAccounts,ps as normaliseRecordName,cs as nsDelegationPhysicalName,vs as openNextBuilder,Ua as parseAccountsConfiguration,Bt as parseBuildPhase,J as parseDeployContractVersion,w as parseDeployEvent,yt as parseDiffOutput,ao as parseShellArgs,bo as partitionAccounts,Ls as partitionForRegion,Hi as partitionPreFlightByRemediation,aa as pinProbeCoverage,de as placeAccountsInOUs,ee as probeAccountStackExists,vo as probeSecretsDrift,wo as projectAccountRows,Ho as projectScalarSummary,Mi as proveFlipMetadataOnly,ea as proveRemovalTargetsOnly,ct as readDomainState,Ei as readDriftSuspects,fi as readRemediationJournal,Ui as readRetainFlipState,rt as readStateFile,Qo as reconcileProviderAccounts,qo as reconcileTrailMigration,lt as recordDomainDeployState,ci as recordDriftSuspects,oe as regionDisabledMessage,nt as regionSuffix,xe as registerSecurityDelegates,Tr as remediationPhaseRank,Rr as remediationPlaceholderPhysicalId,An as renderConsentVerdictLines,ln as renderDestructionTicketLines,sa as renderPinReportLines,js as renderPlanLines,Qs as renderPlanSummary,Cs as resolveBuildArgs,Os as resolveBuildSecretSessionProvider,Ds as resolveBuildSecrets,Ps as resolveSecretRefValue,xo as restart,ga as restoreAndReconcileQuarantinedBucket,fa as restoreBucketPolicy,en as runApprovalGate,is as runCaaPreflight,Ss as runDelegatedDomainDestroy,on as runDestructionGate,li as runDriftPreFlight,oa as runDriftRepairGate,wi as runForgetSurgery,Ha as runOpenNextBuild,Ja as runOrganisationSetup,na as runPinRemediation,Zi as runRecreatePreFlight,Qi as runRecreateSurgery,_i as runRoute53RecordPreflight,Zs as signApprovalToken,so as sleep,_o as sleepAbortable,fe as snapshotIdentityCentre,ji as snapshotPolicyForType,fs as sourcedRefsFromBuildArgs,Ot as startStackMonitoring,Fs as staticSiteBuilder,Zr as stubCallerIdentity,Oo as success,Ci as sweepExpiredRemediationJournals,Ji as synthTemplateDeclaresResource,Ca as synthesiseEnforceSslDocument,_s as systemDnsNameProbe,ns as templateOwnsDelegationRecord,Gr as toPascalCase,Oa as toResourcePolicyStatements,ro as toServiceError,Ws as toWirePlanChanges,Da as triageBucketPolicy,ma as unlockBucket,da as unlockQueue,Te as updateBackupGlobalSettings,at as updateTemplateHash,Is as validateBuildGroup,ar as verbsForDriftVerdict,qs as verifyApprovalToken,Ia as verifyOrgTrailDelivery,ki as verifyRetainFlipDiff,ts as waitForNsPropagation,Wr as wrapApplicationError,St as writeDomainState,Ni as writeRemediationJournal,tt as writeStateFile};
|
|
@@ -19,6 +19,7 @@ import type { ApprovalGate, ApprovalGatePlanDetail } from "../../types/approval.
|
|
|
19
19
|
import type { CfnRegistrySummaryReader } from "../../services/infrastructure/CfnRegistryService.js";
|
|
20
20
|
import type { CfnTemplateReader } from "./plan/computeDeployPlan.js";
|
|
21
21
|
import { type DeployPlanLoader } from "./plan/loadDeployPlan.js";
|
|
22
|
+
import { type VerifyApprovalTokenResult } from "./plan/approvalToken.js";
|
|
22
23
|
export interface RunApprovalGateParams {
|
|
23
24
|
/** The surface resolver. Optional — a token-resume or plan-only run needs none. */
|
|
24
25
|
approvalGate?: ApprovalGate;
|
|
@@ -57,4 +58,14 @@ export type ApprovalGateOutcome = {
|
|
|
57
58
|
expiresAt: string;
|
|
58
59
|
planDetail: ApprovalGatePlanDetail;
|
|
59
60
|
};
|
|
61
|
+
type ApprovalRefusal = Extract<VerifyApprovalTokenResult, {
|
|
62
|
+
ok: false;
|
|
63
|
+
}>["reason"];
|
|
64
|
+
/**
|
|
65
|
+
* The canonical operator-facing wording for each token-refusal reason.
|
|
66
|
+
* Exported so every surface that verifies an approval token outside this
|
|
67
|
+
* gate (the domain deploy operation) refuses with byte-identical copy.
|
|
68
|
+
*/
|
|
69
|
+
export declare function approvalRefusalReason(reason: ApprovalRefusal): string;
|
|
60
70
|
export declare function runApprovalGate(params: RunApprovalGateParams): Promise<Result<ApprovalGateOutcome, Error>>;
|
|
71
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var k=Object.defineProperty;var p=(e,n)=>k(e,"name",{value:n,configurable:!0});import{success as o,failure as v}from"@fjall/generator";import{computeAssemblyDigest as h}from"./plan/assemblyDigest.js";import{loadDeployPlan as y}from"./plan/loadDeployPlan.js";import{renderPlanLines as A}from"./plan/renderDeployPlan.js";import{signApprovalToken as w,verifyApprovalToken as m}from"./plan/approvalToken.js";function x(e){switch(e){case"superseded":return"the plan changed since it was approved (re-plan and approve again)";case"expired":return"the approval window expired";case"tampered":return"the approval signature did not verify";case"malformed":return"the approval token was malformed"}}p(x,"
|
|
1
|
+
var k=Object.defineProperty;var p=(e,n)=>k(e,"name",{value:n,configurable:!0});import{success as o,failure as v}from"@fjall/generator";import{computeAssemblyDigest as h}from"./plan/assemblyDigest.js";import{loadDeployPlan as y}from"./plan/loadDeployPlan.js";import{renderPlanLines as A}from"./plan/renderDeployPlan.js";import{signApprovalToken as w,verifyApprovalToken as m}from"./plan/approvalToken.js";function x(e){switch(e){case"superseded":return"the plan changed since it was approved (re-plan and approve again)";case"expired":return"the approval window expired";case"tampered":return"the approval signature did not verify";case"malformed":return"the approval token was malformed"}}p(x,"approvalRefusalReason");function P(e,n,r){const i=n.changeCount===0&&r.length>0?`no resource changes against the live stacks; template hashes differ from the last recorded deploy for ${r.length} stack(s) (${r.join(", ")}) \u2014 applying will redeploy them`:n.summary;e.onLog?.(`Deploy plan: ${i}`,"info");for(const u of A(n))e.onLog?.(u,"info")}p(P,"emitPlanSummary");async function j(e){const n=h(e.detection.currentHashes),r=e.options.approvalToken;if(r!==void 0&&r!==""){const t=m({token:r,assemblyDigest:n});if(t.ok)return e.callbacks.onLog?.("Approval token verified against the current plan \u2014 proceeding","info"),o({kind:"proceed"});const f=x(t.reason);return e.callbacks.onLog?.(`Approval refused: ${f}`,"warn"),o({kind:"rejected",reason:f})}const i=[...e.detection.stackChanges.entries()].filter(([,t])=>t).map(([t])=>t),l=await(e.loadPlan??(()=>y({cfnService:e.cfnService,cdkOutPath:e.cdkOutPath,changedStacks:i,assemblyDigest:n,...e.registry!==void 0?{registry:e.registry}:{},...e.abortSignal!==void 0?{abortSignal:e.abortSignal}:{}})))();if(!l.success)return v(l.error);const s=l.data;P(e.callbacks,s,i);const c={hashDriftStacks:i,resourceChangeCount:s.changeCount,resourceChangedStacks:[...new Set(s.changes.map(t=>t.stack))]},a=w({assemblyDigest:n});if(e.options.autoApprove===!0)return e.callbacks.onLog?.("Plan auto-approved (--auto-approve)","info"),o({kind:"proceed"});if(e.options.planOnly===!0)return o({kind:"awaiting",approvalToken:a.token,assemblyDigest:n,expiresAt:a.expiresAt,planDetail:c});if(e.approvalGate===void 0)return o({kind:"awaiting",approvalToken:a.token,assemblyDigest:n,expiresAt:a.expiresAt,planDetail:c});const g={target:e.target,plan:s,approvalToken:a.token,expiresAt:a.expiresAt,hasDestructiveChanges:s.hasDestructiveChanges},d=await e.approvalGate.resolve(g);switch(d.kind){case"approved":return o({kind:"proceed"});case"rejected":return o({kind:"rejected",reason:d.reason,planDetail:c});case"suspended":return o({kind:"awaiting",approvalToken:d.approvalToken,assemblyDigest:n,expiresAt:a.expiresAt,planDetail:c})}}p(j,"runApprovalGate");export{x as approvalRefusalReason,j as runApprovalGate};
|
|
@@ -8,3 +8,5 @@ export { NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS, NS_PROPAGATION_DEFAULT_INTERVAL_MS
|
|
|
8
8
|
export { ACM_CAA_ISSUERS, caaAncestorChain, formatCaaRecord, runCaaPreflight, type CaaPreflightParams, type CaaPreflightVerdict } from "./caaPreflight.js";
|
|
9
9
|
export { deployDelegatedDomain, type DelegatedDomainDeployer, type DelegatedZonePhaseState, type DeployDelegatedDomainParams, type DelegatedDomainDeployOutcome } from "./delegatedDomainDeploy.js";
|
|
10
10
|
export { CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE, templateOwnsDelegationRecord, deleteChildNsFromParent, nsDelegationPhysicalName, runDelegatedDomainDestroy, type NsDeleteOutcome, type DeleteChildNsParams, type DelegationDestroyNsOutcome, type DelegatedDomainDestroyOutcome, type DelegatedDomainDestroyParams } from "./delegationDestroyMirror.js";
|
|
11
|
+
export { classifyZoneRecords, buildSatelliteRecordIndex, createSystemDnsNameProbe, systemDnsNameProbe, normaliseRecordName, type RecordClassification, type ClassifiedRecord, type ZoneClassificationReport, type ZoneClassifierClients, type ZoneClassifierPhase, type ClassifyZoneOptions, type SatelliteRecordIndex, type AwsSdkClientLike, type DnsProbeVerdict, type DnsNameProbe } from "./zoneClassifier.js";
|
|
12
|
+
export { isRoute53NameServer, isDelegatedToRoute53 } from "./route53Delegation.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DOMAIN_DELEGATION_ERROR_TYPES as r,DomainDelegationError as a,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as
|
|
1
|
+
import{DOMAIN_DELEGATION_ERROR_TYPES as r,DomainDelegationError as a,DEFAULT_PUBLIC_RESOLVER_ADDRESSES as t,PUBLIC_DNS_QUERY_TIMEOUT_MS as s,createPublicResolvers as m,normaliseDnsName as _,isDnsEmptyAnswer as n}from"./types.js";import{NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS as E,NS_PROPAGATION_DEFAULT_INTERVAL_MS as R,waitForNsPropagation as i}from"./nsPropagationGate.js";import{ACM_CAA_ISSUERS as A,caaAncestorChain as S,formatCaaRecord as N,runCaaPreflight as T}from"./caaPreflight.js";import{deployDelegatedDomain as O}from"./delegatedDomainDeploy.js";import{CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as c,templateOwnsDelegationRecord as C,deleteChildNsFromParent as p,nsDelegationPhysicalName as I,runDelegatedDomainDestroy as f}from"./delegationDestroyMirror.js";import{classifyZoneRecords as L,buildSatelliteRecordIndex as g,createSystemDnsNameProbe as x,systemDnsNameProbe as y,normaliseRecordName as M}from"./zoneClassifier.js";import{isRoute53NameServer as F,isDelegatedToRoute53 as b}from"./route53Delegation.js";export{A as ACM_CAA_ISSUERS,c as CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE,t as DEFAULT_PUBLIC_RESOLVER_ADDRESSES,r as DOMAIN_DELEGATION_ERROR_TYPES,a as DomainDelegationError,R as NS_PROPAGATION_DEFAULT_INTERVAL_MS,E as NS_PROPAGATION_DEFAULT_MAX_ATTEMPTS,s as PUBLIC_DNS_QUERY_TIMEOUT_MS,g as buildSatelliteRecordIndex,S as caaAncestorChain,L as classifyZoneRecords,m as createPublicResolvers,x as createSystemDnsNameProbe,p as deleteChildNsFromParent,O as deployDelegatedDomain,N as formatCaaRecord,b as isDelegatedToRoute53,n as isDnsEmptyAnswer,F as isRoute53NameServer,_ as normaliseDnsName,M as normaliseRecordName,I as nsDelegationPhysicalName,T as runCaaPreflight,f as runDelegatedDomainDestroy,y as systemDnsNameProbe,C as templateOwnsDelegationRecord,i as waitForNsPropagation};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Route53-delegation heuristic — the ONE implementation behind both
|
|
3
|
+
* the CLI's `fjall domain verify` and the webapp's manage_domain verify
|
|
4
|
+
* operation, so the two surfaces can never disagree on the same zone.
|
|
5
|
+
*
|
|
6
|
+
* DNS is case-insensitive (RFC 4343) and dns0x20 query randomisation
|
|
7
|
+
* legitimately returns upper/mixed-case NS names, so matching MUST be
|
|
8
|
+
* case-insensitive; zone-file-shaped inputs carry a trailing dot, so that is
|
|
9
|
+
* shed too. Both are handled by routing through `normaliseRecordName`.
|
|
10
|
+
*
|
|
11
|
+
* The `awsdns` substring test is deliberately a HEURISTIC, not hardening: it
|
|
12
|
+
* matches any name containing `awsdns` (Route53's name-server namespace,
|
|
13
|
+
* `ns-*.awsdns-NN.{com,net,org,co.uk}`). Delegation verification is a
|
|
14
|
+
* user-facing readiness signal, not a security boundary.
|
|
15
|
+
*/
|
|
16
|
+
/** True when a single NS name looks like a Route53 name server. */
|
|
17
|
+
export declare function isRoute53NameServer(ns: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* True when ANY of the zone's name servers is a Route53 name server — the
|
|
20
|
+
* delegation verdict for a resolver's NS answer. Empty input is `false`
|
|
21
|
+
* (no answer proves nothing).
|
|
22
|
+
*/
|
|
23
|
+
export declare function isDelegatedToRoute53(nameservers: readonly string[]): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var t=Object.defineProperty;var o=(e,r)=>t(e,"name",{value:r,configurable:!0});import{normaliseRecordName as n}from"./zoneClassifier.js";const s="awsdns";function i(e){return n(e).includes(s)}o(i,"isRoute53NameServer");function R(e){return e.some(i)}o(R,"isDelegatedToRoute53");export{R as isDelegatedToRoute53,i as isRoute53NameServer};
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
* destroy mirror that removes the child NS from the parent BEFORE the CFN
|
|
6
6
|
* destroy.
|
|
7
7
|
*
|
|
8
|
-
* `DomainDeployPhase` is
|
|
9
|
-
* contract (`components/infrastructure/lib/utils/domainTypes.ts`, shared with
|
|
8
|
+
* `DomainDeployPhase` is the construct-side wire contract (shared with
|
|
10
9
|
* `DevSubstrate.phase`): the CLI injects `phase` into synth and
|
|
11
10
|
* `composeDelegatedDomain` early-returns before certificate issuance when the
|
|
12
|
-
* phase is `"zone"`.
|
|
13
|
-
* (
|
|
14
|
-
*
|
|
11
|
+
* phase is `"zone"`. The two-literal union is homed in `@fjall/util`
|
|
12
|
+
* (`infra/domainExports.ts`) — the lowest common layer — and re-exported here
|
|
13
|
+
* and at `components/infrastructure/lib/utils/domainTypes.ts` so both sides
|
|
14
|
+
* read one declaration.
|
|
15
15
|
*/
|
|
16
16
|
import { BaseServiceError } from "../../types/errors/ServiceError.js";
|
|
17
17
|
/** Two-step deploy phase — the construct-side gate's wire vocabulary. */
|
|
18
|
-
export type DomainDeployPhase
|
|
18
|
+
export type { DomainDeployPhase } from "@fjall/util";
|
|
19
19
|
/**
|
|
20
20
|
* Typed failure vocabulary for the delegation orchestration. The codes are
|
|
21
21
|
* part of the surface contract: `delegation_unreachable` mirrors the
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { type Result } from "@fjall/generator";
|
|
2
|
+
/**
|
|
3
|
+
* D6 zone-hygiene classification engine (design
|
|
4
|
+
* 2026-07-17-domain-management-gold-plating.md). Pure orchestration over
|
|
5
|
+
* injected AWS clients — no AwsContext, no process state — so every
|
|
6
|
+
* classification path is unit-testable with fakes. All evidence gathering is
|
|
7
|
+
* read-only; classification NEVER mutates anything. Destructive follow-ups
|
|
8
|
+
* (residue deletion) route through the destruction ceremony on the Phase 3
|
|
9
|
+
* command surface, never from here.
|
|
10
|
+
*
|
|
11
|
+
* Fail-closed contract (fail-closed-default-policy ADR): whenever evidence
|
|
12
|
+
* cannot be obtained (AccessDenied, unreadable template, throttle), the
|
|
13
|
+
* affected records resolve to the conservative bucket — `unknown`, never
|
|
14
|
+
* `residue` — and the report carries a warning naming the gap and its cure.
|
|
15
|
+
*
|
|
16
|
+
* Residue evidence comes in exactly two shapes, both verified against live
|
|
17
|
+
* state: ACM validation CNAMEs no live certificate references, and dangling
|
|
18
|
+
* A/AAAA aliases into AWS-managed namespaces (CloudFront/ELB) whose target a
|
|
19
|
+
* read-only DNS probe proves NXDOMAIN. Everything else stays `unknown`.
|
|
20
|
+
*/
|
|
21
|
+
export type RecordClassification = "declared" | "satellite" | "residue" | "unknown";
|
|
22
|
+
export interface ClassifiedRecord {
|
|
23
|
+
/** Normalised FQDN: lowercase, no trailing dot, octal escapes decoded. */
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly type: string;
|
|
26
|
+
/**
|
|
27
|
+
* Routing-policy variant identity. Each SetIdentifier variant is its own
|
|
28
|
+
* classified record — evidence is evaluated, and remediation consented,
|
|
29
|
+
* per variant.
|
|
30
|
+
*/
|
|
31
|
+
readonly setIdentifier?: string;
|
|
32
|
+
/** Live record values (alias records carry the alias target DNS name). */
|
|
33
|
+
readonly values: readonly string[];
|
|
34
|
+
readonly classification: RecordClassification;
|
|
35
|
+
/** Owning CloudFormation stack, when proven (declared/satellite). */
|
|
36
|
+
readonly ownerStack?: string;
|
|
37
|
+
/** Human-readable evidence note (masked at construction). */
|
|
38
|
+
readonly detail?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface ZoneClassificationReport {
|
|
41
|
+
readonly hostedZoneId: string;
|
|
42
|
+
readonly zoneName: string;
|
|
43
|
+
readonly records: readonly ClassifiedRecord[];
|
|
44
|
+
readonly counts: Readonly<Record<RecordClassification, number>>;
|
|
45
|
+
/** Evidence gaps that forced conservative verdicts (already masked). */
|
|
46
|
+
readonly warnings: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Minimal structural AWS SDK v3 client — the injectable seam. Command
|
|
50
|
+
* instances are the real SDK command classes, so fakes can dispatch on
|
|
51
|
+
* `instanceof`.
|
|
52
|
+
*/
|
|
53
|
+
export interface AwsSdkClientLike {
|
|
54
|
+
send(command: unknown, options?: {
|
|
55
|
+
abortSignal?: AbortSignal;
|
|
56
|
+
}): Promise<unknown>;
|
|
57
|
+
}
|
|
58
|
+
export interface ZoneClassifierClients {
|
|
59
|
+
readonly route53: AwsSdkClientLike;
|
|
60
|
+
readonly cloudFormation: AwsSdkClientLike;
|
|
61
|
+
/**
|
|
62
|
+
* ACM clients keyed by region. Must cover every region a relevant
|
|
63
|
+
* certificate can live in: the zone's home region (ALB/API certs) and
|
|
64
|
+
* us-east-1 (CloudFront certs, D3).
|
|
65
|
+
*/
|
|
66
|
+
readonly acmByRegion: ReadonlyMap<string, AwsSdkClientLike>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* DNS-probe verdict for a dangling-alias target. The probe answers an
|
|
70
|
+
* existence question, not a liveness one: `resolves` means address records
|
|
71
|
+
* were observed on either family, so the target NAME still exists in DNS and
|
|
72
|
+
* the record cannot be dangling. Only `nxdomain`, the resolver's name-wide
|
|
73
|
+
* proof the name no longer exists (RFC 2308: NXDOMAIN means no records of
|
|
74
|
+
* ANY type), can support a `residue` verdict. `indeterminate` (SERVFAIL,
|
|
75
|
+
* timeout, cancellation, or NODATA on both families; see
|
|
76
|
+
* createSystemDnsNameProbe for why double NODATA proves nothing) fails
|
|
77
|
+
* closed to `unknown` per the fail-closed-default-policy ADR.
|
|
78
|
+
*/
|
|
79
|
+
export type DnsProbeVerdict = "nxdomain" | "resolves" | "indeterminate";
|
|
80
|
+
/** Injectable DNS probe seam — unit tests supply fakes, never live DNS. */
|
|
81
|
+
export type DnsNameProbe = (dnsName: string, abortSignal?: AbortSignal) => Promise<DnsProbeVerdict>;
|
|
82
|
+
/**
|
|
83
|
+
* Build the default probe over per-family address lookups. The probe answers
|
|
84
|
+
* one question: does the target NAME still exist in DNS? c-ares surfaces
|
|
85
|
+
* NXDOMAIN as ENOTFOUND, and NXDOMAIN is name-wide (RFC 2308: no records of
|
|
86
|
+
* ANY type), so an A-query ENOTFOUND is definitive absence with no AAAA
|
|
87
|
+
* query needed. ENODATA on A means NOERROR with no A records (e.g. an
|
|
88
|
+
* IPv6-only or dualstack-without-public-IPv4 load balancer), so the AAAA
|
|
89
|
+
* family gets a say: addresses prove the name exists (`resolves`), ENOTFOUND
|
|
90
|
+
* is still definitive absence. A second ENODATA proves NOTHING and stays
|
|
91
|
+
* `indeterminate`: cloudfront.net's authoritative servers answer NOERROR
|
|
92
|
+
* with zero records for EVERY name (deleted distributions included), never
|
|
93
|
+
* NXDOMAIN, so double NODATA is the mainline shape of a dangling CloudFront
|
|
94
|
+
* target, not evidence of existence. Any other code in either query
|
|
95
|
+
* (ESERVFAIL, ETIMEOUT, ECANCELLED and friends) is `indeterminate` so
|
|
96
|
+
* dependent records fail closed. Exported as a factory so the
|
|
97
|
+
* code-to-verdict matrix is testable without live DNS.
|
|
98
|
+
*/
|
|
99
|
+
export declare function createSystemDnsNameProbe(resolveAddresses?: (dnsName: string, rrtype: "A" | "AAAA", abortSignal?: AbortSignal) => Promise<string[]>): DnsNameProbe;
|
|
100
|
+
export declare const systemDnsNameProbe: DnsNameProbe;
|
|
101
|
+
/** Progress phases, in emission order — the sync operation maps these onto steps. */
|
|
102
|
+
export type ZoneClassifierPhase = "read-records" | "index-stacks" | "check-acm" | "classify";
|
|
103
|
+
export interface ClassifyZoneOptions {
|
|
104
|
+
readonly zone: {
|
|
105
|
+
readonly hostedZoneId: string;
|
|
106
|
+
readonly zoneName: string;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* The domain stack that owns this zone (deploy-state convention). Records in
|
|
110
|
+
* its CURRENT deployed template classify `declared`. Omit when the zone has
|
|
111
|
+
* never been stack-owned (pre-adoption import flows) — only zone-owned
|
|
112
|
+
* SOA/apex-NS classify declared then.
|
|
113
|
+
*/
|
|
114
|
+
readonly domainStackName?: string;
|
|
115
|
+
readonly clients: ZoneClassifierClients;
|
|
116
|
+
/**
|
|
117
|
+
* Pre-built satellite index (per-run cache). Callers classifying several
|
|
118
|
+
* zones in one account build this once via `buildSatelliteRecordIndex` and
|
|
119
|
+
* pass it in; omitted, the classifier builds it itself.
|
|
120
|
+
*/
|
|
121
|
+
readonly satelliteIndex?: SatelliteRecordIndex;
|
|
122
|
+
/**
|
|
123
|
+
* DNS probe verifying dangling-alias targets (see DnsProbeVerdict).
|
|
124
|
+
* Injected by tests; production callers rely on the system-resolver default.
|
|
125
|
+
*/
|
|
126
|
+
readonly dnsProbe?: DnsNameProbe;
|
|
127
|
+
readonly abortSignal?: AbortSignal;
|
|
128
|
+
readonly onPhase?: (phase: ZoneClassifierPhase) => void;
|
|
129
|
+
}
|
|
130
|
+
export interface SatelliteRecordIndex {
|
|
131
|
+
/**
|
|
132
|
+
* record key (`name|TYPE|setIdentifier`, empty third segment for simple
|
|
133
|
+
* records) → owning live Fjall stack name.
|
|
134
|
+
*/
|
|
135
|
+
readonly byRecordKey: ReadonlyMap<string, string>;
|
|
136
|
+
/**
|
|
137
|
+
* Every live Fjall-owned stack that was enumerated, whether or not it
|
|
138
|
+
* declares Route53 records. Certificate-ownership evidence (D3) resolves
|
|
139
|
+
* validation-CNAME cert ARNs against these stacks' physical resources.
|
|
140
|
+
*/
|
|
141
|
+
readonly stackNames: readonly string[];
|
|
142
|
+
readonly warnings: readonly string[];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Route53 returns names with a trailing dot and octal-escaped bytes
|
|
146
|
+
* (`\052` = `*`). Normalise both directions (live names AND template names)
|
|
147
|
+
* through this so keys always compare.
|
|
148
|
+
*
|
|
149
|
+
* NOT the same as {@link normaliseDnsName} (orchestration/domain/types.ts),
|
|
150
|
+
* which only lowercases and sheds the trailing dot: this normaliser
|
|
151
|
+
* additionally DECODES Route53's octal escapes, so `\052.example.com.`
|
|
152
|
+
* becomes `*.example.com`. Use this one whenever the input can come from a
|
|
153
|
+
* Route53 API response (ListResourceRecordSets, ACM validation records);
|
|
154
|
+
* use normaliseDnsName for plain resolver/user-supplied names where a
|
|
155
|
+
* backslash sequence must stay literal.
|
|
156
|
+
*/
|
|
157
|
+
export declare function normaliseRecordName(name: string): string;
|
|
158
|
+
/**
|
|
159
|
+
* Extract every (name, type, setIdentifier) a CloudFormation template
|
|
160
|
+
* declares via `AWS::Route53::RecordSet` or `AWS::Route53::RecordSetGroup`.
|
|
161
|
+
* Intrinsic (non-string) names — or an intrinsic SetIdentifier, whose
|
|
162
|
+
* variant identity is unknowable — cannot be indexed; their live records
|
|
163
|
+
* stay in the conservative bucket rather than being guessed at.
|
|
164
|
+
*
|
|
165
|
+
* `Custom::CrossAccountZoneDelegation` resources (D8 child-writes) claim the
|
|
166
|
+
* `<DelegatedZoneName>|NS|` row they UPSERT into the parent zone, so a
|
|
167
|
+
* same-account child stack's delegation classifies declared/satellite
|
|
168
|
+
* exactly like a RecordSet. Unlike a RecordSet's routinely-intrinsic Name, a
|
|
169
|
+
* delegation without a literal DelegatedZoneName is FAILURE, not a skip:
|
|
170
|
+
* Fjall's delegated-domain path always synthesises the literal zone name, so
|
|
171
|
+
* a non-literal one is malformed, and the claim it hides targets ANOTHER
|
|
172
|
+
* zone's NS row, where a silent drop would leave that row 'unknown' with no
|
|
173
|
+
* warning naming this stack as the evidence gap.
|
|
174
|
+
*
|
|
175
|
+
* A non-JSON body (a hand-written YAML template) is FAILURE, never an empty
|
|
176
|
+
* key set: the stack may well declare records we cannot see, so treating it
|
|
177
|
+
* as zero claims would let its live records mint `residue`. Structurally
|
|
178
|
+
* valid JSON without record declarations IS genuine evidence of zero claims
|
|
179
|
+
* and stays success(empty). Deliberately no YAML parsing here: correct
|
|
180
|
+
* CloudFormation YAML requires the short-form intrinsic tag schema, a
|
|
181
|
+
* dependency and correctness surface of its own, so the cure named in the
|
|
182
|
+
* failure is conversion, not a lossy parse.
|
|
183
|
+
*/
|
|
184
|
+
export declare function extractTemplateRecordKeys(templateBody: string): Result<Set<string>, Error>;
|
|
185
|
+
/**
|
|
186
|
+
* Enumerate live Fjall-owned stacks in the account and index every Route53
|
|
187
|
+
* record their CURRENT deployed templates declare. Read-only; build once per
|
|
188
|
+
* run and share across zones (D6 "cached per run"). Enumeration or template
|
|
189
|
+
* failures degrade to warnings — affected records classify `unknown`, never
|
|
190
|
+
* `satellite` or `residue`.
|
|
191
|
+
*/
|
|
192
|
+
export declare function buildSatelliteRecordIndex(cloudFormation: AwsSdkClientLike, options?: {
|
|
193
|
+
readonly excludeStackNames?: readonly string[];
|
|
194
|
+
readonly abortSignal?: AbortSignal;
|
|
195
|
+
}): Promise<SatelliteRecordIndex>;
|
|
196
|
+
/**
|
|
197
|
+
* Classify every live record set in a hosted zone against the account's
|
|
198
|
+
* deployed CloudFormation state and live ACM certificates. See module doc for
|
|
199
|
+
* the fail-closed contract.
|
|
200
|
+
*/
|
|
201
|
+
export declare function classifyZoneRecords(options: ClassifyZoneOptions): Promise<Result<ZoneClassificationReport, Error>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var z=Object.defineProperty;var l=(t,e)=>z(t,"name",{value:e,configurable:!0});import{ListResourceRecordSetsCommand as K}from"@aws-sdk/client-route-53";import{DescribeStacksCommand as U,DescribeStackResourcesCommand as B,GetTemplateCommand as V}from"@aws-sdk/client-cloudformation";import{ListCertificatesCommand as F,DescribeCertificateCommand as G}from"@aws-sdk/client-acm";import{Resolver as j}from"node:dns/promises";import{success as R,failure as S}from"@fjall/generator";import{maskSensitiveOutput as h,getErrorMessage as A}from"@fjall/util";import{composeSdkAbortSignal as N,isAborted as C}from"../../aws/organisations/types.js";import{CROSS_ACCOUNT_DELEGATION_RESOURCE_TYPE as x}from"./delegationDestroyMirror.js";const W=5e3,Z=2;async function J(t,e,a){const n=new j({timeout:W,tries:Z}),o=l(()=>{n.cancel()},"cancel");a?.addEventListener("abort",o,{once:!0});try{return e==="A"?await n.resolve4(t):await n.resolve6(t)}finally{a?.removeEventListener("abort",o)}}l(J,"resolveWithSystemResolver");function X(t=J){const e=l(async(a,n,o)=>{try{return(await t(a,n,o)).length>0?"answers":"indeterminate"}catch(s){const i=s.code;return i==="ENOTFOUND"?"nxdomain":i==="ENODATA"?"nodata":"indeterminate"}},"queryFamily");return async(a,n)=>{const o=await e(a,"A",n);if(o==="answers")return"resolves";if(o==="nxdomain")return"nxdomain";if(o==="indeterminate")return"indeterminate";const s=await e(a,"AAAA",n);return s==="answers"?"resolves":s==="nxdomain"?"nxdomain":"indeterminate"}}l(X,"createSystemDnsNameProbe");const q=X(),Y=new Set(["CREATE_COMPLETE","UPDATE_COMPLETE","UPDATE_ROLLBACK_COMPLETE","IMPORT_COMPLETE","IMPORT_ROLLBACK_COMPLETE","UPDATE_IN_PROGRESS","UPDATE_COMPLETE_CLEANUP_IN_PROGRESS","UPDATE_ROLLBACK_IN_PROGRESS","UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS"]),H="fjall:",Q="Fjall",ee=/^_[0-9a-f]{8,64}$/,te=".acm-validations.aws",ne=[/\.cloudfront\.net$/,/\.elb\.amazonaws\.com$/,/\.elb\.[a-z0-9-]+\.amazonaws\.com$/];function g(t){const e=t.replace(/\\(\d{3})/g,(n,o)=>String.fromCharCode(parseInt(o,8)));return(e.endsWith(".")?e.slice(0,-1):e).toLowerCase()}l(g,"normaliseRecordName");function E(t,e,a){return`${g(t)}|${e.toUpperCase()}|${a??""}`}l(E,"recordKey");async function ae(t,e,a){const n=[];let o,s,i;do{if(C(a))throw new Error("record listing aborted by shutdown signal");const c=await t.send(new K({HostedZoneId:e,StartRecordName:o,StartRecordType:s,StartRecordIdentifier:i}),{abortSignal:N(a)});for(const r of c.ResourceRecordSets??[]){if(!r.Name||!r.Type)continue;const f=r.AliasTarget?.DNSName!==void 0?g(r.AliasTarget.DNSName):void 0,u=r.AliasTarget?.DNSName!==void 0?[r.AliasTarget.DNSName]:(r.ResourceRecords??[]).flatMap(p=>p.Value!==void 0?[p.Value]:[]);n.push({name:g(r.Name),type:r.Type,...r.SetIdentifier!==void 0?{setIdentifier:r.SetIdentifier}:{},values:u,...f!==void 0?{aliasTargetDnsName:f}:{}})}c.IsTruncated?(o=c.NextRecordName,s=c.NextRecordType,i=c.NextRecordIdentifier):(o=void 0,s=void 0,i=void 0)}while(o);return n}l(ae,"listLiveRecords");function re(t){const e=new Set;let a;try{a=JSON.parse(t)}catch{return S(new Error("stack template is not JSON (likely a hand-written YAML template), so its Route53 record declarations cannot be indexed. Cure: convert the template to JSON or accept conservative classification."))}if(typeof a!="object"||a===null)return R(e);const n=a.Resources;if(typeof n!="object"||n===null)return R(e);const o=l(s=>{const i=s.Name,c=s.Type,r=s.SetIdentifier;typeof i!="string"||typeof c!="string"||r!==void 0&&typeof r!="string"||e.add(E(i,c,r))},"addKey");for(const[s,i]of Object.entries(n)){if(typeof i!="object"||i===null)continue;const{Type:c,Properties:r}=i,f=typeof r=="object"&&r!==null?r:void 0;if(c===x){const u=f?.DelegatedZoneName;if(typeof u!="string")return S(new Error(`${x} resource '${s}' has no literal DelegatedZoneName, so the parent-zone NS row it writes cannot be indexed. Cure: synthesise the delegation with a literal delegated zone name or accept conservative classification.`));e.add(E(u,"NS"));continue}if(f!==void 0){if(c==="AWS::Route53::RecordSet")o(f);else if(c==="AWS::Route53::RecordSetGroup"){const u=f.RecordSets;if(!Array.isArray(u))continue;for(const p of u)typeof p=="object"&&p!==null&&o(p)}}}return R(e)}l(re,"extractTemplateRecordKeys");async function M(t,e,a){try{const n=await t.send(new V({StackName:e,TemplateStage:"Processed"}),{abortSignal:N(a)});if(n.TemplateBody===void 0)return S(new Error(`zone classification: CloudFormation returned no template body for stack '${e}'`));const o=re(n.TemplateBody);return o.success?o:S(new Error(`stack '${e}': ${o.error.message}`))}catch(n){return S(n instanceof Error?n:new Error(String(n)))}}l(M,"readStackRecordKeys");function oe(t){return t.Tags?.some(e=>e.Key?.startsWith(H))===!0?!0:t.StackName?.startsWith(Q)===!0}l(oe,"isFjallStack");async function ie(t,e={}){const a=new Map,n=[],o=new Set(e.excludeStackNames??[]),s=[];try{let i;do{if(C(e.abortSignal))throw new Error("stack enumeration aborted by shutdown signal");const c=await t.send(new U({...i!==void 0?{NextToken:i}:{}}),{abortSignal:N(e.abortSignal)});for(const r of c.Stacks??[])r.StackName===void 0||o.has(r.StackName)||r.StackStatus===void 0||!Y.has(r.StackStatus)||!oe(r)||s.push(r.StackName);i=c.NextToken}while(i!==void 0)}catch(i){return n.push(h(`zone classification: could not enumerate CloudFormation stacks (${A(i)}) \u2014 satellite ownership cannot be proven, so unmatched records classify 'unknown'. Cure: grant cloudformation:DescribeStacks and retry.`)),{byRecordKey:a,stackNames:[],warnings:n}}for(const i of s){const c=await M(t,i,e.abortSignal);if(!c.success){n.push(h(`zone classification: could not read template for stack '${i}' (${A(c.error)}) \u2014 its records classify 'unknown'. Cure: grant cloudformation:GetTemplate and retry.`));continue}for(const r of c.data)a.has(r)||a.set(r,i)}return{byRecordKey:a,stackNames:s,warnings:n}}l(ie,"buildSatelliteRecordIndex");async function se(t,e){const a=new Map;for(const[n,o]of t)try{const s=[];let i;do{if(C(e))throw new Error("certificate listing aborted by shutdown signal");const c=await o.send(new F({...i!==void 0?{NextToken:i}:{}}),{abortSignal:N(e)});for(const r of c.CertificateSummaryList??[])r.CertificateArn!==void 0&&s.push(r.CertificateArn);i=c.NextToken}while(i!==void 0);for(const c of s){if(C(e))throw new Error("certificate description aborted by shutdown signal");const r=await o.send(new G({CertificateArn:c}),{abortSignal:N(e)});for(const f of r.Certificate?.DomainValidationOptions??[]){const u=f.ResourceRecord;if(u?.Type==="CNAME"&&u.Name!==void 0){const p=g(u.Name),w=a.get(p)??new Set;w.add(c),a.set(p,w)}}}}catch(s){return S(new Error(`zone classification: could not read ACM certificates in ${n} (${A(s)}). Cure: grant acm:ListCertificates and acm:DescribeCertificate in ${n}, then retry.`))}return R(a)}l(se,"collectAcmValidationReferences");async function ce(t,e,a,n){const o=new Map,s=[];for(const i of e){if(o.size===a.size)break;try{if(C(n))throw new Error("stack resource listing aborted by shutdown signal");const c=await t.send(new B({StackName:i}),{abortSignal:N(n)});for(const r of c.StackResources??[])r.ResourceType!=="AWS::CertificateManager::Certificate"||r.PhysicalResourceId===void 0||!a.has(r.PhysicalResourceId)||o.has(r.PhysicalResourceId)||o.set(r.PhysicalResourceId,i)}catch(c){s.push(h(`zone classification: could not list resources for stack '${i}' (${A(c)}), so certificate ownership cannot be proven there and its validation CNAMEs stay 'unknown'. Cure: grant cloudformation:DescribeStackResources and retry.`))}}return{ownerByArn:o,warnings:s}}l(ce,"resolveCertificateOwnership");function b(t){if(t.type!=="CNAME")return!1;const e=t.name.split(".")[0]??"";return ee.test(e)?t.values.some(a=>g(a).endsWith(te)):!1}l(b,"isAcmValidationShaped");function P(t){if(t.type!=="A"&&t.type!=="AAAA")return!1;const e=t.aliasTargetDnsName;return e===void 0?!1:ne.some(a=>a.test(e))}l(P,"isAwsManagedAliasCandidate");async function Ne(t){const{zone:e,domainStackName:a,clients:n,abortSignal:o,onPhase:s}=t,i=[];s?.("read-records");let c;try{c=await ae(n.route53,e.hostedZoneId,o)}catch(d){return S(new Error(`zone classification: could not list record sets for zone ${e.hostedZoneId} (${e.zoneName}): ${A(d)}. Cure: grant route53:ListResourceRecordSets on the zone and retry.`))}let r=new Set,f=!0;if(a!==void 0){const d=await M(n.cloudFormation,a,o);d.success?r=d.data:(f=!1,i.push(h(`zone classification: could not read the domain stack template for '${a}' (${A(d.error)}) \u2014 only zone-owned SOA/NS classify 'declared'. Cure: deploy the domain stack with 'fjall domain deploy ${e.zoneName}' or grant cloudformation:GetTemplate.`)))}s?.("index-stacks");const u=t.satelliteIndex??await ie(n.cloudFormation,{...a!==void 0?{excludeStackNames:[a]}:{},...o!==void 0?{abortSignal:o}:{}});i.push(...u.warnings),s?.("check-acm");const p=c.some(b);let w;if(p){const d=await se(n.acmByRegion,o);d.success?w=d.data:i.push(h(d.error.message))}let I;if(w!==void 0){const d=new Set;for(const m of c)if(b(m))for(const y of w.get(m.name)??[])d.add(y);if(d.size>0){const m=await ce(n.cloudFormation,[...a!==void 0?[a]:[],...u.stackNames],d,o);I=m.ownerByArn,i.push(...m.warnings)}}const _=f&&u.warnings.length===0,T=new Set;if(_)for(const d of c){if(!P(d))continue;const m=E(d.name,d.type,d.setIdentifier);r.has(m)||u.byRecordKey.has(m)||T.add(d.aliasTargetDnsName)}let O;if(T.size>0){const d=t.dnsProbe??q,m=new Map;for(const y of T){let k;try{k=await d(y,o)}catch($){k="indeterminate",i.push(h(`zone classification: DNS probe for alias target '${y}' failed (${A($)}) \u2014 dependent alias records classify 'unknown', never 'residue'. Cure: retry with a working resolver.`)),m.set(y,k);continue}k==="indeterminate"&&i.push(h(`zone classification: DNS probe for alias target '${y}' was inconclusive \u2014 dependent alias records classify 'unknown', never 'residue'. Cure: retry once the resolver answers definitively.`)),m.set(y,k)}O=m}s?.("classify");const v=g(e.zoneName),D=c.map(d=>le(d,{zoneApex:v,domainStackName:a,declaredKeys:r,satelliteIndex:u,acmValidationReferences:w,certificateOwnerByArn:I,templateEvidenceComplete:_,aliasProbeVerdicts:O})).sort((d,m)=>d.name.localeCompare(m.name)||d.type.localeCompare(m.type)||(d.setIdentifier??"").localeCompare(m.setIdentifier??"")),L={declared:0,satellite:0,residue:0,unknown:0};for(const d of D)L[d.classification]+=1;return R({hostedZoneId:e.hostedZoneId,zoneName:v,records:D,counts:L,warnings:i})}l(Ne,"classifyZoneRecords");function de(t,e){const a=new Set;for(const n of t){const o=e?.get(n);if(o===void 0)return;a.add(o)}return a}l(de,"provenCertificateOwners");function le(t,e){const a=E(t.name,t.type,t.setIdentifier),n={name:t.name,type:t.type,...t.setIdentifier!==void 0?{setIdentifier:t.setIdentifier}:{},values:t.values};if(t.name===e.zoneApex&&(t.type==="SOA"||t.type==="NS"))return{...n,classification:"declared",...e.domainStackName!==void 0?{ownerStack:e.domainStackName}:{},detail:"zone-owned record, created with the hosted zone"};if(e.declaredKeys.has(a))return{...n,classification:"declared",...e.domainStackName!==void 0?{ownerStack:e.domainStackName}:{}};const o=e.satelliteIndex.byRecordKey.get(a);if(o!==void 0)return{...n,classification:"satellite",ownerStack:o};if(b(t)){if(e.acmValidationReferences===void 0)return{...n,classification:"unknown",detail:"ACM validation CNAME shape, but live-certificate evidence was unavailable \u2014 fail-closed as unknown rather than residue"};const s=e.acmValidationReferences.get(t.name);if(s!==void 0&&s.size>0){const i=de(s,e.certificateOwnerByArn);if(i!==void 0){const c=[...i].sort();if(e.domainStackName!==void 0&&c.every(f=>f===e.domainStackName))return{...n,classification:"declared",ownerStack:e.domainStackName,detail:"ACM validation CNAME for the domain stack's live certificates; required for issuance and auto-renewal"};const r=c.find(f=>f!==e.domainStackName);if(r!==void 0)return{...n,classification:"satellite",ownerStack:r,detail:`ACM validation CNAME for live certificates owned by ${c.map(f=>`'${f}'`).join(", ")}; required for issuance and auto-renewal`}}return{...n,classification:"unknown",detail:"ACM validation CNAME still referenced by a live certificate \u2014 keep it; it is not residue"}}return{...n,classification:"residue",detail:"ACM validation CNAME not referenced by any live certificate in the scanned regions"}}if(P(t)){if(!e.templateEvidenceComplete)return{...n,classification:"unknown",detail:"alias to an AWS-managed target, but template evidence was incomplete \u2014 fail-closed as unknown rather than residue"};const s=e.aliasProbeVerdicts?.get(t.aliasTargetDnsName);return s==="nxdomain"?{...n,classification:"residue",detail:`dangling alias: target ${t.aliasTargetDnsName} no longer exists (NXDOMAIN) and no live template references this record`}:s==="resolves"?{...n,classification:"unknown",detail:"alias target still exists in DNS, so the record cannot be dangling; not residue"}:{...n,classification:"unknown",detail:"alias target probe was inconclusive \u2014 fail-closed as unknown rather than residue"}}return{...n,classification:"unknown"}}l(le,"classifyRecord");export{ie as buildSatelliteRecordIndex,Ne as classifyZoneRecords,X as createSystemDnsNameProbe,re as extractTemplateRecordKeys,g as normaliseRecordName,q as systemDnsNameProbe};
|
|
@@ -80,6 +80,12 @@ export interface Route53RecordCollision {
|
|
|
80
80
|
readonly type: string;
|
|
81
81
|
/** Present when the template claim carries a routing-policy SetIdentifier. */
|
|
82
82
|
readonly setIdentifier?: string;
|
|
83
|
+
/**
|
|
84
|
+
* SetIdentifier of the LIVE record set this row would release — distinct
|
|
85
|
+
* from the claim's own `setIdentifier`. Each colliding live variant mints
|
|
86
|
+
* its own row, so a takeover release names exactly one record set.
|
|
87
|
+
*/
|
|
88
|
+
readonly liveSetIdentifier?: string;
|
|
83
89
|
/** Bare hosted-zone id the live collision was found in. */
|
|
84
90
|
readonly zoneId: string;
|
|
85
91
|
/** Pre-masked human description of the live record's values. */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var T=Object.defineProperty;var
|
|
2
|
-
`)}
|
|
1
|
+
var T=Object.defineProperty;var l=(e,t)=>T(e,"name",{value:t,configurable:!0});import{Route53Client as C,ListHostedZonesByNameCommand as x,ListResourceRecordSetsCommand as j}from"@aws-sdk/client-route-53";import{readFile as O}from"node:fs/promises";import{join as Z}from"node:path";import{getErrorMessage as I,maskSensitiveOutput as p}from"@fjall/util";import{logger as A}from"@fjall/util/logger";import{composeSdkAbortSignal as k,isAborted as w}from"../../aws/organisations/types.js";import{bareHostedZoneId as R,canonicalDnsName as g,listStartName as H}from"./route53Names.js";const D="Route53RecordPreflight";function b(e,t,n){return`${e}|${t}|${n??""}`}l(b,"ownershipKey");function P(e,t){const n=[],s=[];for(const[o,r]of Object.entries(t.Resources??{})){if(r?.Type!=="AWS::Route53::RecordSet")continue;const d=r.Properties??{},c=d.Name,a=d.Type,u=d.HostedZoneId,f=d.HostedZoneName,h=d.SetIdentifier,y=typeof u=="string"?{kind:"id",id:R(u)}:typeof f=="string"?{kind:"name",name:g(f)}:void 0;if(typeof c!="string"||typeof a!="string"||y===void 0||h!==void 0&&typeof h!="string"){s.push(o);continue}n.push({stackName:e,logicalId:o,name:g(c),declaredName:c,type:a,...typeof h=="string"?{setIdentifier:h}:{},zone:y})}return{claims:n,skipped:s}}l(P,"extractRecordClaims");function L(e){const t=new Set;for(const n of Object.values(e.Resources??{})){if(n?.Type!=="AWS::Route53::RecordSet")continue;const s=n.Properties??{},o=s.Name,r=s.Type,d=s.SetIdentifier;typeof o!="string"||typeof r!="string"||t.add(b(g(o),r,typeof d=="string"?d:void 0))}return t}l(L,"extractOwnedKeys");async function F(e,t){try{const n=await O(Z(e,`${t}.template.json`),"utf8");return JSON.parse(n)}catch(n){A.debug(D,"Could not read the synthesised template",{stackName:t,error:p(I(n))});return}}l(F,"readSynthTemplate");async function M(e,t,n,s){const o=[];let r=H(n),d,c;for(;;){if(w(s))throw new Error("Pre-flight aborted while listing live record sets");const a=await e.send(new j({HostedZoneId:t,StartRecordName:r,...d!==void 0?{StartRecordType:d}:{},...c!==void 0?{StartRecordIdentifier:c}:{},MaxItems:100}),{abortSignal:k(s)});let u=!1;for(const f of a.ResourceRecordSets??[])f.Name!==void 0&&g(f.Name)===n?o.push(f):u=!0;if(a.IsTruncated!==!0||u||(r=a.NextRecordName??r,d=a.NextRecordType,c=a.NextRecordIdentifier,a.NextRecordName===void 0))break}return o}l(M,"listLiveRecordsAtName");async function E(e,t,n){const s=[];let o=t,r;for(;;){if(w(n))throw new Error("Pre-flight aborted while listing hosted zones");const d=await e.send(new x({DNSName:o,...r!==void 0?{HostedZoneId:r}:{},MaxItems:20}),{abortSignal:k(n)});let c=!1;for(const a of d.HostedZones??[])a.Name!==void 0&&g(a.Name)===t?a.Id!==void 0&&s.push(R(a.Id)):c=!0;if(d.IsTruncated!==!0||c||(o=d.NextDNSName??o,r=d.NextHostedZoneId,d.NextDNSName===void 0&&d.NextHostedZoneId===void 0))break}return s}l(E,"listZoneIdsNamed");function v(e){const t=e.SetIdentifier!==void 0?`${e.Type} [setIdentifier '${e.SetIdentifier}']`:`${e.Type??"unknown type"}`,n=e.AliasTarget?.DNSName!==void 0?`alias \u2192 ${e.AliasTarget.DNSName}`:(e.ResourceRecords??[]).map(s=>s.Value).filter(s=>s!==void 0).join(", ");return p(n!==""?`${t}: ${n}`:t)}l(v,"describeLiveRecord");function B(e,t,n){return t.filter(o=>o.Type===e.type).filter(o=>n.has(b(e.name,e.type,o.SetIdentifier))?!1:e.setIdentifier===void 0?!0:o.SetIdentifier===void 0||o.SetIdentifier===e.setIdentifier)}l(B,"findCollisions");function $(e){return e.zone.kind==="id"?e.zone.id:e.zone.name}l($,"zoneDisplay");function J(e){return[`Deploy halted: the Route53 record pre-flight found ${e.length} record conflict(s) or unverifiable zone(s).`,...e.map(t=>` - ${t}`),`A record that already exists and is not in this stack's previous template belongs to another owner \u2014 deploying over it would fail at CloudFormation mid-deploy. Inspect ownership with 'fjall domain records list <zone>'. There is no bypass flag; the two cures are ownership-shaped: a record owned by ANOTHER stack must be released from that owner through its destruction ceremony first; an adopted zone's live records can be taken over \u2014 re-run "fjall domain deploy <zone>" and consent to the takeover ticket with --remediate. If a zone listing failed transiently, re-run the deploy. Nothing was mutated.`].join(`
|
|
2
|
+
`)}l(J,"formatBlockMessage");function K(e,t,n){const s=e.type.toUpperCase();let o;return(s==="NS"||s==="SOA")&&(o=`${s} records never ride the record-takeover ceremony \u2014 SOA rides the zone lifecycle and an NS delegation has its own destroy-mirror ceremony ('fjall domain destroy <child>' releases a delegation); release the record from its owner instead`),{stackName:e.stackName,logicalId:e.logicalId,declaredName:e.declaredName,canonicalName:e.name,type:e.type,...e.setIdentifier!==void 0?{setIdentifier:e.setIdentifier}:{},...n.SetIdentifier!==void 0?{liveSetIdentifier:n.SetIdentifier}:{},zoneId:t,liveDescription:v(n),consentable:o===void 0,...o!==void 0?{nonConsentableReason:p(o)}:{}}}l(K,"buildCollisionRow");async function Y(e,t){const n=[],s=[];let o=!1;for(const r of t.stackNames){const d=await F(t.cdkOutPath,r);if(d===void 0){if(t.onUnreadableSynthTemplate==="block"){o=!0,n.push(p(`${r}: its synthesised template could not be read from ${t.cdkOutPath} \u2014 the record claims are unknowable, so the pre-flight fails closed; re-run the deploy, and if this persists check that the synth step wrote '${r}.template.json' into that directory`));continue}t.onLog?.(`Route53 record pre-flight skipped for ${r} \u2014 its synthesised template could not be read from ${t.cdkOutPath}; CloudFormation remains the record-collision backstop for this deploy`,"warn");continue}const{claims:c,skipped:a}=P(r,d);if(a.length>0&&t.onLog?.(`Route53 record pre-flight could not verify ${a.length} record set(s) on ${r} (${a.join(", ")}) \u2014 their name or zone identity is a CloudFormation intrinsic, not a literal; CloudFormation remains the collision backstop for them`,"warn"),c.length===0)continue;let u=new Set;const f=await t.cfnService.getTemplate(r,t.abortSignal);if(f.success)try{u=L(JSON.parse(f.data))}catch(i){o=!0,n.push(p(`${r}: the previously deployed template could not be parsed (${I(i)}) \u2014 record ownership is unverifiable, so the pre-flight fails closed; re-run the deploy, and if this persists inspect the stack's template in CloudFormation`));continue}else if(f.error.errorType!=="stack_not_found"){o=!0,n.push(p(`${r}: the previously deployed template could not be fetched (${f.error.message}) \u2014 record ownership is unverifiable, so the pre-flight fails closed; re-run the deploy`));continue}const h=e.getClient(C),y=new Map;for(const i of c){if(w(t.abortSignal)){o=!0,n.push(`${r} \u203A ${i.logicalId}: the pre-flight was aborted before the zone listing for '${i.declaredName}' completed \u2014 re-run the deploy`);break}if(!u.has(b(i.name,i.type,i.setIdentifier)))try{let m;i.zone.kind==="id"?m=[i.zone.id]:(m=y.get(i.zone.name)??await E(h,i.zone.name,t.abortSignal),y.set(i.zone.name,m));for(const N of m){const z=await M(h,N,i.name,t.abortSignal);for(const S of B(i,z,u))n.push(p(`${r} \u203A ${i.logicalId}: record '${i.declaredName}' (${i.type}${i.setIdentifier!==void 0?`, setIdentifier '${i.setIdentifier}'`:""}) already exists in zone ${N} and is not in this stack's previous template \u2014 live record: ${v(S)}. Find its owner with 'fjall domain records list ${$(i)}'`)),s.push(K(i,N,S))}}catch(m){o=!0,n.push(p(`${r} \u203A ${i.logicalId}: the live zone ${$(i)} could not be listed to verify record '${i.declaredName}' (${i.type}) \u2014 ${I(m)}. The pre-flight fails closed rather than deploying over an unverifiable zone; re-run the deploy, or inspect the zone with 'fjall domain records list ${$(i)}'`))}}}if(n.length>0){const r=J(n);return!o&&s.length===n.length?{kind:"blocked",message:r,collisions:s}:{kind:"blocked",message:r}}return{kind:"proceed"}}l(Y,"runRoute53RecordPreflight");export{Y as runRoute53RecordPreflight};
|
|
@@ -49,7 +49,7 @@ export type { OrgSetupPhase, OrgSetupCallbacks, OrgSetupConfig, OrgSetupResult }
|
|
|
49
49
|
export * from "./builders/index.js";
|
|
50
50
|
export { buildDeployPlan, computeDeployPlan, computeAssemblyDigest, digestHead, classifyImpact, derivePropertyChanges, isDataLoss, isStatefulResourceType, renderPlanSummary, renderPlanLines, toWirePlanChanges, signApprovalToken, verifyApprovalToken, DEFAULT_APPROVAL_TTL_MS, APPROVAL_TOKEN_PATTERN } from "./application/plan/index.js";
|
|
51
51
|
export type { DeployPlan, DeployPlanResourceChange, StackTemplatePair, CfnTemplateReader, ComputeDeployPlanParams, ComputeDeployPlanStack, ImpactClassification, SignApprovalTokenOptions, SignedApprovalToken, VerifyApprovalTokenOptions, VerifyApprovalTokenResult } from "./application/plan/index.js";
|
|
52
|
-
export { runApprovalGate, type RunApprovalGateParams, type ApprovalGateOutcome } from "./application/approvalGate.js";
|
|
52
|
+
export { runApprovalGate, approvalRefusalReason, type RunApprovalGateParams, type ApprovalGateOutcome } from "./application/approvalGate.js";
|
|
53
53
|
export { runDestructionGate, buildDestructionTicket, evaluateDestructionConsents, computeTicketDigest, legalRemediationVerbs, executableRemediationVerbs, advertisableRemediationVerbs, renderDestructionTicketLines, renderConsentVerdictLines, type RunDestructionGateParams, type DestructionGateOutcome, type EvaluateDestructionConsentsParams } from "./application/destructionGate.js";
|
|
54
54
|
export { loadDeployPlan, createMemoisedPlanLoader, type LoadDeployPlanParams, type DeployPlanLoader } from "./application/plan/loadDeployPlan.js";
|
|
55
55
|
export { classifyDriftFailure, fetchLastOperationEvents } from "./drift/classifyDriftFailure.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{deploy as t}from"./deploy.js";import{destroy as i}from"./destroy.js";import{restart as n,probeSecretsDrift as s}from"./restart/restartApplication.js";import{computeSecretsDrift as p,deriveStaleParameters as c,extractConsumedSsmParameters as m,ssmParameterNameFromValueFrom as u}from"./restart/secretsDrift.js";import{deployOrganisation as d}from"./organisation/organisationDeploy.js";import{destroyOrganisation as T}from"./organisation/organisationDestroy.js";import{cleanupFailedStack as x,emptyS3Bucket as P,preEmptyStackBuckets as A,formatQuarantineSuspectedMessage as E,formatRetainedBucketsMessage as D,isQuarantineDetail as y,isRetainedBucketsDetail as _,PRE_EMPTY_TAG_KEYS as g,isCleanableState as O,SAFE_CLEANUP_STATES as F}from"./stackCleanup.js";import{partitionAccounts as k,buildRegionList as B,buildAccountRegionPairs as b,cascadeHomeRegion as C,cascadeOperationKey as L}from"./organisation/cascadeHelpers.js";import{projectScalarSummary as I,projectAccountRows as h}from"./organisation/cascadeSummary.js";import{reconcileProviderAccounts as G,mergeReconciledProviderAccounts as K}from"./organisation/reconcileProviderAccounts.js";import{decideNextTransition as Y,reconcileTrailMigration as V,ORG_TRAIL_BUCKET_OUTPUT_KEY as J,TRAIL_BUCKET_OUTPUT_KEY as H,TRAIL_KEY_ARN_OUTPUT_KEY as Q}from"./trailMigration/trailMigration.js";import{decommissionMemberTrailStorage as j}from"./trailMigration/memberTrailCleanup.js";import{unlockBucket as q}from"./unlock/unlockBucket.js";import{unlockQueue as X}from"./unlock/unlockQueue.js";import{triageBucketPolicy as $,isEnforceSslStatement as ee}from"./unlock/bucketPolicyTriage.js";import{toResourcePolicyStatements as te}from"./unlock/toResourcePolicyStatements.js";import{restoreBucketPolicy as ie,synthesiseEnforceSslDocument as ae,ensureEnforceSsl as ne}from"./unlock/restoreBucketPolicy.js";import{restoreAndReconcileQuarantinedBucket as le}from"./unlock/restoreAndReconcileQuarantinedBucket.js";import{parseAccountsConfiguration as ce,flattenAccountsToEnvironments as me,extractAllAccountNames as ue,accountsConfigToOUTree as fe,isStringArray as de,isAccountsConfig as Re,isOuOnlyAccountBucket as Te,OU_ONLY_ACCOUNT_BUCKETS as Se}from"./organisation/accountsConfig.js";import{resolveBuildSecrets as Pe,resolveSecretRefValue as Ae,resolveBuildSecretSessionProvider as Ee,sourcedRefsFromBuildArgs as De}from"./application/buildSecretResolver.js";import{buildBuildSecretSessionPolicy as _e,partitionForRegion as ge}from"./application/buildSecretSession.js";import{buildDeploySessionPolicy as Fe}from"./application/deploySessionPolicy.js";import{resolveBuildArgs as ke}from"./application/buildArgResolver.js";import{validateBuildGroup as be}from"./application/buildGroupValidator.js";export*from"./domain/index.js";import{runOpenNextBuild as Ue}from"./application/openNextBuild.js";import{runOrganisationSetup as he,ORG_SETUP_PHASES as Ne}from"./organisation/organisationSetup.js";export*from"./builders/index.js";import{buildDeployPlan as Me,computeDeployPlan as Ye,computeAssemblyDigest as Ve,digestHead as Je,classifyImpact as He,derivePropertyChanges as Qe,isDataLoss as we,isStatefulResourceType as je,renderPlanSummary as We,renderPlanLines as qe,toWirePlanChanges as ze,signApprovalToken as Xe,verifyApprovalToken as Ze,DEFAULT_APPROVAL_TTL_MS as $e,APPROVAL_TOKEN_PATTERN as er}from"./application/plan/index.js";import{runApprovalGate as tr}from"./application/approvalGate.js";import{runDestructionGate as ir,buildDestructionTicket as ar,evaluateDestructionConsents as nr,computeTicketDigest as sr,legalRemediationVerbs as lr,executableRemediationVerbs as pr,advertisableRemediationVerbs as cr,renderDestructionTicketLines as mr,renderConsentVerdictLines as ur}from"./application/destructionGate.js";import{loadDeployPlan as dr,createMemoisedPlanLoader as Rr}from"./application/plan/loadDeployPlan.js";import{classifyDriftFailure as Sr,fetchLastOperationEvents as xr}from"./drift/classifyDriftFailure.js";import{DriftProbe as Ar}from"./drift/driftProbe.js";import{clearDriftSuspects as Dr,defaultDriftJournalDir as yr,readDriftSuspects as _r,recordDriftSuspects as gr}from"./drift/driftSuspectJournal.js";import{detectStackDrift as Fr}from"./drift/detectStackDrift.js";import{runDriftPreFlight as kr,formatDriftPreFlightBlock as Br,DRIFT_PREFLIGHT_TRIGGER_STATUSES as br,DRIFT_PREFLIGHT_BUDGET_MS as Cr}from"./drift/driftPreFlight.js";import{runRoute53RecordPreflight as Ur}from"./drift/route53RecordPreflight.js";import{archiveCompletedRemediationJournal as hr,computeRemediationOpId as Nr,defaultRemediationJournalDir as Gr,findRemediationJournalByOpId as Kr,listActiveRemediationOps as Mr,listActiveRemediationOpsForContext as Yr,readRemediationJournal as Vr,sweepExpiredRemediationJournals as Jr,writeRemediationJournal as Hr,REMEDIATION_JOURNAL_RETENTION_DAYS as Qr}from"./remediation/remediationJournal.js";import{captureRemediationForensics as jr,defaultRemediationForensicsDir as Wr}from"./remediation/forensicsCapture.js";import{applyRetainFlip as zr,composeFlipCapabilities as Xr,computeTemplateDigest as Zr,deriveRetainFlipTemplate as $r,findMarkedResourcesByOpId as et,proveFlipMetadataOnly as rt,readRetainFlipState as tt,verifyRetainFlipDiff as ot,FORGET_MARKER_KEY as it,FORGET_FLIP_SPEC as at,RECREATE_MARKER_KEY as nt}from"./remediation/retainFlip.js";import{assessForgetResumability as lt,completeForgetAfterConverge as pt,completeForgetAfterDeploy as ct,formatRecreateInFlightCures as mt,partitionPreFlightByRemediation as ut,runForgetSurgery as ft,synthTemplateDeclaresResource as dt}from"./remediation/forgetResource.js";import{runRecreateSurgery as Tt,snapshotPolicyForType as St,SNAPSHOT_CAPABLE_RESOURCE_TYPES as xt}from"./remediation/recreateResource.js";import{runRecreatePreFlight as At}from"./remediation/recreatePreFlight.js";import{deriveRemovalTemplate as Dt,findRemovalDeletionFailures as yt,findResourcesPresent as _t,proveRemovalTargetsOnly as gt}from"./remediation/removalUpdate.js";import{advertisableDriftVerbs as Ft,buildDriftRepairTicket as vt,runDriftRepairGate as kt}from"./remediation/driftRepairGate.js";import{formatPinOutcomeDetail as bt,pinProbeCoverage as Ct,renderPinReportLines as Lt,runPinRemediation as Ut}from"./remediation/pinRemediation.js";import{composePostFailureRepairOffer as ht,formatDriftRepairOffer as Nt,DriftRepairAvailableError as Gt}from"./remediation/postFailureRepairOffer.js";import{checkDeployPathStackAvailability as Mt,isDeployPathBlockingStatus as Yt,StackUnavailableError as Vt}from"./activeDeploymentGuard.js";import{assertLeaseBeforeStack as Ht,LeaseDeniedError as Qt}from"./application/leaseGate.js";export{er as APPROVAL_TOKEN_PATTERN,$e as DEFAULT_APPROVAL_TTL_MS,Cr as DRIFT_PREFLIGHT_BUDGET_MS,br as DRIFT_PREFLIGHT_TRIGGER_STATUSES,Ar as DriftProbe,Gt as DriftRepairAvailableError,at as FORGET_FLIP_SPEC,it as FORGET_MARKER_KEY,Qt as LeaseDeniedError,Ne as ORG_SETUP_PHASES,J as ORG_TRAIL_BUCKET_OUTPUT_KEY,Se as OU_ONLY_ACCOUNT_BUCKETS,g as PRE_EMPTY_TAG_KEYS,nt as RECREATE_MARKER_KEY,Qr as REMEDIATION_JOURNAL_RETENTION_DAYS,F as SAFE_CLEANUP_STATES,xt as SNAPSHOT_CAPABLE_RESOURCE_TYPES,Vt as StackUnavailableError,H as TRAIL_BUCKET_OUTPUT_KEY,Q as TRAIL_KEY_ARN_OUTPUT_KEY,fe as accountsConfigToOUTree,Ft as advertisableDriftVerbs,cr as advertisableRemediationVerbs,zr as applyRetainFlip,hr as archiveCompletedRemediationJournal,Ht as assertLeaseBeforeStack,lt as assessForgetResumability,b as buildAccountRegionPairs,_e as buildBuildSecretSessionPolicy,Me as buildDeployPlan,Fe as buildDeploySessionPolicy,ar as buildDestructionTicket,vt as buildDriftRepairTicket,B as buildRegionList,jr as captureRemediationForensics,C as cascadeHomeRegion,L as cascadeOperationKey,Mt as checkDeployPathStackAvailability,Sr as classifyDriftFailure,He as classifyImpact,x as cleanupFailedStack,Dr as clearDriftSuspects,pt as completeForgetAfterConverge,ct as completeForgetAfterDeploy,Xr as composeFlipCapabilities,ht as composePostFailureRepairOffer,Ve as computeAssemblyDigest,Ye as computeDeployPlan,Nr as computeRemediationOpId,p as computeSecretsDrift,Zr as computeTemplateDigest,sr as computeTicketDigest,Rr as createMemoisedPlanLoader,Y as decideNextTransition,j as decommissionMemberTrailStorage,yr as defaultDriftJournalDir,Wr as defaultRemediationForensicsDir,Gr as defaultRemediationJournalDir,t as deploy,d as deployOrganisation,Qe as derivePropertyChanges,Dt as deriveRemovalTemplate,$r as deriveRetainFlipTemplate,c as deriveStaleParameters,i as destroy,T as destroyOrganisation,Fr as detectStackDrift,Je as digestHead,P as emptyS3Bucket,ne as ensureEnforceSsl,nr as evaluateDestructionConsents,pr as executableRemediationVerbs,ue as extractAllAccountNames,m as extractConsumedSsmParameters,xr as fetchLastOperationEvents,et as findMarkedResourcesByOpId,Kr as findRemediationJournalByOpId,yt as findRemovalDeletionFailures,_t as findResourcesPresent,me as flattenAccountsToEnvironments,Br as formatDriftPreFlightBlock,Nt as formatDriftRepairOffer,bt as formatPinOutcomeDetail,E as formatQuarantineSuspectedMessage,mt as formatRecreateInFlightCures,D as formatRetainedBucketsMessage,Re as isAccountsConfig,O as isCleanableState,we as isDataLoss,Yt as isDeployPathBlockingStatus,ee as isEnforceSslStatement,Te as isOuOnlyAccountBucket,y as isQuarantineDetail,_ as isRetainedBucketsDetail,je as isStatefulResourceType,de as isStringArray,lr as legalRemediationVerbs,Mr as listActiveRemediationOps,Yr as listActiveRemediationOpsForContext,dr as loadDeployPlan,K as mergeReconciledProviderAccounts,ce as parseAccountsConfiguration,k as partitionAccounts,ge as partitionForRegion,ut as partitionPreFlightByRemediation,Ct as pinProbeCoverage,A as preEmptyStackBuckets,s as probeSecretsDrift,h as projectAccountRows,I as projectScalarSummary,rt as proveFlipMetadataOnly,gt as proveRemovalTargetsOnly,_r as readDriftSuspects,Vr as readRemediationJournal,tt as readRetainFlipState,G as reconcileProviderAccounts,V as reconcileTrailMigration,gr as recordDriftSuspects,ur as renderConsentVerdictLines,mr as renderDestructionTicketLines,Lt as renderPinReportLines,qe as renderPlanLines,We as renderPlanSummary,ke as resolveBuildArgs,Ee as resolveBuildSecretSessionProvider,Pe as resolveBuildSecrets,Ae as resolveSecretRefValue,n as restart,le as restoreAndReconcileQuarantinedBucket,ie as restoreBucketPolicy,tr as runApprovalGate,ir as runDestructionGate,kr as runDriftPreFlight,kt as runDriftRepairGate,ft as runForgetSurgery,Ue as runOpenNextBuild,he as runOrganisationSetup,Ut as runPinRemediation,At as runRecreatePreFlight,Tt as runRecreateSurgery,Ur as runRoute53RecordPreflight,Xe as signApprovalToken,St as snapshotPolicyForType,De as sourcedRefsFromBuildArgs,u as ssmParameterNameFromValueFrom,Jr as sweepExpiredRemediationJournals,dt as synthTemplateDeclaresResource,ae as synthesiseEnforceSslDocument,te as toResourcePolicyStatements,ze as toWirePlanChanges,$ as triageBucketPolicy,q as unlockBucket,X as unlockQueue,be as validateBuildGroup,Ze as verifyApprovalToken,ot as verifyRetainFlipDiff,Hr as writeRemediationJournal};
|
|
1
|
+
import{deploy as t}from"./deploy.js";import{destroy as i}from"./destroy.js";import{restart as n,probeSecretsDrift as s}from"./restart/restartApplication.js";import{computeSecretsDrift as p,deriveStaleParameters as c,extractConsumedSsmParameters as m,ssmParameterNameFromValueFrom as u}from"./restart/secretsDrift.js";import{deployOrganisation as d}from"./organisation/organisationDeploy.js";import{destroyOrganisation as T}from"./organisation/organisationDestroy.js";import{cleanupFailedStack as x,emptyS3Bucket as P,preEmptyStackBuckets as A,formatQuarantineSuspectedMessage as E,formatRetainedBucketsMessage as D,isQuarantineDetail as y,isRetainedBucketsDetail as _,PRE_EMPTY_TAG_KEYS as g,isCleanableState as O,SAFE_CLEANUP_STATES as v}from"./stackCleanup.js";import{partitionAccounts as k,buildRegionList as B,buildAccountRegionPairs as b,cascadeHomeRegion as C,cascadeOperationKey as L}from"./organisation/cascadeHelpers.js";import{projectScalarSummary as I,projectAccountRows as h}from"./organisation/cascadeSummary.js";import{reconcileProviderAccounts as G,mergeReconciledProviderAccounts as K}from"./organisation/reconcileProviderAccounts.js";import{decideNextTransition as Y,reconcileTrailMigration as V,ORG_TRAIL_BUCKET_OUTPUT_KEY as J,TRAIL_BUCKET_OUTPUT_KEY as H,TRAIL_KEY_ARN_OUTPUT_KEY as Q}from"./trailMigration/trailMigration.js";import{decommissionMemberTrailStorage as j}from"./trailMigration/memberTrailCleanup.js";import{unlockBucket as q}from"./unlock/unlockBucket.js";import{unlockQueue as X}from"./unlock/unlockQueue.js";import{triageBucketPolicy as $,isEnforceSslStatement as ee}from"./unlock/bucketPolicyTriage.js";import{toResourcePolicyStatements as te}from"./unlock/toResourcePolicyStatements.js";import{restoreBucketPolicy as ie,synthesiseEnforceSslDocument as ae,ensureEnforceSsl as ne}from"./unlock/restoreBucketPolicy.js";import{restoreAndReconcileQuarantinedBucket as le}from"./unlock/restoreAndReconcileQuarantinedBucket.js";import{parseAccountsConfiguration as ce,flattenAccountsToEnvironments as me,extractAllAccountNames as ue,accountsConfigToOUTree as fe,isStringArray as de,isAccountsConfig as Re,isOuOnlyAccountBucket as Te,OU_ONLY_ACCOUNT_BUCKETS as Se}from"./organisation/accountsConfig.js";import{resolveBuildSecrets as Pe,resolveSecretRefValue as Ae,resolveBuildSecretSessionProvider as Ee,sourcedRefsFromBuildArgs as De}from"./application/buildSecretResolver.js";import{buildBuildSecretSessionPolicy as _e,partitionForRegion as ge}from"./application/buildSecretSession.js";import{buildDeploySessionPolicy as ve}from"./application/deploySessionPolicy.js";import{resolveBuildArgs as ke}from"./application/buildArgResolver.js";import{validateBuildGroup as be}from"./application/buildGroupValidator.js";export*from"./domain/index.js";import{runOpenNextBuild as Ue}from"./application/openNextBuild.js";import{runOrganisationSetup as he,ORG_SETUP_PHASES as Ne}from"./organisation/organisationSetup.js";export*from"./builders/index.js";import{buildDeployPlan as Me,computeDeployPlan as Ye,computeAssemblyDigest as Ve,digestHead as Je,classifyImpact as He,derivePropertyChanges as Qe,isDataLoss as we,isStatefulResourceType as je,renderPlanSummary as We,renderPlanLines as qe,toWirePlanChanges as ze,signApprovalToken as Xe,verifyApprovalToken as Ze,DEFAULT_APPROVAL_TTL_MS as $e,APPROVAL_TOKEN_PATTERN as er}from"./application/plan/index.js";import{runApprovalGate as tr,approvalRefusalReason as or}from"./application/approvalGate.js";import{runDestructionGate as ar,buildDestructionTicket as nr,evaluateDestructionConsents as sr,computeTicketDigest as lr,legalRemediationVerbs as pr,executableRemediationVerbs as cr,advertisableRemediationVerbs as mr,renderDestructionTicketLines as ur,renderConsentVerdictLines as fr}from"./application/destructionGate.js";import{loadDeployPlan as Rr,createMemoisedPlanLoader as Tr}from"./application/plan/loadDeployPlan.js";import{classifyDriftFailure as xr,fetchLastOperationEvents as Pr}from"./drift/classifyDriftFailure.js";import{DriftProbe as Er}from"./drift/driftProbe.js";import{clearDriftSuspects as yr,defaultDriftJournalDir as _r,readDriftSuspects as gr,recordDriftSuspects as Or}from"./drift/driftSuspectJournal.js";import{detectStackDrift as Fr}from"./drift/detectStackDrift.js";import{runDriftPreFlight as Br,formatDriftPreFlightBlock as br,DRIFT_PREFLIGHT_TRIGGER_STATUSES as Cr,DRIFT_PREFLIGHT_BUDGET_MS as Lr}from"./drift/driftPreFlight.js";import{runRoute53RecordPreflight as Ir}from"./drift/route53RecordPreflight.js";import{archiveCompletedRemediationJournal as Nr,computeRemediationOpId as Gr,defaultRemediationJournalDir as Kr,findRemediationJournalByOpId as Mr,listActiveRemediationOps as Yr,listActiveRemediationOpsForContext as Vr,readRemediationJournal as Jr,sweepExpiredRemediationJournals as Hr,writeRemediationJournal as Qr,REMEDIATION_JOURNAL_RETENTION_DAYS as wr}from"./remediation/remediationJournal.js";import{captureRemediationForensics as Wr,defaultRemediationForensicsDir as qr}from"./remediation/forensicsCapture.js";import{applyRetainFlip as Xr,composeFlipCapabilities as Zr,computeTemplateDigest as $r,deriveRetainFlipTemplate as et,findMarkedResourcesByOpId as rt,proveFlipMetadataOnly as tt,readRetainFlipState as ot,verifyRetainFlipDiff as it,FORGET_MARKER_KEY as at,FORGET_FLIP_SPEC as nt,RECREATE_MARKER_KEY as st}from"./remediation/retainFlip.js";import{assessForgetResumability as pt,completeForgetAfterConverge as ct,completeForgetAfterDeploy as mt,formatRecreateInFlightCures as ut,partitionPreFlightByRemediation as ft,runForgetSurgery as dt,synthTemplateDeclaresResource as Rt}from"./remediation/forgetResource.js";import{runRecreateSurgery as St,snapshotPolicyForType as xt,SNAPSHOT_CAPABLE_RESOURCE_TYPES as Pt}from"./remediation/recreateResource.js";import{runRecreatePreFlight as Et}from"./remediation/recreatePreFlight.js";import{deriveRemovalTemplate as yt,findRemovalDeletionFailures as _t,findResourcesPresent as gt,proveRemovalTargetsOnly as Ot}from"./remediation/removalUpdate.js";import{advertisableDriftVerbs as Ft,buildDriftRepairTicket as kt,runDriftRepairGate as Bt}from"./remediation/driftRepairGate.js";import{formatPinOutcomeDetail as Ct,pinProbeCoverage as Lt,renderPinReportLines as Ut,runPinRemediation as It}from"./remediation/pinRemediation.js";import{composePostFailureRepairOffer as Nt,formatDriftRepairOffer as Gt,DriftRepairAvailableError as Kt}from"./remediation/postFailureRepairOffer.js";import{checkDeployPathStackAvailability as Yt,isDeployPathBlockingStatus as Vt,StackUnavailableError as Jt}from"./activeDeploymentGuard.js";import{assertLeaseBeforeStack as Qt,LeaseDeniedError as wt}from"./application/leaseGate.js";export{er as APPROVAL_TOKEN_PATTERN,$e as DEFAULT_APPROVAL_TTL_MS,Lr as DRIFT_PREFLIGHT_BUDGET_MS,Cr as DRIFT_PREFLIGHT_TRIGGER_STATUSES,Er as DriftProbe,Kt as DriftRepairAvailableError,nt as FORGET_FLIP_SPEC,at as FORGET_MARKER_KEY,wt as LeaseDeniedError,Ne as ORG_SETUP_PHASES,J as ORG_TRAIL_BUCKET_OUTPUT_KEY,Se as OU_ONLY_ACCOUNT_BUCKETS,g as PRE_EMPTY_TAG_KEYS,st as RECREATE_MARKER_KEY,wr as REMEDIATION_JOURNAL_RETENTION_DAYS,v as SAFE_CLEANUP_STATES,Pt as SNAPSHOT_CAPABLE_RESOURCE_TYPES,Jt as StackUnavailableError,H as TRAIL_BUCKET_OUTPUT_KEY,Q as TRAIL_KEY_ARN_OUTPUT_KEY,fe as accountsConfigToOUTree,Ft as advertisableDriftVerbs,mr as advertisableRemediationVerbs,Xr as applyRetainFlip,or as approvalRefusalReason,Nr as archiveCompletedRemediationJournal,Qt as assertLeaseBeforeStack,pt as assessForgetResumability,b as buildAccountRegionPairs,_e as buildBuildSecretSessionPolicy,Me as buildDeployPlan,ve as buildDeploySessionPolicy,nr as buildDestructionTicket,kt as buildDriftRepairTicket,B as buildRegionList,Wr as captureRemediationForensics,C as cascadeHomeRegion,L as cascadeOperationKey,Yt as checkDeployPathStackAvailability,xr as classifyDriftFailure,He as classifyImpact,x as cleanupFailedStack,yr as clearDriftSuspects,ct as completeForgetAfterConverge,mt as completeForgetAfterDeploy,Zr as composeFlipCapabilities,Nt as composePostFailureRepairOffer,Ve as computeAssemblyDigest,Ye as computeDeployPlan,Gr as computeRemediationOpId,p as computeSecretsDrift,$r as computeTemplateDigest,lr as computeTicketDigest,Tr as createMemoisedPlanLoader,Y as decideNextTransition,j as decommissionMemberTrailStorage,_r as defaultDriftJournalDir,qr as defaultRemediationForensicsDir,Kr as defaultRemediationJournalDir,t as deploy,d as deployOrganisation,Qe as derivePropertyChanges,yt as deriveRemovalTemplate,et as deriveRetainFlipTemplate,c as deriveStaleParameters,i as destroy,T as destroyOrganisation,Fr as detectStackDrift,Je as digestHead,P as emptyS3Bucket,ne as ensureEnforceSsl,sr as evaluateDestructionConsents,cr as executableRemediationVerbs,ue as extractAllAccountNames,m as extractConsumedSsmParameters,Pr as fetchLastOperationEvents,rt as findMarkedResourcesByOpId,Mr as findRemediationJournalByOpId,_t as findRemovalDeletionFailures,gt as findResourcesPresent,me as flattenAccountsToEnvironments,br as formatDriftPreFlightBlock,Gt as formatDriftRepairOffer,Ct as formatPinOutcomeDetail,E as formatQuarantineSuspectedMessage,ut as formatRecreateInFlightCures,D as formatRetainedBucketsMessage,Re as isAccountsConfig,O as isCleanableState,we as isDataLoss,Vt as isDeployPathBlockingStatus,ee as isEnforceSslStatement,Te as isOuOnlyAccountBucket,y as isQuarantineDetail,_ as isRetainedBucketsDetail,je as isStatefulResourceType,de as isStringArray,pr as legalRemediationVerbs,Yr as listActiveRemediationOps,Vr as listActiveRemediationOpsForContext,Rr as loadDeployPlan,K as mergeReconciledProviderAccounts,ce as parseAccountsConfiguration,k as partitionAccounts,ge as partitionForRegion,ft as partitionPreFlightByRemediation,Lt as pinProbeCoverage,A as preEmptyStackBuckets,s as probeSecretsDrift,h as projectAccountRows,I as projectScalarSummary,tt as proveFlipMetadataOnly,Ot as proveRemovalTargetsOnly,gr as readDriftSuspects,Jr as readRemediationJournal,ot as readRetainFlipState,G as reconcileProviderAccounts,V as reconcileTrailMigration,Or as recordDriftSuspects,fr as renderConsentVerdictLines,ur as renderDestructionTicketLines,Ut as renderPinReportLines,qe as renderPlanLines,We as renderPlanSummary,ke as resolveBuildArgs,Ee as resolveBuildSecretSessionProvider,Pe as resolveBuildSecrets,Ae as resolveSecretRefValue,n as restart,le as restoreAndReconcileQuarantinedBucket,ie as restoreBucketPolicy,tr as runApprovalGate,ar as runDestructionGate,Br as runDriftPreFlight,Bt as runDriftRepairGate,dt as runForgetSurgery,Ue as runOpenNextBuild,he as runOrganisationSetup,It as runPinRemediation,Et as runRecreatePreFlight,St as runRecreateSurgery,Ir as runRoute53RecordPreflight,Xe as signApprovalToken,xt as snapshotPolicyForType,De as sourcedRefsFromBuildArgs,u as ssmParameterNameFromValueFrom,Hr as sweepExpiredRemediationJournals,Rt as synthTemplateDeclaresResource,ae as synthesiseEnforceSslDocument,te as toResourcePolicyStatements,ze as toWirePlanChanges,$ as triageBucketPolicy,q as unlockBucket,X as unlockQueue,be as validateBuildGroup,Ze as verifyApprovalToken,it as verifyRetainFlipDiff,Qr as writeRemediationJournal};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type Result } from "@fjall/generator";
|
|
2
|
+
/**
|
|
3
|
+
* Domain component deploy state — the domain twin of the application state
|
|
4
|
+
* IO in FjallState.ts, sharing the SAME `.fjall-state.json` filename inside
|
|
5
|
+
* the domain component directory. `templateHashes` stays `{}` for domains;
|
|
6
|
+
* `domain.directoryHash` is the deliberate cheap change signal (D11).
|
|
7
|
+
*
|
|
8
|
+
* ORACLE PRINCIPLE (post-d60d1b6ed): per-machine state is ONLY
|
|
9
|
+
* (i) a change-detection cache (directoryHash vs current content), and
|
|
10
|
+
* (ii) an offline fast path (skip an AWS round trip when a record exists),
|
|
11
|
+
* NEVER a deployment oracle. Absence proves nothing (fresh clone, deploy ran
|
|
12
|
+
* on another machine) and presence proves nothing durable (the stack may
|
|
13
|
+
* have been destroyed elsewhere). Consumers that need the truth must ask
|
|
14
|
+
* CloudFormation (e.g. DomainService.readDomainStackOutputs). Deploys write
|
|
15
|
+
* the record; `fjall domain destroy` deletes it — parity with the
|
|
16
|
+
* application lifecycle (applicationDestroy deletes the app state file).
|
|
17
|
+
*
|
|
18
|
+
* Migration: domains previously wrote `.deploy-state.json`. Reads prefer the
|
|
19
|
+
* new file, fall back to the legacy one, and when both exist (mixed CLI
|
|
20
|
+
* versions on one machine) pick the newer `lastDeployedAt`. A successful
|
|
21
|
+
* write emits the new file and best-effort unlinks the legacy pair.
|
|
22
|
+
* Old-CLI-reads-new-file degrades safely: the legacy strict schema rejects
|
|
23
|
+
* the new shape, reads as "no record", and the old CLI redeploys.
|
|
24
|
+
*/
|
|
25
|
+
/** Legacy pre-unification state filename (kept readable for one release). */
|
|
26
|
+
export declare const LEGACY_DOMAIN_STATE_FILENAME = ".deploy-state.json";
|
|
27
|
+
/**
|
|
28
|
+
* Flat read/write model shared by both file generations — identical to the
|
|
29
|
+
* legacy `.deploy-state.json` document so consumers see one shape regardless
|
|
30
|
+
* of which file backed the read.
|
|
31
|
+
*/
|
|
32
|
+
export interface DomainDeployState {
|
|
33
|
+
readonly lastDeployedAt: string;
|
|
34
|
+
readonly cloudformationStackName: string;
|
|
35
|
+
readonly hostedZoneId?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Content hash of the domain component directory at deploy time (D11
|
|
38
|
+
* change detection). Absent on states written by older CLIs or when
|
|
39
|
+
* hashing failed — treated as "cannot prove unchanged", so the cascade
|
|
40
|
+
* re-deploys.
|
|
41
|
+
*/
|
|
42
|
+
readonly directoryHash?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Read the domain deploy state from a component directory, preferring the
|
|
46
|
+
* unified `.fjall-state.json` and falling back to the legacy
|
|
47
|
+
* `.deploy-state.json`. When both carry a record (mixed CLI versions on one
|
|
48
|
+
* machine during rollout) the newer `lastDeployedAt` wins; unparseable
|
|
49
|
+
* timestamps resolve towards the new file.
|
|
50
|
+
*/
|
|
51
|
+
export declare function readDomainState(componentPath: string): Result<DomainDeployState | undefined, Error>;
|
|
52
|
+
/**
|
|
53
|
+
* Write the domain deploy state atomically (temp file + rename) as a unified
|
|
54
|
+
* `.fjall-state.json`, then best-effort unlink the legacy pair — the write
|
|
55
|
+
* IS the migration step.
|
|
56
|
+
*/
|
|
57
|
+
export declare function writeDomainState(componentPath: string, state: DomainDeployState): Result<void, Error>;
|
|
58
|
+
/**
|
|
59
|
+
* Deterministic sha256 over a domain component directory: sorted relative
|
|
60
|
+
* paths and file contents, NUL-delimited. The simple honest change signal
|
|
61
|
+
* for D11 — a byte changes anywhere in the component, the hash changes.
|
|
62
|
+
*/
|
|
63
|
+
export declare function hashDomainDirectory(componentPath: string): Result<string, Error>;
|
|
64
|
+
/**
|
|
65
|
+
* The one post-deploy state writer: hash the component directory, stamp the
|
|
66
|
+
* deploy time, derive the stack name (D2 shared derivation), write. A hash
|
|
67
|
+
* failure is non-fatal — the state is written without it and D11 detection
|
|
68
|
+
* re-deploys. Callers own only their warning plumbing on failure.
|
|
69
|
+
*/
|
|
70
|
+
export declare function recordDomainDeployState(params: {
|
|
71
|
+
readonly domainName: string;
|
|
72
|
+
readonly componentPath: string;
|
|
73
|
+
}): Result<DomainDeployState, Error>;
|
|
74
|
+
/**
|
|
75
|
+
* Delete the domain deploy state (both file generations and their temp
|
|
76
|
+
* files). Called by `fjall domain destroy` AFTER confirmed stack deletion so
|
|
77
|
+
* the per-machine cache stops claiming a destroyed deploy. Absence is fine;
|
|
78
|
+
* any other unlink failure is reported so the caller can warn — it must
|
|
79
|
+
* never fail the destroy itself (later reads degrade to the oracle/redeploy
|
|
80
|
+
* anyway).
|
|
81
|
+
*/
|
|
82
|
+
export declare function deleteDomainState(componentPath: string): Result<void, Error>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var g=Object.defineProperty;var a=(t,e)=>g(t,"name",{value:e,configurable:!0});import{existsSync as p,mkdirSync as E,readdirSync as N,readFileSync as h,renameSync as H,unlinkSync as S,writeFileSync as I}from"fs";import{createHash as A}from"crypto";import{dirname as k,join as i}from"path";import{z as u}from"zod";import{success as c,failure as f}from"@fjall/generator";import{getDomainStackName as w,getErrorMessage as F,normaliseError as m}from"@fjall/util";import{FjallStateFileSchema as x,getStateFilePath as y}from"./FjallState.js";const l=".deploy-state.json",_=u.object({lastDeployedAt:u.string(),cloudformationStackName:u.string(),hostedZoneId:u.string().optional(),directoryHash:u.string().optional()}).strict();function D(t,e){if(!p(t))return c(void 0);let n;try{n=h(t,"utf8")}catch(s){return f(m(s))}let r;try{r=JSON.parse(n)}catch{return c(void 0)}return c(e(r))}a(D,"readStateDocument");function $(t){const e=x.safeParse(t);if(!e.success)return;const{domain:n,lastDeployedAt:r}=e.data;if(!(n===void 0||r===void 0))return{lastDeployedAt:r,cloudformationStackName:n.cloudformationStackName,...n.hostedZoneId!==void 0?{hostedZoneId:n.hostedZoneId}:{},...n.directoryHash!==void 0?{directoryHash:n.directoryHash}:{}}}a($,"parseCurrentDocument");function j(t){const e=_.safeParse(t);return e.success?e.data:void 0}a(j,"parseLegacyDocument");function P(t){const e=D(y(t),$);if(!e.success)return e;const n=D(i(t,l),j);if(!n.success)return e.data!==void 0?e:n;if(e.data===void 0)return n;if(n.data===void 0)return e;const r=Date.parse(e.data.lastDeployedAt),s=Date.parse(n.data.lastDeployedAt);return Number.isFinite(s)&&(!Number.isFinite(r)||s>r)?n:e}a(P,"readDomainState");function L(t){for(const e of[l,`${l}.tmp`])try{S(i(t,e))}catch{}}a(L,"unlinkLegacyStateFiles");function T(t,e){const n=y(t),r=`${n}.tmp`,s={version:1,lastDeployedAt:e.lastDeployedAt,templateHashes:{},domain:{cloudformationStackName:e.cloudformationStackName,...e.hostedZoneId!==void 0?{hostedZoneId:e.hostedZoneId}:{},...e.directoryHash!==void 0?{directoryHash:e.directoryHash}:{}}};try{E(k(n),{recursive:!0}),I(r,JSON.stringify(s,null,2)+`
|
|
2
|
+
`,"utf8"),H(r,n)}catch(o){return f(m(o))}return L(t),c(void 0)}a(T,"writeDomainState");const Z=new Set(["node_modules","cdk.out",".git"]),b=[".fjall-state",".deploy-state"];function C(t){return Z.has(t)||b.some(e=>t.startsWith(e))}a(C,"isHashExcluded");function O(t){if(!p(t))return f(new Error(`domain change detection: directory not found at ${t}`));const e=A("sha256"),n=a(r=>{const s=N(i(t,r),{withFileTypes:!0}).filter(o=>!C(o.name)).sort((o,d)=>o.name.localeCompare(d.name));for(const o of s){const d=r===""?o.name:i(r,o.name);o.isDirectory()?n(d):o.isFile()&&(e.update(d),e.update("\0"),e.update(h(i(t,d))),e.update("\0"))}},"walk");try{n("")}catch(r){return f(m(r))}return c(e.digest("hex"))}a(O,"hashDomainDirectory");function W(t){const e=O(t.componentPath),n={lastDeployedAt:new Date().toISOString(),cloudformationStackName:w(t.domainName),...e.success?{directoryHash:e.data}:{}},r=T(t.componentPath,n);return r.success?c(n):r}a(W,"recordDomainDeployState");function Y(t){const e=y(t),n=[e,`${e}.tmp`,i(t,l),i(t,`${l}.tmp`)],r=[];for(const s of n)try{S(s)}catch(o){(typeof o=="object"&&o!==null&&"code"in o?o.code:void 0)!=="ENOENT"&&r.push(`${s}: ${F(o)}`)}return r.length>0?f(new Error(`could not delete domain deploy state: ${r.join("; ")}`)):c(void 0)}a(Y,"deleteDomainState");export{l as LEGACY_DOMAIN_STATE_FILENAME,Y as deleteDomainState,O as hashDomainDirectory,P as readDomainState,W as recordDomainDeployState,T as writeDomainState};
|
|
@@ -6,7 +6,12 @@ declare const TemplateHashEntrySchema: z.ZodObject<{
|
|
|
6
6
|
}, z.core.$strict>;
|
|
7
7
|
/**
|
|
8
8
|
* State file schema for hash-based change detection.
|
|
9
|
-
* Location: fjall/{appName}/.fjall-state.json
|
|
9
|
+
* Location: fjall/{appName}/.fjall-state.json for applications,
|
|
10
|
+
* fjall/domains/{domainName}/.fjall-state.json for domain components.
|
|
11
|
+
*
|
|
12
|
+
* `domain` is additive-optional on version 1: new CLIs read old app files
|
|
13
|
+
* unchanged, while old CLIs reading a domain-shaped file fail their strict
|
|
14
|
+
* legacy parse and safely degrade to "no record" (redeploy).
|
|
10
15
|
*/
|
|
11
16
|
export declare const FjallStateFileSchema: z.ZodObject<{
|
|
12
17
|
version: z.ZodLiteral<1>;
|
|
@@ -16,6 +21,11 @@ export declare const FjallStateFileSchema: z.ZodObject<{
|
|
|
16
21
|
deployedAt: z.ZodString;
|
|
17
22
|
stackStatus: z.ZodOptional<z.ZodString>;
|
|
18
23
|
}, z.core.$strict>>;
|
|
24
|
+
domain: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
cloudformationStackName: z.ZodString;
|
|
26
|
+
hostedZoneId: z.ZodOptional<z.ZodString>;
|
|
27
|
+
directoryHash: z.ZodOptional<z.ZodString>;
|
|
28
|
+
}, z.core.$strict>>;
|
|
19
29
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
20
30
|
}, z.core.$strict>;
|
|
21
31
|
export type TemplateHashEntry = z.infer<typeof TemplateHashEntrySchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var d=Object.defineProperty;var n=(t,e)=>d(t,"name",{value:e,configurable:!0});import{z as a}from"zod";import{randomBytes as f}from"crypto";import{readFile as m,writeFile as S,unlink as c,rename as g,mkdir as h}from"fs/promises";import{dirname as y,join as p}from"path";import{fileExists as F}from"@fjall/util/fsHelpers";import{logger as i}from"@fjall/util/logger";import{getErrorMessage as l,maskSensitiveOutput as w}from"@fjall/util";const x=a.object({hash:a.string(),deployedAt:a.string(),stackStatus:a.string().optional()}).strict(),j=a.object({cloudformationStackName:a.string(),hostedZoneId:a.string().optional(),directoryHash:a.string().optional()}).strict(),E=a.object({version:a.literal(1),lastDeployedAt:a.string().optional(),templateHashes:a.record(a.string(),x),domain:j.optional(),metadata:a.record(a.string(),a.unknown()).optional()}).strict(),A=".fjall-state.json";function s(t){return p(t,A)}n(s,"getStateFilePath");function H(t){return t.replace(/-/g,"")}n(H,"regionSuffix");function J(t,e,r){return p(t,`.fjall-state.cascade-${e}-${H(r)}.json`)}n(J,"getCascadeStateFilePath");async function b(t){if(!await F(t))return null;try{const e=await m(t,"utf-8"),r=JSON.parse(e),o=E.safeParse(r);return o.success?o.data:null}catch(e){return i.debug("FjallState","Failed to read state file",{path:t,error:l(e)}),null}}n(b,"readStateFileAt");async function k(t,e){const r=`${t}.${Date.now()}-${f(4).toString("hex")}.tmp`;await h(y(t),{recursive:!0});try{await S(r,JSON.stringify(e,null,2),"utf-8"),await g(r,t)}catch(o){try{await c(r)}catch(u){i.debug("FjallState","Temp file cleanup failed (non-fatal)",{path:r,error:l(u)})}throw o}}n(k,"writeStateFileAt");async function M(t){return b(s(t))}n(M,"readStateFile");async function _(t,e){return k(s(t),e)}n(_,"writeStateFile");function z(){return{version:1,templateHashes:{}}}n(z,"createEmptyState");async function C(t){const e=s(t);try{await c(e)}catch(r){(typeof r=="object"&&r!==null&&"code"in r?r.code:void 0)!=="ENOENT"&&i.warn("FjallState","Failed to delete state file",{path:e,error:w(l(r))})}}n(C,"deleteStateFile");function L(t,e,r,o){return{...t,lastDeployedAt:new Date().toISOString(),templateHashes:{...t.templateHashes,[e]:{hash:r,deployedAt:new Date().toISOString(),...o!==void 0&&{stackStatus:o}}}}}n(L,"updateTemplateHash");export{E as FjallStateFileSchema,z as createEmptyState,C as deleteStateFile,J as getCascadeStateFilePath,s as getStateFilePath,M as readStateFile,b as readStateFileAt,H as regionSuffix,L as updateTemplateHash,_ as writeStateFile,k as writeStateFileAt};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/deploy-core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Shared deployment engine for Fjall — used by CLI and webapp worker",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@aws-cdk/cloudformation-diff": "2.187.1",
|
|
68
68
|
"@aws-sdk/client-account": "^3.1067.0",
|
|
69
|
+
"@aws-sdk/client-acm": "^3.1038.0",
|
|
69
70
|
"@aws-sdk/client-backup": "^3.1038.0",
|
|
70
71
|
"@aws-sdk/client-cloudformation": "^3.1038.0",
|
|
71
72
|
"@aws-sdk/client-cloudtrail": "^3.1065.0",
|
|
@@ -87,8 +88,8 @@
|
|
|
87
88
|
"@aws-sdk/client-ssm": "^3.1038.0",
|
|
88
89
|
"@aws-sdk/client-sso-admin": "^3.1038.0",
|
|
89
90
|
"@aws-sdk/client-sts": "^3.1038.0",
|
|
90
|
-
"@fjall/generator": "^3.
|
|
91
|
-
"@fjall/util": "^3.
|
|
91
|
+
"@fjall/generator": "^3.6.0",
|
|
92
|
+
"@fjall/util": "^3.6.0",
|
|
92
93
|
"@smithy/node-http-handler": "^4.6.1",
|
|
93
94
|
"aws-cdk": "^2.1128.1",
|
|
94
95
|
"tsx": "^4.21.0",
|
|
@@ -99,5 +100,5 @@
|
|
|
99
100
|
"typescript": "^6.0.3",
|
|
100
101
|
"vitest": "^4.1.5"
|
|
101
102
|
},
|
|
102
|
-
"gitHead": "
|
|
103
|
+
"gitHead": "10366db602d7e80669e22825a52071a47e05c3b7"
|
|
103
104
|
}
|