@fjall/deploy-core 2.21.0 → 2.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/.minified +1 -1
  2. package/dist/src/aws/AwsProvider.d.ts +9 -0
  3. package/dist/src/aws/SimpleAwsProvider.d.ts +9 -2
  4. package/dist/src/aws/SimpleAwsProvider.js +1 -1
  5. package/dist/src/aws/index.d.ts +2 -0
  6. package/dist/src/aws/index.js +1 -1
  7. package/dist/src/aws/regions/regionOptStatus.d.ts +26 -0
  8. package/dist/src/aws/regions/regionOptStatus.js +1 -0
  9. package/dist/src/aws/utils/cloudformationEventHelpers.js +1 -1
  10. package/dist/src/aws/utils/cloudformationEventTypes.d.ts +6 -0
  11. package/dist/src/aws/utils/cloudformationEvents.d.ts +1 -0
  12. package/dist/src/aws/utils/cloudformationEvents.js +1 -1
  13. package/dist/src/index.d.ts +10 -2
  14. package/dist/src/index.js +1 -1
  15. package/dist/src/orchestration/application/applicationDeploy.js +1 -1
  16. package/dist/src/orchestration/application/applicationDeployHelpers.js +2 -2
  17. package/dist/src/orchestration/application/approvalGate.d.ts +44 -0
  18. package/dist/src/orchestration/application/approvalGate.js +1 -0
  19. package/dist/src/orchestration/application/buildArgResolver.d.ts +72 -0
  20. package/dist/src/orchestration/application/buildArgResolver.js +1 -0
  21. package/dist/src/orchestration/application/buildGroupValidator.d.ts +64 -0
  22. package/dist/src/orchestration/application/buildGroupValidator.js +1 -0
  23. package/dist/src/orchestration/application/buildSecretResolver.d.ts +57 -0
  24. package/dist/src/orchestration/application/buildSecretResolver.js +1 -0
  25. package/dist/src/orchestration/application/buildSecretSession.d.ts +40 -0
  26. package/dist/src/orchestration/application/buildSecretSession.js +1 -0
  27. package/dist/src/orchestration/application/codeOnlyDeploy.js +1 -1
  28. package/dist/src/orchestration/application/dockerBuildHelper.js +1 -1
  29. package/dist/src/orchestration/application/plan/approvalToken.d.ts +40 -0
  30. package/dist/src/orchestration/application/plan/approvalToken.js +1 -0
  31. package/dist/src/orchestration/application/plan/assemblyDigest.d.ts +21 -0
  32. package/dist/src/orchestration/application/plan/assemblyDigest.js +2 -0
  33. package/dist/src/orchestration/application/plan/buildDeployPlan.d.ts +14 -0
  34. package/dist/src/orchestration/application/plan/buildDeployPlan.js +1 -0
  35. package/dist/src/orchestration/application/plan/classify.d.ts +37 -0
  36. package/dist/src/orchestration/application/plan/classify.js +1 -0
  37. package/dist/src/orchestration/application/plan/computeDeployPlan.d.ts +24 -0
  38. package/dist/src/orchestration/application/plan/computeDeployPlan.js +1 -0
  39. package/dist/src/orchestration/application/plan/index.d.ts +8 -0
  40. package/dist/src/orchestration/application/plan/index.js +1 -0
  41. package/dist/src/orchestration/application/plan/renderDeployPlan.d.ts +18 -0
  42. package/dist/src/orchestration/application/plan/renderDeployPlan.js +1 -0
  43. package/dist/src/orchestration/application/plan/types.d.ts +54 -0
  44. package/dist/src/orchestration/application/plan/types.js +0 -0
  45. package/dist/src/orchestration/deploy.js +1 -1
  46. package/dist/src/orchestration/destroy.js +1 -1
  47. package/dist/src/orchestration/dockerBuildParamsKeys.d.ts +2 -0
  48. package/dist/src/orchestration/dockerBuildParamsKeys.js +1 -0
  49. package/dist/src/orchestration/dockerInterface.d.ts +34 -0
  50. package/dist/src/orchestration/index.d.ts +8 -1
  51. package/dist/src/orchestration/index.js +1 -1
  52. package/dist/src/orchestration/serviceFactory.d.ts +7 -0
  53. package/dist/src/orchestration/serviceFactory.js +1 -1
  54. package/dist/src/orchestration/stepLifecycle.d.ts +7 -1
  55. package/dist/src/orchestration/stepLifecycle.js +1 -1
  56. package/dist/src/services/infrastructure/CdkEventMonitoring.d.ts +3 -0
  57. package/dist/src/services/infrastructure/CdkEventMonitoring.js +1 -1
  58. package/dist/src/services/infrastructure/CdkProcessManager.d.ts +10 -1
  59. package/dist/src/services/infrastructure/CdkProcessManager.js +3 -3
  60. package/dist/src/services/infrastructure/CdkService.d.ts +1 -0
  61. package/dist/src/services/infrastructure/CdkService.js +2 -2
  62. package/dist/src/services/infrastructure/CdkServiceTypes.d.ts +15 -0
  63. package/dist/src/services/infrastructure/CloudFormationService.d.ts +11 -0
  64. package/dist/src/services/infrastructure/CloudFormationService.js +1 -1
  65. package/dist/src/services/infrastructure/cancelInFlightStack.d.ts +22 -0
  66. package/dist/src/services/infrastructure/cancelInFlightStack.js +3 -0
  67. package/dist/src/types/approval.d.ts +53 -0
  68. package/dist/src/types/approval.js +0 -0
  69. package/dist/src/types/callbackKeys.d.ts +1 -1
  70. package/dist/src/types/callbackKeys.js +1 -1
  71. package/dist/src/types/callbacks.d.ts +18 -4
  72. package/dist/src/types/config/entitlements.d.ts +7 -0
  73. package/dist/src/types/credentials.d.ts +14 -0
  74. package/dist/src/types/deployEmitter.d.ts +85 -0
  75. package/dist/src/types/deployEmitter.js +1 -0
  76. package/dist/src/types/deployEvent.d.ts +907 -0
  77. package/dist/src/types/deployEvent.js +1 -0
  78. package/dist/src/types/deployEventParse.d.ts +52 -0
  79. package/dist/src/types/deployEventParse.js +1 -0
  80. package/dist/src/types/deployEventTypeGuards.d.ts +10 -0
  81. package/dist/src/types/deployEventTypeGuards.js +1 -0
  82. package/dist/src/types/index.d.ts +7 -2
  83. package/dist/src/types/index.js +1 -1
  84. package/dist/src/types/params.d.ts +112 -1
  85. package/package.json +8 -4
@@ -0,0 +1 @@
1
+ import{z as e}from"zod";import{CASCADE_PHASES as h,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as E}from"./deploymentEventSchema.js";import{TRAIL_MIGRATION_PHASES as A,TRAIL_MIGRATION_STATUSES as C}from"./events.js";import{TRAIL_LIFECYCLE_STATES as p}from"@fjall/util/config";const Ue="fjall.deploy/1.1",Ve=1,Ye=1,_=["fjall.deploy/1.0","fjall.deploy/1.1"],a=256,o=256,s=2048,i=2048,n=4096,j=2048,m=8192,r=2048,g=4096,T=["completed","skipped","error","cancelled"],y=["info","debug","warn"],D=["emptying-bucket","deleting-stack","waiting","complete","error","quarantine-suspected","retained-buckets"],v=["bootstrap","synth","deploy","destroy"],P=["success","failure","cancelled","no-changes","rejected"],R=["detect","synth","hash","validate"],c=["started","completed"],l=["docker","buildpush","opennext"],d=["succeeded","skipped","failed"],N=["create","update","replace","delete","read","no-op"],K=["will","may","conditional","none"],O=["destructive","cost","policy"],f=["approved","rejected","expired","superseded"],u=e.object({create:e.number().int().nonnegative(),update:e.number().int().nonnegative(),replace:e.number().int().nonnegative(),delete:e.number().int().nonnegative(),read:e.number().int().nonnegative(),"no-op":e.number().int().nonnegative()}).strict(),L={create:!0,update:!0,replace:!0,delete:!0,read:!0,"no-op":!0},t={contract:e.enum(_),deploymentId:e.string().min(1).max(a),seq:e.number().int().nonnegative(),time:e.string().datetime()},x=e.object({index:e.number().int().nonnegative(),total:e.number().int().positive()}).strict(),b=e.object({id:e.string().max(a),name:e.string().max(o)}).strict(),k=e.object({logicalId:e.string().max(a),resourceType:e.string().max(a),status:e.string().max(64),displayName:e.string().max(o).optional(),category:e.enum(E).optional(),group:e.string().max(128).optional(),constructPath:e.string().max(512).optional(),statusReason:e.string().max(i).optional(),physicalId:e.string().max(r).optional(),expectedDurationSeconds:e.number().nonnegative().optional()}).strict(),M=e.object({pattern:e.string().max(128).nullable(),hasDockerfile:e.boolean(),hasDifferences:e.boolean(),resources:e.object({hasNetwork:e.boolean(),hasCompute:e.boolean(),hasDatabase:e.boolean(),hasStorage:e.boolean(),hasMessaging:e.boolean(),hasCdn:e.boolean()}).strict(),requiredSecrets:e.array(e.string().max(512)).max(100).optional()}).strict(),I=e.object({path:e.string().max(512),forcesReplacement:e.boolean()}).strict(),U=e.object({address:e.string().max(512),resourceType:e.string().max(a),action:e.enum(N),stack:e.string().max(a).optional(),replacementMode:e.enum(K).optional(),dataLoss:e.boolean().optional(),propertyChanges:e.array(I).max(100).optional()}).strict(),S=e.object({accountId:e.string().max(a),error:e.string().max(n)}).strict(),V=e.object({platformDeployed:e.boolean(),platformSkipped:e.boolean(),platformFailed:e.boolean(),domainsDeployed:e.boolean(),accountsDeployed:e.number().int().nonnegative(),accountsSkipped:e.number().int().nonnegative(),accountsFailed:e.number().int().nonnegative(),errors:e.array(S).max(1e3)}).strict(),Y=e.object({accountId:e.string().max(a),accountName:e.string().max(o),region:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),B=e.object({accountId:e.string().max(a),result:e.enum(d),durationMs:e.number().nonnegative(),error:e.string().max(n).optional()}).strict(),G=e.object({members:e.array(Y).max(1e3),platform:B.optional(),domainsDeployed:e.boolean(),errors:e.array(S).max(1e3),totalDurationMs:e.number().nonnegative()}).strict(),X=e.object({bucketName:e.string().max(o),accountId:e.string().max(a).optional()}).strict(),w=e.object({retainedBuckets:e.array(e.string().max(o)).max(1e3),message:e.string().max(s)}).strict(),H=e.union([X,w]),q=e.object({stack:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional()}).strict(),F=e.object({accountId:e.string().max(a),region:e.string().max(a),profileName:e.string().max(o).optional()}).strict(),z=e.object({...t,progressKind:e.literal("step.started"),step:b,progress:x.optional()}).strict(),J=e.object({...t,progressKind:e.literal("step.completed"),step:b,status:e.enum(T),progress:x.optional(),errorMessage:e.string().max(n).optional()}).strict(),Q=e.object({...t,progressKind:e.literal("log"),level:e.enum(y),message:e.string().max(s)}).strict(),W=e.object({...t,progressKind:e.literal("output"),chunk:e.string().max(m)}).strict(),Z=e.object({...t,progressKind:e.literal("resource"),resource:k,scope:e.object({stack:e.string().max(a).optional(),operationKey:e.string().max(a).optional(),region:e.string().max(a).optional()}).strict().optional()}).strict(),$=e.object({...t,progressKind:e.literal("phase.parallel"),status:e.enum(c),stacks:e.array(e.string().max(a)).max(50),description:e.string().max(o).optional(),results:e.array(q).max(50).optional()}).strict(),ee=e.object({...t,progressKind:e.literal("build.started"),builder:e.enum(l),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),ecrRepositoryUri:e.string().max(r).optional()}).strict(),te=e.object({...t,progressKind:e.literal("build.progress"),builder:e.enum(l),message:e.string().max(s),serviceName:e.string().max(o).optional(),percentage:e.number().optional(),layerId:e.string().max(a).optional(),status:e.string().max(64).optional()}).strict(),ae=e.object({...t,progressKind:e.literal("build.completed"),builder:e.enum(l),success:e.boolean(),serviceName:e.string().max(o).optional(),imageTag:e.string().max(o).optional(),imageDigest:e.string().max(a).optional(),imageUri:e.string().max(g).optional(),ecrRepositoryArn:e.string().max(r).optional(),durationMs:e.number().nonnegative().optional(),error:e.string().max(n).optional()}).strict(),oe=e.object({...t,progressKind:e.literal("taskdef.registered"),serviceName:e.string().max(o),taskDefinitionArn:e.string().max(r),previousTaskDefinitionArn:e.string().max(r),revision:e.number().int().nonnegative(),family:e.string().max(o),imageDigest:e.string().max(a).optional()}).strict(),re=e.object({...t,progressKind:e.literal("ecs.update"),status:e.string().max(64),service:e.string().max(o).optional()}).strict(),se=e.object({...t,progressKind:e.literal("ecs.progress"),message:e.string().max(s),percentage:e.number().optional()}).strict(),ne=e.object({...t,progressKind:e.literal("ecs.completed"),serviceName:e.string().max(o),serviceArn:e.string().max(r),success:e.boolean(),taskDefinitionArn:e.string().max(r),durationMs:e.number().nonnegative(),reason:e.string().max(i).optional(),finalRunningCount:e.number().int().nonnegative().optional(),finalDesiredCount:e.number().int().nonnegative().optional()}).strict(),ie=e.object({...t,progressKind:e.literal("migrations.started"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),imageDigest:e.string().max(a)}).strict(),ce=e.object({...t,progressKind:e.literal("migrations.completed"),family:e.string().max(o),taskDefinitionArn:e.string().max(r),success:e.boolean(),durationMs:e.number().nonnegative(),exitCode:e.number().int().optional(),reason:e.string().max(i).optional()}).strict(),le=e.object({...t,progressKind:e.literal("cdk.bootstrap"),status:e.string().max(s)}).strict(),pe=e.object({...t,progressKind:e.literal("cdk.output"),outputType:e.enum(["synth","diff"]),output:e.string().max(m)}).strict(),me=e.object({...t,progressKind:e.literal("detection.completed"),detection:M}).strict(),ge=e.object({...t,progressKind:e.literal("detection.phase"),phase:e.enum(R),status:e.enum(c)}).strict(),de=e.object({...t,progressKind:e.literal("cascade.started")}).strict(),ue=e.object({...t,progressKind:e.literal("cascade.accountsReconciled"),hasPlatformAccount:e.boolean(),hasMemberAccounts:e.boolean()}).strict(),xe=e.object({...t,progressKind:e.literal("cascade.orgChanges"),hasOrgChanges:e.boolean()}).strict(),be=e.object({...t,progressKind:e.literal("cascade.missingAccounts"),accountNames:e.array(e.string().max(o)).max(256)}).strict(),Se=e.object({...t,progressKind:e.literal("cascade.phase"),phase:e.enum(h),status:e.enum(c)}).strict(),he=e.object({...t,progressKind:e.literal("cascade.account.started"),operationKey:e.string().max(a),accountId:e.string().max(a),region:e.string().max(a),deployType:e.string().max(64).optional()}).strict(),Ee=e.object({...t,progressKind:e.literal("cascade.account.phase"),operationKey:e.string().max(a),phase:e.enum(v),region:e.string().max(a).optional()}).strict(),Ae=e.object({...t,progressKind:e.literal("cascade.account.completed"),operationKey:e.string().max(a),success:e.boolean(),error:e.string().max(n).optional(),region:e.string().max(a).optional(),outputs:e.record(e.string().max(o),e.string().max(i)).optional(),skipped:e.boolean().optional()}).strict(),Ce=e.object({...t,progressKind:e.literal("cascade.completed"),result:V}).strict(),_e=e.object({...t,progressKind:e.literal("cascade.ledger"),ledger:G}).strict(),je=e.object({...t,progressKind:e.literal("trail.phase"),accountId:e.string().max(a),accountName:e.string().max(o),phase:e.enum(A),status:e.enum(C),detail:e.string().max(j).optional()}).strict(),Te=e.object({...t,progressKind:e.literal("trail.lifecycle"),accountId:e.string().max(a),to:e.enum(p),from:e.enum(p).optional()}).strict(),ye=e.object({...t,progressKind:e.literal("cleanup.progress"),stackName:e.string().max(a),phase:e.enum(D),detail:H.optional()}).strict(),De=e.object({...t,progressKind:e.literal("auth.ssoUrl"),url:e.string().max(g).nullable()}).strict(),ve=e.object({...t,progressKind:e.literal("auth.completed"),result:F.nullable()}).strict(),Pe=e.object({...t,progressKind:e.literal("error"),message:e.string().max(n),name:e.string().max(o).optional()}).strict(),Re=e.object({...t,progressKind:e.literal("deploy.completed"),result:e.enum(P),ok:e.boolean(),errorType:e.string().max(128).optional(),message:e.string().max(s)}).strict(),Ne=e.object({...t,progressKind:e.literal("plan.available"),plan:e.object({summary:e.string().max(s),changeCount:e.number().int().nonnegative(),hasDestructiveChanges:e.boolean(),changes:e.array(U).max(1e3).optional(),diffRef:e.string().max(512).optional(),iamBroadening:e.boolean().optional(),securityGroupBroadening:e.boolean().optional(),changeCountsByAction:u.optional()}).strict()}).strict(),Ke=e.object({...t,progressKind:e.literal("approval.awaiting"),approval:e.object({token:e.string().max(512),kind:e.enum(O),reason:e.string().max(s),expiresAt:e.string().datetime(),assemblyDigest:e.string().max(128).optional(),changeCounts:u.optional(),approvalClass:e.string().max(64).optional(),requiredApprovers:e.array(e.string().max(256)).max(50).optional()}).strict()}).strict(),Oe=e.object({...t,progressKind:e.literal("approval.resolved"),approval:e.object({token:e.string().max(512),decision:e.enum(f),actor:e.string().max(o).optional()}).strict()}).strict(),Be=e.discriminatedUnion("progressKind",[z,J,Q,W,Z,$,ee,te,ae,oe,re,se,ne,ie,ce,le,pe,me,ge,de,ue,xe,be,Se,he,Ee,Ae,Ce,_e,je,Te,ye,De,ve,Pe,Re,Ne,Ke,Oe]),fe={"step.started":!0,"step.completed":!0,log:!0,output:!0,resource:!0,"phase.parallel":!0,"build.started":!0,"build.progress":!0,"build.completed":!0,"taskdef.registered":!0,"ecs.update":!0,"ecs.progress":!0,"ecs.completed":!0,"migrations.started":!0,"migrations.completed":!0,"cdk.bootstrap":!0,"cdk.output":!0,"detection.completed":!0,"detection.phase":!0,"cascade.started":!0,"cascade.accountsReconciled":!0,"cascade.orgChanges":!0,"cascade.missingAccounts":!0,"cascade.phase":!0,"cascade.account.started":!0,"cascade.account.phase":!0,"cascade.account.completed":!0,"cascade.completed":!0,"cascade.ledger":!0,"trail.phase":!0,"trail.lifecycle":!0,"cleanup.progress":!0,"auth.ssoUrl":!0,"auth.completed":!0,error:!0,"deploy.completed":!0,"plan.available":!0,"approval.awaiting":!0,"approval.resolved":!0},Ge=Object.keys(fe);export{Ge as ALL_PROGRESS_KINDS,f as APPROVAL_DECISIONS,O as APPROVAL_KINDS,l as BUILDERS,v as CASCADE_ACCOUNT_PHASES,d as CASCADE_OUTCOME_RESULTS,u as ChangeCountsSchema,r as DEPLOY_EVENT_ARN_MAX,Ue as DEPLOY_EVENT_CONTRACT,Ve as DEPLOY_EVENT_CONTRACT_MAJOR,Ye as DEPLOY_EVENT_CONTRACT_MINOR,n as DEPLOY_EVENT_ERROR_MESSAGE_MAX,a as DEPLOY_EVENT_ID_MAX,s as DEPLOY_EVENT_MESSAGE_MAX,o as DEPLOY_EVENT_NAME_MAX,m as DEPLOY_EVENT_OUTPUT_MAX,i as DEPLOY_EVENT_STATUS_REASON_MAX,j as DEPLOY_EVENT_TRAIL_DETAIL_MAX,g as DEPLOY_EVENT_URL_MAX,P as DEPLOY_RESULTS,R as DETECTION_PHASES,Be as DeployEventSchema,k as DeployResourceSchema,y as LOG_LEVELS,c as PHASE_STATUSES,N as PLAN_ACTIONS,U as PlanChangeSchema,I as PlanPropertyChangeSchema,K as REPLACEMENT_MODES,D as STACK_CLEANUP_PHASES,T as STEP_COMPLETE_STATUSES,_ as SUPPORTED_CONTRACT_MARKERS,x as StepProgressSchema};
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Safe, never-throwing parser for the {@link DeployEvent} contract.
3
+ *
4
+ * `parseDeployEvent` classifies any input into one of four outcomes so a consumer
5
+ * can distinguish forward-compatible events it should render best-effort from a
6
+ * same-version producer bug it must surface loudly:
7
+ *
8
+ * - `ok` — validates against the current contract.
9
+ * - `unknown` — same major, but a future minor OR an unrecognised
10
+ * progressKind. Forward-compatible; render best-effort.
11
+ * - `invalid` — same major, a KNOWN progressKind, yet validation failed.
12
+ * A producer bug (missing/mistyped field) — surface loudly.
13
+ * - `incompatible` — different/unparseable major, or not a contract event.
14
+ *
15
+ * Conflating `invalid` into `unknown` would let a malformed in-version event be
16
+ * swallowed by forward-compat handling, so the taxonomy keeps them distinct.
17
+ */
18
+ import { type DeployEvent } from "./deployEvent.js";
19
+ /**
20
+ * Outcome of {@link parseDeployEvent}.
21
+ *
22
+ * `raw` and `reason` are diagnostic and are NOT masked — they may echo
23
+ * credential-bearing content from a malformed event. A consumer that logs them
24
+ * MUST mask first (`maskSensitiveOutput`).
25
+ */
26
+ export type ParsedDeployEvent = {
27
+ status: "ok";
28
+ event: DeployEvent;
29
+ } | {
30
+ status: "unknown";
31
+ contract: string;
32
+ progressKind?: string;
33
+ raw: unknown;
34
+ } | {
35
+ status: "invalid";
36
+ reason: string;
37
+ progressKind?: string;
38
+ raw: unknown;
39
+ } | {
40
+ status: "incompatible";
41
+ reason: string;
42
+ raw: unknown;
43
+ };
44
+ /**
45
+ * Extract the `{ major, minor }` from a contract marker, or `null` if the string
46
+ * is not a `fjall.deploy/<major>.<minor>` marker.
47
+ */
48
+ export declare function parseDeployContractVersion(contract: string): {
49
+ major: number;
50
+ minor: number;
51
+ } | null;
52
+ export declare function parseDeployEvent(raw: unknown): ParsedDeployEvent;
@@ -0,0 +1 @@
1
+ import{ALL_PROGRESS_KINDS as a,DEPLOY_EVENT_CONTRACT_MAJOR as i,DEPLOY_EVENT_CONTRACT_MINOR as d,DeployEventSchema as f}from"./deployEvent.js";const l=/^fjall\.deploy\/(\d+)\.(\d+)$/,p=new Set(a);function m(n){const e=l.exec(n);if(e===null)return null;const t=e[1],o=e[2];if(t===void 0||o===void 0)return null;const r=parseInt(t,10),s=parseInt(o,10);return Number.isNaN(r)||Number.isNaN(s)?null:{major:r,minor:s}}function u(n,e){if(!(e in n))return;const t=n[e];return typeof t=="string"?t:void 0}function E(n){const e=f.safeParse(n);if(e.success)return{status:"ok",event:e.data};if(typeof n!="object"||n===null)return{status:"incompatible",reason:"Event is not an object",raw:n};const t=u(n,"contract");if(t===void 0)return{status:"incompatible",reason:"Missing or non-string contract marker",raw:n};const o=m(t);if(o===null)return{status:"incompatible",reason:`Unrecognised contract marker: ${t}`,raw:n};if(o.major!==i)return{status:"incompatible",reason:`Contract major ${o.major} unsupported (expected ${i})`,raw:n};const r=u(n,"progressKind"),s=o.minor>d,c=r===void 0||!p.has(r);return s||c?{status:"unknown",contract:t,...r!==void 0&&{progressKind:r},raw:n}:{status:"invalid",reason:e.error.message,...r!==void 0&&{progressKind:r},raw:n}}export{m as parseDeployContractVersion,E as parseDeployEvent};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Compile-time proof that the `{0,0}` step-progress footgun is unrepresentable in
3
+ * the TYPE, complementing the runtime `.positive()` / `.nonnegative()` checks the
4
+ * tests assert. These lines live in compiled `src/` (the package tsconfig
5
+ * excludes `__tests__/`, which `tsc --noEmit` would never see), so the package
6
+ * `typecheck` actually runs them. Each `@ts-expect-error` suppresses a real error;
7
+ * if the `StepProgress` shape ever loosened to permit one of these, the directive
8
+ * would become unused and `tsc` would fail `TS2578: Unused '@ts-expect-error'`.
9
+ */
10
+ export {};
@@ -0,0 +1 @@
1
+ const o={index:0},n={total:5},l={index:null,total:5};
@@ -1,12 +1,17 @@
1
1
  export { DeploymentEventSchema, DEPLOYMENT_EVENT_TYPES, DEPLOYMENT_EVENT_RESOURCE_CATEGORIES, DEPLOYMENT_EVENT_STATUS_REASON_MAX, DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX, DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX, CASCADE_PHASES, CASCADE_ACCOUNT_STATUSES, toCascadePhase } from "./deploymentEventSchema.js";
2
2
  export type { DeploymentEvent, DeploymentEventType, DeploymentEventResourceCategory, DeploymentEventCascadePhase, DeploymentEventCascadeAccountStatus } from "./deploymentEventSchema.js";
3
- export type { AwsCredentials, DeployIdentity } from "./credentials.js";
4
- export type { DeployCallbacks, StepCompleteStatus, StackCleanupQuarantineDetail, StackCleanupRetainedBucketsDetail } from "./callbacks.js";
3
+ export type { AwsCredentials, DeployIdentity, ScopedBuildSecretSessionMinter } from "./credentials.js";
4
+ export type { DeployCallbacks, StepCompleteStatus, StackCleanupPhase, CascadeAccountPhase, LogLevel, StackCleanupQuarantineDetail, StackCleanupRetainedBucketsDetail } from "./callbacks.js";
5
5
  export { isQuarantineDetail, isRetainedBucketsDetail } from "./callbacks.js";
6
+ export { DeployEventSchema, StepProgressSchema, DeployResourceSchema, PlanChangeSchema, PlanPropertyChangeSchema, ChangeCountsSchema, DEPLOY_EVENT_CONTRACT, DEPLOY_EVENT_CONTRACT_MAJOR, DEPLOY_EVENT_CONTRACT_MINOR, SUPPORTED_CONTRACT_MARKERS, DEPLOY_EVENT_ID_MAX, DEPLOY_EVENT_NAME_MAX, DEPLOY_EVENT_MESSAGE_MAX, DEPLOY_EVENT_STATUS_REASON_MAX, DEPLOY_EVENT_ERROR_MESSAGE_MAX, DEPLOY_EVENT_TRAIL_DETAIL_MAX, DEPLOY_EVENT_OUTPUT_MAX, DEPLOY_EVENT_ARN_MAX, DEPLOY_EVENT_URL_MAX, STEP_COMPLETE_STATUSES, LOG_LEVELS, STACK_CLEANUP_PHASES, CASCADE_ACCOUNT_PHASES, DEPLOY_RESULTS, DETECTION_PHASES, PHASE_STATUSES, BUILDERS, CASCADE_OUTCOME_RESULTS, PLAN_ACTIONS, REPLACEMENT_MODES, APPROVAL_KINDS, APPROVAL_DECISIONS, ALL_PROGRESS_KINDS } from "./deployEvent.js";
7
+ export type { DeployEvent, ProgressKind, StepProgress, DeployResource, PlanChange, PlanPropertyChange, ChangeCounts, PlanAction, ReplacementMode, ApprovalKind, ApprovalDecision, DeployRunResult } from "./deployEvent.js";
8
+ export { createDeployEmitter, type DeployEmitter, type CreateDeployEmitterOptions } from "./deployEmitter.js";
9
+ export { parseDeployEvent, parseDeployContractVersion, type ParsedDeployEvent } from "./deployEventParse.js";
6
10
  export type { ProgressEvent, ProgressEventType, ResourceEvent, AwsAuthResult, CascadeDeploymentResult, CascadePhase, BuildPushStartEvent, BuildPushProgressEvent, BuildPushCompleteEvent, TaskDefRegisteredEvent, ECSCompleteEvent, MigrationsStartEvent, MigrationsCompleteEvent, TrailMigrationPhase, TrailMigrationStatus, TrailMigrationPhaseEvent } from "./events.js";
7
11
  export { TRAIL_MIGRATION_PHASES, TRAIL_MIGRATION_STATUSES } from "./events.js";
8
12
  export type { ApiClientInterface, EntitlementsData } from "./apiClient.js";
9
13
  export type { DeployParams, DeployOptions, DeploymentType, DeployResult, DestroyParams, DestroyOptions, DestroyResult } from "./params.js";
14
+ export type { ApprovalGate, ApprovalRequest, GateResolution } from "./approval.js";
10
15
  export type { OrgConfig, ProviderAccount, RootAccessManagementMode, SSOSession } from "./config/orgConfig.js";
11
16
  export type { Entitlements } from "./config/entitlements.js";
12
17
  export type { StackOutput, StackOutputsRecord, DeploymentContext, StepOutput, ApplicationDeploymentContext, CallerIdentity } from "./deployment/index.js";
@@ -1 +1 @@
1
- import{DeploymentEventSchema as t,DEPLOYMENT_EVENT_TYPES as A,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as T,DEPLOYMENT_EVENT_STATUS_REASON_MAX as r,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as S,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as _,CASCADE_PHASES as a,CASCADE_ACCOUNT_STATUSES as o,toCascadePhase as p}from"./deploymentEventSchema.js";import{isQuarantineDetail as i,isRetainedBucketsDetail as N}from"./callbacks.js";import{TRAIL_MIGRATION_PHASES as R,TRAIL_MIGRATION_STATUSES as l}from"./events.js";import{stubCallerIdentity as L}from"./deployment/index.js";import{ProgressReporter as n}from"./ProgressEvent.js";import{APPLICATION_STACKS as m,ORGANISATION_TYPES as C,APPLICATION_DEPLOY_ORDER as c,APPLICATION_DESTROY_ORDER as M,OPENNEXT_DEPLOY_ORDER as f,OPENNEXT_DESTROY_ORDER as x,PARALLEL_DEPLOY_GROUPS as Y,PARALLEL_DESTROY_GROUPS as g,OPENNEXT_PARALLEL_GROUPS as F,isApplicationOperation as U,isOrganisationOperation as d,getParallelDeployGroups as G,getParallelDestroyGroups as u,getApplicationDeployOrder as y,getApplicationDestroyOrder as X,getApplicationStackName as h,getOrganisationStackName as k,isApplicationStack as K,getApplicationStepName as V,getApplicationStepId as H,toPascalCase as v}from"./operations.js";import{PARALLEL_OPERATION_TYPES as b}from"./deployment/index.js";import{isOpenNextPattern as B,OPENNEXT_PATTERNS as Q}from"./detection/patternTypes.js";import{deriveResourcesFromManifestStacks as z}from"./detection/patternDetection.js";import{STACK_NOT_FOUND_PATTERN as W,STACK_FAILED_STATE_PATTERN as Z,CDK_NO_STACKS_MATCH as $,INFRASTRUCTURE_FILENAME as ee}from"./constants.js";import{ApplicationError as te,wrapApplicationError as Ae}from"./application/index.js";import{FjallStateFileSchema as re,readStateFile as Se,writeStateFile as _e,createEmptyState as ae,deleteStateFile as oe,updateTemplateHash as pe,getStateFilePath as Oe,regionSuffix as ie}from"./config/FjallState.js";import{STEP_IDS as Pe,STEP_NAMES as Re,INFRASTRUCTURE_STEP_NAMES as le,INFRA_STEP_NAME as De}from"./stepDefinitions.js";export{c as APPLICATION_DEPLOY_ORDER,M as APPLICATION_DESTROY_ORDER,m as APPLICATION_STACKS,te as ApplicationError,o as CASCADE_ACCOUNT_STATUSES,a as CASCADE_PHASES,$ as CDK_NO_STACKS_MATCH,S as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,T as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,r as DEPLOYMENT_EVENT_STATUS_REASON_MAX,_ as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,A as DEPLOYMENT_EVENT_TYPES,t as DeploymentEventSchema,re as FjallStateFileSchema,ee as INFRASTRUCTURE_FILENAME,le as INFRASTRUCTURE_STEP_NAMES,De as INFRA_STEP_NAME,f as OPENNEXT_DEPLOY_ORDER,x as OPENNEXT_DESTROY_ORDER,F as OPENNEXT_PARALLEL_GROUPS,Q as OPENNEXT_PATTERNS,C as ORGANISATION_TYPES,Y as PARALLEL_DEPLOY_GROUPS,g as PARALLEL_DESTROY_GROUPS,b as PARALLEL_OPERATION_TYPES,n as ProgressReporter,Z as STACK_FAILED_STATE_PATTERN,W as STACK_NOT_FOUND_PATTERN,Pe as STEP_IDS,Re as STEP_NAMES,R as TRAIL_MIGRATION_PHASES,l as TRAIL_MIGRATION_STATUSES,ae as createEmptyState,oe as deleteStateFile,z as deriveResourcesFromManifestStacks,y as getApplicationDeployOrder,X as getApplicationDestroyOrder,h as getApplicationStackName,H as getApplicationStepId,V as getApplicationStepName,k as getOrganisationStackName,G as getParallelDeployGroups,u as getParallelDestroyGroups,Oe as getStateFilePath,U as isApplicationOperation,K as isApplicationStack,B as isOpenNextPattern,d as isOrganisationOperation,i as isQuarantineDetail,N as isRetainedBucketsDetail,Se as readStateFile,ie as regionSuffix,L as stubCallerIdentity,p as toCascadePhase,v as toPascalCase,pe as updateTemplateHash,Ae as wrapApplicationError,_e as writeStateFile};
1
+ import{DeploymentEventSchema as e,DEPLOYMENT_EVENT_TYPES as A,DEPLOYMENT_EVENT_RESOURCE_CATEGORIES as S,DEPLOYMENT_EVENT_STATUS_REASON_MAX as T,DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX as t,DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX as O,CASCADE_PHASES as P,CASCADE_ACCOUNT_STATUSES as r,toCascadePhase as N}from"./deploymentEventSchema.js";import{isQuarantineDetail as a,isRetainedBucketsDetail as R}from"./callbacks.js";import{DeployEventSchema as p,StepProgressSchema as D,DeployResourceSchema as C,PlanChangeSchema as i,PlanPropertyChangeSchema as l,ChangeCountsSchema as I,DEPLOY_EVENT_CONTRACT as M,DEPLOY_EVENT_CONTRACT_MAJOR as n,DEPLOY_EVENT_CONTRACT_MINOR as m,SUPPORTED_CONTRACT_MARKERS as s,DEPLOY_EVENT_ID_MAX as c,DEPLOY_EVENT_NAME_MAX as Y,DEPLOY_EVENT_MESSAGE_MAX as U,DEPLOY_EVENT_STATUS_REASON_MAX as V,DEPLOY_EVENT_ERROR_MESSAGE_MAX as f,DEPLOY_EVENT_TRAIL_DETAIL_MAX as x,DEPLOY_EVENT_OUTPUT_MAX as g,DEPLOY_EVENT_ARN_MAX as X,DEPLOY_EVENT_URL_MAX as h,STEP_COMPLETE_STATUSES as G,LOG_LEVELS as y,STACK_CLEANUP_PHASES as F,CASCADE_ACCOUNT_PHASES as d,DEPLOY_RESULTS as u,DETECTION_PHASES as K,PHASE_STATUSES as H,BUILDERS as k,CASCADE_OUTCOME_RESULTS as v,PLAN_ACTIONS as w,REPLACEMENT_MODES as B,APPROVAL_KINDS as b,APPROVAL_DECISIONS as j,ALL_PROGRESS_KINDS as J}from"./deployEvent.js";import{createDeployEmitter as q}from"./deployEmitter.js";import{parseDeployEvent as W,parseDeployContractVersion as Z}from"./deployEventParse.js";import{TRAIL_MIGRATION_PHASES as EE,TRAIL_MIGRATION_STATUSES as _E}from"./events.js";import{stubCallerIdentity as AE}from"./deployment/index.js";import{ProgressReporter as TE}from"./ProgressEvent.js";import{APPLICATION_STACKS as OE,ORGANISATION_TYPES as PE,APPLICATION_DEPLOY_ORDER as rE,APPLICATION_DESTROY_ORDER as NE,OPENNEXT_DEPLOY_ORDER as oE,OPENNEXT_DESTROY_ORDER as aE,PARALLEL_DEPLOY_GROUPS as RE,PARALLEL_DESTROY_GROUPS as LE,OPENNEXT_PARALLEL_GROUPS as pE,isApplicationOperation as DE,isOrganisationOperation as CE,getParallelDeployGroups as iE,getParallelDestroyGroups as lE,getApplicationDeployOrder as IE,getApplicationDestroyOrder as ME,getApplicationStackName as nE,getOrganisationStackName as mE,isApplicationStack as sE,getApplicationStepName as cE,getApplicationStepId as YE,toPascalCase as UE}from"./operations.js";import{PARALLEL_OPERATION_TYPES as fE}from"./deployment/index.js";import{isOpenNextPattern as gE,OPENNEXT_PATTERNS as XE}from"./detection/patternTypes.js";import{deriveResourcesFromManifestStacks as GE}from"./detection/patternDetection.js";import{STACK_NOT_FOUND_PATTERN as FE,STACK_FAILED_STATE_PATTERN as dE,CDK_NO_STACKS_MATCH as uE,INFRASTRUCTURE_FILENAME as KE}from"./constants.js";import{ApplicationError as kE,wrapApplicationError as vE}from"./application/index.js";import{FjallStateFileSchema as BE,readStateFile as bE,writeStateFile as jE,createEmptyState as JE,deleteStateFile as QE,updateTemplateHash as qE,getStateFilePath as zE,regionSuffix as WE}from"./config/FjallState.js";import{STEP_IDS as $E,STEP_NAMES as E_,INFRASTRUCTURE_STEP_NAMES as __,INFRA_STEP_NAME as e_}from"./stepDefinitions.js";export{J as ALL_PROGRESS_KINDS,rE as APPLICATION_DEPLOY_ORDER,NE as APPLICATION_DESTROY_ORDER,OE as APPLICATION_STACKS,j as APPROVAL_DECISIONS,b as APPROVAL_KINDS,kE as ApplicationError,k as BUILDERS,d as CASCADE_ACCOUNT_PHASES,r as CASCADE_ACCOUNT_STATUSES,v as CASCADE_OUTCOME_RESULTS,P as CASCADE_PHASES,uE as CDK_NO_STACKS_MATCH,I as ChangeCountsSchema,t as DEPLOYMENT_EVENT_ERROR_MESSAGE_MAX,S as DEPLOYMENT_EVENT_RESOURCE_CATEGORIES,T as DEPLOYMENT_EVENT_STATUS_REASON_MAX,O as DEPLOYMENT_EVENT_TRAIL_DETAIL_MAX,A as DEPLOYMENT_EVENT_TYPES,X as DEPLOY_EVENT_ARN_MAX,M as DEPLOY_EVENT_CONTRACT,n as DEPLOY_EVENT_CONTRACT_MAJOR,m as DEPLOY_EVENT_CONTRACT_MINOR,f as DEPLOY_EVENT_ERROR_MESSAGE_MAX,c as DEPLOY_EVENT_ID_MAX,U as DEPLOY_EVENT_MESSAGE_MAX,Y as DEPLOY_EVENT_NAME_MAX,g as DEPLOY_EVENT_OUTPUT_MAX,V as DEPLOY_EVENT_STATUS_REASON_MAX,x as DEPLOY_EVENT_TRAIL_DETAIL_MAX,h as DEPLOY_EVENT_URL_MAX,u as DEPLOY_RESULTS,K as DETECTION_PHASES,p as DeployEventSchema,C as DeployResourceSchema,e as DeploymentEventSchema,BE as FjallStateFileSchema,KE as INFRASTRUCTURE_FILENAME,__ as INFRASTRUCTURE_STEP_NAMES,e_ as INFRA_STEP_NAME,y as LOG_LEVELS,oE as OPENNEXT_DEPLOY_ORDER,aE as OPENNEXT_DESTROY_ORDER,pE as OPENNEXT_PARALLEL_GROUPS,XE as OPENNEXT_PATTERNS,PE as ORGANISATION_TYPES,RE as PARALLEL_DEPLOY_GROUPS,LE as PARALLEL_DESTROY_GROUPS,fE as PARALLEL_OPERATION_TYPES,H as PHASE_STATUSES,w as PLAN_ACTIONS,i as PlanChangeSchema,l as PlanPropertyChangeSchema,TE as ProgressReporter,B as REPLACEMENT_MODES,F as STACK_CLEANUP_PHASES,dE as STACK_FAILED_STATE_PATTERN,FE as STACK_NOT_FOUND_PATTERN,G as STEP_COMPLETE_STATUSES,$E as STEP_IDS,E_ as STEP_NAMES,s as SUPPORTED_CONTRACT_MARKERS,D as StepProgressSchema,EE as TRAIL_MIGRATION_PHASES,_E as TRAIL_MIGRATION_STATUSES,q as createDeployEmitter,JE as createEmptyState,QE as deleteStateFile,GE as deriveResourcesFromManifestStacks,IE as getApplicationDeployOrder,ME as getApplicationDestroyOrder,nE as getApplicationStackName,YE as getApplicationStepId,cE as getApplicationStepName,mE as getOrganisationStackName,iE as getParallelDeployGroups,lE as getParallelDestroyGroups,zE as getStateFilePath,DE as isApplicationOperation,sE as isApplicationStack,gE as isOpenNextPattern,CE as isOrganisationOperation,a as isQuarantineDetail,R as isRetainedBucketsDetail,Z as parseDeployContractVersion,W as parseDeployEvent,bE as readStateFile,WE as regionSuffix,AE as stubCallerIdentity,N as toCascadePhase,UE as toPascalCase,qE as updateTemplateHash,vE as wrapApplicationError,jE as writeStateFile};
@@ -1,10 +1,13 @@
1
1
  import type { Result } from "@fjall/generator";
2
- import type { AwsCredentials, DeployIdentity } from "./credentials.js";
2
+ import type { AwsCredentials, DeployIdentity, ScopedBuildSecretSessionMinter } from "./credentials.js";
3
3
  import type { DeployCallbacks } from "./callbacks.js";
4
4
  import type { ApiClientInterface } from "./apiClient.js";
5
5
  import type { OrgConfig } from "./config/orgConfig.js";
6
6
  import type { DockerProvider } from "../orchestration/dockerInterface.js";
7
7
  import type { DomainDeployProvider } from "../orchestration/domainInterface.js";
8
+ import type { ApprovalGate } from "./approval.js";
9
+ import type { FailureAnalysis } from "@fjall/util/aws";
10
+ import type { DockerBuildSecretRef } from "@fjall/util/manifest/schemas";
8
11
  export interface DeployParams {
9
12
  /** Deployment target name (e.g., "my-app", "organisation", "platform", "account-prod") */
10
13
  target: string;
@@ -12,6 +15,14 @@ export interface DeployParams {
12
15
  workingDirectory: string;
13
16
  /** AWS credentials for the deployment. deploy-core never resolves these itself. */
14
17
  awsCredentials: AwsCredentials;
18
+ /**
19
+ * Optional re-mint hook the worker supplies so build-secret reads run under a
20
+ * least-privilege child session (the inline policy narrows the worker's deploy
21
+ * role to exactly this app's SSM/SM/KMS). The CLI omits it — its `AwsContext`
22
+ * self-scopes via `assumeScopedBuildSecretSession`. When omitted, build-secret
23
+ * reads fall back to the unscoped identity (see `resolveBuildSecrets`).
24
+ */
25
+ mintScopedBuildSecretSession?: ScopedBuildSecretSessionMinter;
15
26
  /** Typed callbacks for progress events. CLI and worker implement differently. */
16
27
  callbacks: DeployCallbacks;
17
28
  /** Deployment options */
@@ -55,6 +66,15 @@ export interface DeployParams {
55
66
  * per-request timeouts so SIGTERM is not stalled by an in-flight call.
56
67
  */
57
68
  abortSignal?: AbortSignal;
69
+ /**
70
+ * Optional engine-level approval gate. When supplied, the engine computes a
71
+ * typed resource-level plan at the read→mutate boundary and resolves an
72
+ * approve / reject / await decision through this surface resolver before any
73
+ * mutation. Omit it for the legacy ungated flow (fully backward-compatible).
74
+ * The non-resolver paths (`options.planOnly`, `options.approvalToken`) engage
75
+ * the gate even when this is omitted.
76
+ */
77
+ approvalGate?: ApprovalGate;
58
78
  }
59
79
  export interface DeployOptions {
60
80
  skipConfirmation?: boolean;
@@ -82,6 +102,48 @@ export interface DeployOptions {
82
102
  * build + push and rolls ECS to `<repo>:<imageTag>`. Implies `deployOnly`.
83
103
  */
84
104
  imageTag?: string;
105
+ /**
106
+ * Approval-gate: require an explicit approve decision before mutating. The
107
+ * engine only gates when a gate is engaged (resolver injected, `planOnly`, or
108
+ * `approvalToken` supplied); this flag is the surface's intent signal that the
109
+ * resolver fail-closes on (non-interactive refuses without `autoApprove`).
110
+ */
111
+ requireApproval?: boolean;
112
+ /**
113
+ * Approval-gate: approve the computed plan without prompting. The plan is
114
+ * still computed and emitted; the engine proceeds to mutate. FAIL-OPEN escape
115
+ * hatch — never the default.
116
+ */
117
+ autoApprove?: boolean;
118
+ /**
119
+ * Approval-gate: compute and emit the plan, then stop before any mutation,
120
+ * returning a signed approval token (`DeployResult.approvalToken`). Phase 1 of
121
+ * the two-phase plan→apply flow (`fjall deploy --plan`, MCP `plan_deployment`,
122
+ * webapp sheet).
123
+ */
124
+ planOnly?: boolean;
125
+ /**
126
+ * Approval-gate: a token from a prior plan-only run. The engine recomputes the
127
+ * plan, re-checks the token's bound digest against the fresh synth (TOCTOU
128
+ * guard), and proceeds to mutate only on a match — otherwise rejects as
129
+ * superseded / expired. Phase 2 of the two-phase flow.
130
+ */
131
+ approvalToken?: string;
132
+ /**
133
+ * CLI `--build-arg KEY=VALUE` overrides, the highest-precedence build-arg tier
134
+ * fed into `resolveBuildArgs` (`buildArgResolver.ts` § precedence ladder) by
135
+ * `dockerBuildHelper.buildGroup`. A key here widens the emitted set beyond the
136
+ * manifest. Parsed from the repeatable flag by `parseBuildArgFlags` (CLI).
137
+ */
138
+ flagBuildArgs?: Record<string, string>;
139
+ /**
140
+ * CLI `--build-secret id=…,ssm=…` ad-hoc references, merged with the manifest
141
+ * `docker.buildSecrets` before the build group's session scoping +
142
+ * `validateBuildGroup` so an ad-hoc ref participates in the least-privilege
143
+ * scope and id-collision check exactly like a manifest ref. Each ref is
144
+ * validated through `DockerBuildSecretRefSchema` (CLI) before it reaches here.
145
+ */
146
+ flagBuildSecrets?: readonly DockerBuildSecretRef[];
85
147
  }
86
148
  export type DeploymentType = "application" | "organisation";
87
149
  export interface DeployResult {
@@ -98,12 +160,54 @@ export interface DeployResult {
98
160
  durationMs?: number;
99
161
  /** Non-fatal warnings (e.g. cascade account failures) */
100
162
  warnings?: string[];
163
+ /**
164
+ * Structured root-cause analysis (category, dependency chain, remediation)
165
+ * captured when a stack failed during the deploy — the same analysis emitted
166
+ * over `DeployCallbacks.onFailureAnalysis`. Populated on a partial-success
167
+ * result (e.g. a cascade where a child stack failed but the run completed);
168
+ * a fully-failed deploy returns `Result.failure` and delivers the analysis
169
+ * over the callback instead. Consumers render it identically to the callback.
170
+ */
171
+ failureAnalysis?: FailureAnalysis;
101
172
  /**
102
173
  * Set when detection found no infrastructure changes and the engine
103
174
  * short-circuited the deploy. Consumers use this to render the
104
175
  * "already up to date" path instead of inferring it from output absence.
105
176
  */
106
177
  noChanges?: boolean;
178
+ /**
179
+ * Set when the deploy was aborted via `DeployParams.abortSignal` (CLI Ctrl-C
180
+ * or worker SIGTERM). The engine has killed the CDK child and issued
181
+ * `CancelUpdateStack` on the in-flight stack, so this is a *cancelled*
182
+ * outcome, NOT a failure. Consumers render it distinctly (CLI: "cancelled"
183
+ * exit 130; worker: retryable re-queue, never DLQ).
184
+ */
185
+ cancelled?: boolean;
186
+ /**
187
+ * Approval-gate: set when the computed plan was REJECTED at the gate (a
188
+ * surface declined, or a resume token was refused as superseded/expired).
189
+ * Conceptually a cancel-before-mutation: no CDK child ran, nothing was
190
+ * mutated. Distinct from `cancelled` (in-flight abort) and from a failure.
191
+ */
192
+ rejected?: boolean;
193
+ /**
194
+ * Approval-gate: set when the engine computed + emitted the plan and stopped
195
+ * before mutation, awaiting an out-of-band approval (`planOnly`, or a resolver
196
+ * that suspended). Pairs with `approvalToken` for the resuming apply call.
197
+ */
198
+ awaitingApproval?: boolean;
199
+ /**
200
+ * Approval-gate: the signed, digest-bound token to echo back on the resuming
201
+ * apply call. Present only when `awaitingApproval` is set. NOT a secret — an
202
+ * echoed-back capability bound to the synthesised plan; not masked.
203
+ */
204
+ approvalToken?: string;
205
+ /**
206
+ * Approval-gate: the assembly digest the plan was computed against. Present
207
+ * with `awaitingApproval` so a caller can persist + correlate the awaiting
208
+ * plan.
209
+ */
210
+ assemblyDigest?: string;
107
211
  }
108
212
  /**
109
213
  * Parameters for the destroy entry point.
@@ -163,6 +267,13 @@ export interface DestroyResult {
163
267
  skippedStacks?: string[];
164
268
  /** Non-fatal warnings (e.g. cascade account failures) */
165
269
  warnings?: string[];
270
+ /**
271
+ * Set when the destroy was aborted via `DestroyParams.abortSignal`. Mirrors
272
+ * {@link DeployResult.cancelled}: a *cancelled* outcome, not a failure. The
273
+ * in-flight DeleteStack continues server-side (a delete cannot be cancelled),
274
+ * but the local process stopped cleanly and the worker re-queues.
275
+ */
276
+ cancelled?: boolean;
166
277
  }
167
278
  /** Re-export Result from generator for consumers. */
168
279
  export type { Result };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fjall/deploy-core",
3
- "version": "2.21.0",
3
+ "version": "2.22.1",
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",
@@ -63,6 +63,8 @@
63
63
  },
64
64
  "license": "SEE LICENSE IN LICENSE",
65
65
  "dependencies": {
66
+ "@aws-cdk/cloudformation-diff": "2.187.1",
67
+ "@aws-sdk/client-account": "^3.1067.0",
66
68
  "@aws-sdk/client-backup": "^3.1038.0",
67
69
  "@aws-sdk/client-cloudformation": "^3.1038.0",
68
70
  "@aws-sdk/client-cloudtrail": "^3.1065.0",
@@ -76,11 +78,13 @@
76
78
  "@aws-sdk/client-s3": "^3.1038.0",
77
79
  "@aws-sdk/client-secrets-manager": "^3.1038.0",
78
80
  "@aws-sdk/client-sqs": "^3.1067.0",
81
+ "@aws-sdk/client-ssm": "^3.1038.0",
79
82
  "@aws-sdk/client-sso-admin": "^3.1038.0",
80
83
  "@aws-sdk/client-sts": "^3.1038.0",
81
- "@fjall/generator": "^2.21.0",
82
- "@fjall/util": "^2.21.0",
84
+ "@fjall/generator": "^2.22.1",
85
+ "@fjall/util": "^2.22.1",
83
86
  "@smithy/node-http-handler": "^4.6.1",
87
+ "aws-cdk": "^2.1128.1",
84
88
  "tsx": "^4.21.0",
85
89
  "zod": "^4.4.3"
86
90
  },
@@ -89,5 +93,5 @@
89
93
  "typescript": "^6.0.3",
90
94
  "vitest": "^4.1.5"
91
95
  },
92
- "gitHead": "1b8902876c40697183ce8cbc25a0556b11d0ec38"
96
+ "gitHead": "ec04f1739f19e4b5212899df7f733ee0d1f06ec3"
93
97
  }