@fjall/deploy-core 12.3.0 → 13.0.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/README.md +8 -0
- package/dist/.build-source-hash +7 -7
- package/dist/.minified +1 -1
- package/dist/src/orchestration/application/destructionGate.js +1 -1
- package/dist/src/orchestration/application/plan/classify.js +1 -1
- package/dist/src/orchestration/remediation/removalUpdate.d.ts +4 -4
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -20,6 +20,14 @@ import { StepRegistry } from "@fjall/deploy-core/steps";
|
|
|
20
20
|
|
|
21
21
|
See [docs.fjall.io](https://docs.fjall.io) for full usage.
|
|
22
22
|
|
|
23
|
+
## Breaking changes
|
|
24
|
+
|
|
25
|
+
Majors are documented in [docs/release-notes](../docs/release-notes/) at the
|
|
26
|
+
repository root. From 13.0.0 the destruction gate's stateful-resource oracle
|
|
27
|
+
also covers log groups, secrets, KMS keys, hosted zones and Cognito user
|
|
28
|
+
pools — deletes and replacements of those types stop at the gate (exit 4)
|
|
29
|
+
until consented with `--remediate`.
|
|
30
|
+
|
|
23
31
|
## Licence
|
|
24
32
|
|
|
25
33
|
Proprietary — see [LICENSE](./LICENSE).
|
package/dist/.build-source-hash
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"package.json",
|
|
10
10
|
"tsconfig.json"
|
|
11
11
|
],
|
|
12
|
-
"hash": "
|
|
12
|
+
"hash": "0132f0e69216695aa306a7e32e7dffdd6d27216a71fc9cb8b999d35b2baaa4e8",
|
|
13
13
|
"files": {
|
|
14
14
|
"src/__test-utils__/awsMockHelpers.ts": "fea371c1b1869678",
|
|
15
15
|
"src/__test-utils__/index.ts": "e03cf35821157dc4",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"src/orchestration/application/databaseEndpointReconcile.ts": "27b14ee41524c632",
|
|
69
69
|
"src/orchestration/application/deploySessionPolicy.ts": "8052c64ce050c2b8",
|
|
70
70
|
"src/orchestration/application/destroyPreFlight.ts": "cc4978dec60b033e",
|
|
71
|
-
"src/orchestration/application/destructionGate.ts": "
|
|
71
|
+
"src/orchestration/application/destructionGate.ts": "5fbaa6ef69eb3ae1",
|
|
72
72
|
"src/orchestration/application/detectionPipeline.ts": "69b7dfcedf22fe01",
|
|
73
73
|
"src/orchestration/application/dockerBuildHelper.ts": "e7a7259e987d93be",
|
|
74
74
|
"src/orchestration/application/ecrCacheRepository.ts": "d7a5602ccabde493",
|
|
@@ -81,13 +81,13 @@
|
|
|
81
81
|
"src/orchestration/application/plan/assemblyDigest.ts": "4c77451ced199188",
|
|
82
82
|
"src/orchestration/application/plan/buildDeployPlan.ts": "4cb0b57b60712404",
|
|
83
83
|
"src/orchestration/application/plan/changeSetEscalation.ts": "d9ad7a5a65283dc4",
|
|
84
|
-
"src/orchestration/application/plan/classify.ts": "
|
|
84
|
+
"src/orchestration/application/plan/classify.ts": "d9fc8d78d281b69a",
|
|
85
85
|
"src/orchestration/application/plan/computeDeployPlan.ts": "62d47d2d620895b6",
|
|
86
86
|
"src/orchestration/application/plan/index.ts": "a2292dca615dd021",
|
|
87
87
|
"src/orchestration/application/plan/loadDeployPlan.ts": "f0d4414fd34f68c3",
|
|
88
88
|
"src/orchestration/application/plan/pinnedNames.ts": "d6a90c96c88f13e0",
|
|
89
89
|
"src/orchestration/application/plan/registryOverlay.ts": "920be845c7f4aea2",
|
|
90
|
-
"src/orchestration/application/plan/renameDetection.ts": "
|
|
90
|
+
"src/orchestration/application/plan/renameDetection.ts": "7242d45be616625f",
|
|
91
91
|
"src/orchestration/application/plan/renderDeployPlan.ts": "7fa4fc332accdc00",
|
|
92
92
|
"src/orchestration/application/plan/types.ts": "191929198672081c",
|
|
93
93
|
"src/orchestration/application/schemaGateImage.ts": "587a115432c6678e",
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
"src/orchestration/remediation/recreatePreFlight.ts": "654ef18cabe97777",
|
|
154
154
|
"src/orchestration/remediation/recreateResource.ts": "a9d97c47e0af68a7",
|
|
155
155
|
"src/orchestration/remediation/remediationJournal.ts": "5ebb14e618fde1c1",
|
|
156
|
-
"src/orchestration/remediation/removalUpdate.ts": "
|
|
156
|
+
"src/orchestration/remediation/removalUpdate.ts": "5e318c32562e01f2",
|
|
157
157
|
"src/orchestration/remediation/retainFlip.ts": "80e7b47e87251db5",
|
|
158
158
|
"src/orchestration/resolveOperation.ts": "84a9f425939fad63",
|
|
159
159
|
"src/orchestration/restart/restartApplication.ts": "3320b6aef19da793",
|
|
@@ -263,9 +263,9 @@
|
|
|
263
263
|
"src/util/sleepAbortable.ts": "f9cac3bf8a79a476",
|
|
264
264
|
"src/version.ts": "1811a4475823b27e",
|
|
265
265
|
"../scripts/minify-dist.mjs": "6b2e4b0df8aec601",
|
|
266
|
-
"package.json": "
|
|
266
|
+
"package.json": "b23f62811690a0c4",
|
|
267
267
|
"tsconfig.json": "1929cf3f99fe9b1e"
|
|
268
268
|
},
|
|
269
|
-
"outputHash": "
|
|
269
|
+
"outputHash": "398e97e933c73915b15c92bb1e732877cb2e829f8cb4958c29c1f810c99734d9",
|
|
270
270
|
"outputFileCount": 495
|
|
271
271
|
}
|
package/dist/.minified
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
247 files minified at 2026-08-
|
|
1
|
+
247 files minified at 2026-08-16T02:45:25.300Z
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var N=Object.defineProperty;var d=(e,i)=>N(e,"name",{value:i,configurable:!0});import{createHash as D}from"node:crypto";import{success as g,failure as x}from"@fjall/generator";import{maskSensitiveOutput as C}from"@fjall/util";import{remediationPlaceholderPhysicalId as L}from"../../types/remediation.js";import{pinProbeCoverage as P}from"../remediation/pinRemediation.js";const v={"replacement-required":["abort","pin","recreate"],"pinned-name-replacement":["abort","pin","recreate"],"data-loss-delete":["abort","forget","recreate"],"resource-deleted":["abort","repair","forget","recreate"],"stack-deleted":["abort","repair","recreate"],"rename-detected":["abort","pin","recreate"],"rename-ambiguous":["abort","recreate"]};function G(e){return v[e]}d(G,"legalRemediationVerbs");const h={"replacement-required":["pin","recreate"],"pinned-name-replacement":["pin","recreate"],"data-loss-delete":["recreate"],"resource-deleted":["forget"],"stack-deleted":[],"rename-detected":["pin"],"rename-ambiguous":[]};function S(e){return h[e]}d(S,"executableRemediationVerbs");function b(e){const i=S(e.finding);return e.verbs.filter(n=>n==="abort"||i.includes(n)&&(n!=="pin"||y(e).covered))}d(b,"advertisableRemediationVerbs");function y(e){if(e.finding==="rename-detected")return e.pinSlotHint!==void 0?{covered:!0}:{covered:!1,detail:"no capacity-identity alias names this rename, so the identity-pin remediation cannot derive the {app, slot} to pin \u2014 hand-author the capacityIdentity entry in fjall-config.json and validate it with 'fjall migrate identity'"};const i=P(e.resourceType,e.offendingProperties);return i.covered?{covered:!0}:{covered:!1,detail:`verb 'pin' has no live-value probe for ${i.unsupportedPairs.join(", ")} in this release \u2014 pin cannot capture the live value(s) into the config for this resource`}}d(y,"pinVerbCoverage");function j(e){if(e.renameFinding!==void 0)return e.renameFinding;if(e.action==="replace")return e.pinnedPhysicalName!==void 0?"pinned-name-replacement":e.dataLoss?"replacement-required":void 0;if(e.action==="delete"&&e.dataLoss&&!e.retained)return"data-loss-delete"}d(j,"findingForChange");function R(e,i,n){if(i==="rename-detected"||i==="rename-ambiguous")return e.renameCause??"logical identity rename detected";if(i==="data-loss-delete")return"removed from the synthesised template \u2014 CloudFormation will delete the live resource and its data";const o=n.length>0?`${n.join(", ")} forces replacement`:"replacement required (no property-level detail available)",t=e.replacementMode==="may"||e.replacementMode==="conditional"?" (conditional verdict \u2014 worst-cased towards ceremony)":"";return i==="pinned-name-replacement"?`${o}${t}; CloudFormation refuses in-stack replacement of custom-named resources`:`${o}${t}`}d(R,"causeForChange");function E(e,i){const n=D("sha256");n.update(e),n.update(`
|
|
1
|
+
var N=Object.defineProperty;var d=(e,i)=>N(e,"name",{value:i,configurable:!0});import{createHash as D}from"node:crypto";import{success as g,failure as x}from"@fjall/generator";import{maskSensitiveOutput as C}from"@fjall/util";import{remediationPlaceholderPhysicalId as L}from"../../types/remediation.js";import{pinProbeCoverage as P}from"../remediation/pinRemediation.js";const v={"replacement-required":["abort","pin","recreate"],"pinned-name-replacement":["abort","pin","recreate"],"data-loss-delete":["abort","forget","recreate"],"resource-deleted":["abort","repair","forget","recreate"],"stack-deleted":["abort","repair","recreate"],"rename-detected":["abort","pin","recreate"],"rename-ambiguous":["abort","recreate"]};function G(e){return v[e]}d(G,"legalRemediationVerbs");const h={"replacement-required":["pin","recreate"],"pinned-name-replacement":["pin","recreate"],"data-loss-delete":["recreate"],"resource-deleted":["forget"],"stack-deleted":[],"rename-detected":["pin"],"rename-ambiguous":["recreate"]};function S(e){return h[e]}d(S,"executableRemediationVerbs");function b(e){const i=S(e.finding);return e.verbs.filter(n=>n==="abort"||i.includes(n)&&(n!=="pin"||y(e).covered))}d(b,"advertisableRemediationVerbs");function y(e){if(e.finding==="rename-detected")return e.pinSlotHint!==void 0?{covered:!0}:{covered:!1,detail:"no capacity-identity alias names this rename, so the identity-pin remediation cannot derive the {app, slot} to pin \u2014 hand-author the capacityIdentity entry in fjall-config.json and validate it with 'fjall migrate identity'"};const i=P(e.resourceType,e.offendingProperties);return i.covered?{covered:!0}:{covered:!1,detail:`verb 'pin' has no live-value probe for ${i.unsupportedPairs.join(", ")} in this release \u2014 pin cannot capture the live value(s) into the config for this resource`}}d(y,"pinVerbCoverage");function j(e){if(e.renameFinding!==void 0)return e.renameFinding;if(e.action==="replace")return e.pinnedPhysicalName!==void 0?"pinned-name-replacement":e.dataLoss?"replacement-required":void 0;if(e.action==="delete"&&e.dataLoss&&!e.retained)return"data-loss-delete"}d(j,"findingForChange");function R(e,i,n){if(i==="rename-detected"||i==="rename-ambiguous")return e.renameCause??"logical identity rename detected";if(i==="data-loss-delete")return"removed from the synthesised template \u2014 CloudFormation will delete the live resource and its data";const o=n.length>0?`${n.join(", ")} forces replacement`:"replacement required (no property-level detail available)",t=e.replacementMode==="may"||e.replacementMode==="conditional"?" (conditional verdict \u2014 worst-cased towards ceremony)":"";return i==="pinned-name-replacement"?`${o}${t}; CloudFormation refuses in-stack replacement of custom-named resources`:`${o}${t}`}d(R,"causeForChange");function E(e,i){const n=D("sha256");n.update(e),n.update(`
|
|
2
2
|
`);const o=i.map(t=>`${t.stack}|${t.logicalId}|${t.resourceType}|${t.physicalName}|${t.finding}`).sort();for(const t of o)n.update(t),n.update(`
|
|
3
3
|
`);return n.digest("hex")}d(E,"computeTicketDigest");function T(e,i){const n=new Set((i??[]).map(t=>`${t.stackName}
|
|
4
4
|
${t.logicalId}`)),o=[];for(const t of e.changes){if(t.action==="delete"&&n.has(`${t.stack}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var o=Object.defineProperty;var a=(e,t)=>o(e,"name",{value:t,configurable:!0});import{ResourceImpact as n}from"@aws-cdk/cloudformation-diff";function S(e){switch(e){case n.WILL_CREATE:return{action:"create",replacementMode:"none",destructive:!1,retained:!1};case n.WILL_UPDATE:return{action:"update",replacementMode:"none",destructive:!1,retained:!1};case n.WILL_REPLACE:return{action:"replace",replacementMode:"will",destructive:!0,retained:!1};case n.MAY_REPLACE:return{action:"replace",replacementMode:"may",destructive:!0,retained:!1};case n.WILL_DESTROY:return{action:"delete",replacementMode:"none",destructive:!0,retained:!1};case n.WILL_ORPHAN:return{action:"delete",replacementMode:"none",destructive:!1,retained:!0};case n.WILL_IMPORT:return{action:"read",replacementMode:"none",destructive:!1,retained:!1};case n.NO_CHANGE:return{action:"no-op",replacementMode:"none",destructive:!1,retained:!1};default:{const t=e;return{action:"replace",replacementMode:"conditional",destructive:!0,retained:!1}}}}a(S,"classifyImpact");const i=["AWS::RDS::","AWS::DynamoDB::Table","AWS::DynamoDB::GlobalTable","AWS::S3::Bucket","AWS::EFS::FileSystem","AWS::ElastiCache::","AWS::Redshift::","AWS::DocDB::","AWS::Neptune::","AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain","AWS::MSK::Cluster","AWS::QLDB::Ledger","AWS::Timestream::","AWS::EC2::Volume","AWS::FSx::","AWS::Logs::LogGroup","AWS::SecretsManager::Secret","AWS::KMS::Key","AWS::Route53::HostedZone","AWS::Cognito::UserPool"];function s(e){return i.some(t=>t.endsWith("::")?e.startsWith(t):e===t)}a(s,"isStatefulResourceType");function f(e){return e.retained||e.action!=="replace"&&e.action!=="delete"?!1:s(e.resourceType)}a(f,"isDataLoss");const l=new Set([n.WILL_REPLACE,n.MAY_REPLACE]);function A(e){if(e===void 0)return[];const t=[];for(const[c,r]of Object.entries(e))if(r.isDifferent!==!1&&(t.push({path:c,forcesReplacement:r.changeImpact!==void 0&&l.has(r.changeImpact)}),t.length>=100))break;return t}a(A,"derivePropertyChanges");export{S as classifyImpact,A as derivePropertyChanges,f as isDataLoss,s as isStatefulResourceType};
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
* alone, and `isStatefulResourceType` is a data-loss LABEL, not a
|
|
26
26
|
* deletion-authorisation gate: types it does not list (nested-stack
|
|
27
27
|
* containers with stateful children, EC2 instances with attached volumes,
|
|
28
|
-
* Custom:: providers whose Delete handlers run arbitrary code
|
|
29
|
-
*
|
|
28
|
+
* Custom:: providers whose Delete handlers run arbitrary code) can still
|
|
29
|
+
* destroy data or state. An allowlisted referrer
|
|
30
30
|
* carrying a retaining DeletionPolicy also fails closed: CloudFormation
|
|
31
31
|
* would DELETE_SKIPPED it, and the converge's re-create would collide with
|
|
32
32
|
* the orphaned physical resource. Co-removals are reported to the caller,
|
|
@@ -111,8 +111,8 @@ export interface StrippedExport {
|
|
|
111
111
|
* derivation closed — the ceremony consented to the TARGETS only, and
|
|
112
112
|
* `isStatefulResourceType` is a data-loss label, not a
|
|
113
113
|
* deletion-authorisation gate (it does not list nested-stack containers,
|
|
114
|
-
* EC2 instances
|
|
115
|
-
*
|
|
114
|
+
* EC2 instances or Custom:: providers, all of which can destroy data or run
|
|
115
|
+
* delete-time code).
|
|
116
116
|
*/
|
|
117
117
|
export declare const CO_REMOVABLE_RESOURCE_TYPES: readonly ["AWS::SecretsManager::SecretTargetAttachment", "AWS::SecretsManager::RotationSchedule"];
|
|
118
118
|
/** An allowlisted glue resource the derivation pulled into the removal
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/deploy-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fjall-tech/fjall.git",
|
|
@@ -96,15 +96,15 @@
|
|
|
96
96
|
"@aws-sdk/client-ssm": "^3.1098.0",
|
|
97
97
|
"@aws-sdk/client-sso-admin": "^3.1098.0",
|
|
98
98
|
"@aws-sdk/client-sts": "^3.1098.0",
|
|
99
|
-
"@fjall/generator": "^
|
|
100
|
-
"@fjall/util": "^
|
|
99
|
+
"@fjall/generator": "^13.0.0",
|
|
100
|
+
"@fjall/util": "^13.0.0",
|
|
101
101
|
"@smithy/node-http-handler": "^4.9.13",
|
|
102
102
|
"aws-cdk": "^2.1134.0",
|
|
103
103
|
"tsx": "^4.23.1",
|
|
104
104
|
"zod": "^4.4.3"
|
|
105
105
|
},
|
|
106
106
|
"peerDependencies": {
|
|
107
|
-
"@fjall/components-infrastructure": ">=
|
|
107
|
+
"@fjall/components-infrastructure": ">=13.0.0 <14.0.0"
|
|
108
108
|
},
|
|
109
109
|
"peerDependenciesMeta": {
|
|
110
110
|
"@fjall/components-infrastructure": {
|