@fjall/deploy-core 2.27.0 → 2.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.minified +1 -1
- package/dist/src/aws/organisations/backup.d.ts +7 -2
- package/dist/src/aws/organisations/backup.js +2 -2
- package/dist/src/aws/organisations/index.d.ts +1 -1
- package/dist/src/aws/organisations/index.js +1 -1
- package/dist/src/aws/organisations/oidcProvider.d.ts +37 -0
- package/dist/src/aws/organisations/oidcProvider.js +1 -1
- package/dist/src/aws/organisations/organisation.d.ts +21 -0
- package/dist/src/aws/organisations/organisation.js +1 -1
- package/dist/src/aws/utils/cloudformationEventHelpers.d.ts +45 -0
- package/dist/src/aws/utils/cloudformationEventHelpers.js +1 -1
- package/dist/src/aws/utils/cloudformationEventTypes.d.ts +1 -1
- package/dist/src/aws/utils/cloudformationEvents.d.ts +2 -1
- package/dist/src/aws/utils/cloudformationEvents.js +1 -1
- package/dist/src/aws/utils/stackStatus.js +1 -1
- package/dist/src/index.d.ts +16 -3
- package/dist/src/index.js +1 -1
- package/dist/src/orchestration/activeDeploymentGuard.d.ts +41 -0
- package/dist/src/orchestration/activeDeploymentGuard.js +8 -4
- package/dist/src/orchestration/application/applicationDeploy.d.ts +9 -0
- package/dist/src/orchestration/application/applicationDeploy.js +1 -1
- package/dist/src/orchestration/application/applicationDeployHelpers.d.ts +20 -3
- package/dist/src/orchestration/application/applicationDeployHelpers.js +3 -3
- package/dist/src/orchestration/application/applicationDestroy.js +1 -1
- package/dist/src/orchestration/application/approvalGate.d.ts +15 -1
- package/dist/src/orchestration/application/approvalGate.js +1 -1
- package/dist/src/orchestration/application/destructionGate.d.ts +164 -0
- package/dist/src/orchestration/application/destructionGate.js +5 -0
- package/dist/src/orchestration/application/dockerBuildHelper.js +1 -1
- package/dist/src/orchestration/application/leaseGate.d.ts +30 -0
- package/dist/src/orchestration/application/leaseGate.js +1 -0
- package/dist/src/orchestration/application/openNextBuild.d.ts +1 -1
- package/dist/src/orchestration/application/openNextBuild.js +3 -3
- package/dist/src/orchestration/application/plan/approvalToken.d.ts +15 -0
- package/dist/src/orchestration/application/plan/approvalToken.js +1 -1
- package/dist/src/orchestration/application/plan/changeSetEscalation.d.ts +46 -0
- package/dist/src/orchestration/application/plan/changeSetEscalation.js +1 -0
- package/dist/src/orchestration/application/plan/computeDeployPlan.d.ts +13 -0
- package/dist/src/orchestration/application/plan/computeDeployPlan.js +1 -1
- package/dist/src/orchestration/application/plan/index.d.ts +4 -1
- package/dist/src/orchestration/application/plan/index.js +1 -1
- package/dist/src/orchestration/application/plan/loadDeployPlan.d.ts +32 -0
- package/dist/src/orchestration/application/plan/loadDeployPlan.js +1 -0
- package/dist/src/orchestration/application/plan/pinnedNames.d.ts +31 -0
- package/dist/src/orchestration/application/plan/pinnedNames.js +1 -0
- package/dist/src/orchestration/application/plan/registryOverlay.d.ts +83 -0
- package/dist/src/orchestration/application/plan/registryOverlay.js +1 -0
- package/dist/src/orchestration/application/plan/renderDeployPlan.d.ts +4 -1
- package/dist/src/orchestration/application/plan/renderDeployPlan.js +1 -1
- package/dist/src/orchestration/application/plan/types.d.ts +31 -0
- package/dist/src/orchestration/application/plan/types.js +1 -0
- package/dist/src/orchestration/builders/frameworkRegistry.js +1 -1
- package/dist/src/orchestration/builders/index.d.ts +1 -0
- package/dist/src/orchestration/builders/index.js +1 -1
- package/dist/src/orchestration/builders/openNextBuilder.js +1 -1
- package/dist/src/orchestration/builders/staticSiteBuilder.d.ts +27 -0
- package/dist/src/orchestration/builders/staticSiteBuilder.js +2 -0
- package/dist/src/orchestration/contextHelpers.d.ts +37 -1
- package/dist/src/orchestration/contextHelpers.js +1 -1
- package/dist/src/orchestration/drift/classifyDriftFailure.d.ts +31 -0
- package/dist/src/orchestration/drift/classifyDriftFailure.js +1 -0
- package/dist/src/orchestration/drift/detectStackDrift.d.ts +37 -0
- package/dist/src/orchestration/drift/detectStackDrift.js +1 -0
- package/dist/src/orchestration/drift/driftPreFlight.d.ts +73 -0
- package/dist/src/orchestration/drift/driftPreFlight.js +7 -0
- package/dist/src/orchestration/drift/driftProbe.d.ts +113 -0
- package/dist/src/orchestration/drift/driftProbe.js +1 -0
- package/dist/src/orchestration/drift/driftSuspectJournal.d.ts +40 -0
- package/dist/src/orchestration/drift/driftSuspectJournal.js +1 -0
- package/dist/src/orchestration/drift/preFlightGate.d.ts +44 -0
- package/dist/src/orchestration/drift/preFlightGate.js +2 -0
- package/dist/src/orchestration/index.d.ts +19 -0
- package/dist/src/orchestration/index.js +1 -1
- package/dist/src/orchestration/organisation/cascadeDestroyHelpers.d.ts +7 -0
- package/dist/src/orchestration/organisation/cascadeDestroyHelpers.js +1 -1
- package/dist/src/orchestration/organisation/cascadeHelpers.js +1 -1
- package/dist/src/orchestration/organisation/organisationDestroy.js +3 -3
- package/dist/src/orchestration/organisationDeploy/infraSteps.d.ts +8 -1
- package/dist/src/orchestration/organisationDeploy/infraSteps.js +1 -1
- package/dist/src/orchestration/organisationDeploy/orgCascadeDeploy.js +5 -5
- package/dist/src/orchestration/organisationDeploy/orgContext.d.ts +21 -2
- package/dist/src/orchestration/organisationDeploy/orgContext.js +1 -1
- package/dist/src/orchestration/organisationDeploy/singleComponentDeploy.js +1 -1
- package/dist/src/orchestration/remediation/driftRepairGate.d.ts +66 -0
- package/dist/src/orchestration/remediation/driftRepairGate.js +1 -0
- package/dist/src/orchestration/remediation/forensicsCapture.d.ts +49 -0
- package/dist/src/orchestration/remediation/forensicsCapture.js +1 -0
- package/dist/src/orchestration/remediation/forgetResource.d.ts +423 -0
- package/dist/src/orchestration/remediation/forgetResource.js +1 -0
- package/dist/src/orchestration/remediation/pinRemediation.d.ts +121 -0
- package/dist/src/orchestration/remediation/pinRemediation.js +1 -0
- package/dist/src/orchestration/remediation/postFailureRepairOffer.d.ts +77 -0
- package/dist/src/orchestration/remediation/postFailureRepairOffer.js +14 -0
- package/dist/src/orchestration/remediation/recreatePreFlight.d.ts +47 -0
- package/dist/src/orchestration/remediation/recreatePreFlight.js +1 -0
- package/dist/src/orchestration/remediation/recreateResource.d.ts +110 -0
- package/dist/src/orchestration/remediation/recreateResource.js +1 -0
- package/dist/src/orchestration/remediation/remediationJournal.d.ts +88 -0
- package/dist/src/orchestration/remediation/remediationJournal.js +2 -0
- package/dist/src/orchestration/remediation/removalUpdate.d.ts +135 -0
- package/dist/src/orchestration/remediation/removalUpdate.js +1 -0
- package/dist/src/orchestration/remediation/retainFlip.d.ts +294 -0
- package/dist/src/orchestration/remediation/retainFlip.js +1 -0
- package/dist/src/orchestration/spawnHelpers.d.ts +9 -0
- package/dist/src/orchestration/spawnHelpers.js +1 -1
- package/dist/src/services/application/ApplicationStackService.d.ts +5 -3
- package/dist/src/services/application/ApplicationStackService.js +1 -1
- package/dist/src/services/application/applicationStackHelpers.d.ts +8 -6
- package/dist/src/services/application/applicationStackHelpers.js +3 -3
- package/dist/src/services/index.d.ts +2 -2
- package/dist/src/services/index.js +1 -1
- package/dist/src/services/infrastructure/CdkEventMonitoring.d.ts +15 -0
- package/dist/src/services/infrastructure/CdkEventMonitoring.js +1 -1
- package/dist/src/services/infrastructure/CdkOutputAnalyser.d.ts +8 -0
- package/dist/src/services/infrastructure/CdkOutputAnalyser.js +2 -1
- package/dist/src/services/infrastructure/CdkService.js +3 -3
- package/dist/src/services/infrastructure/CfnRegistryService.d.ts +68 -0
- package/dist/src/services/infrastructure/CfnRegistryService.js +1 -0
- package/dist/src/services/infrastructure/CloudFormationService.d.ts +5 -2
- package/dist/src/services/infrastructure/CloudFormationService.js +1 -1
- package/dist/src/services/infrastructure/EcsServiceResolver.d.ts +23 -3
- package/dist/src/services/infrastructure/EcsServiceResolver.js +1 -1
- package/dist/src/services/infrastructure/cfnRegistrySeed.d.ts +10 -0
- package/dist/src/services/infrastructure/cfnRegistrySeed.js +1 -0
- package/dist/src/services/infrastructure/changeSetProbe.d.ts +88 -0
- package/dist/src/services/infrastructure/changeSetProbe.js +1 -0
- package/dist/src/services/infrastructure/index.d.ts +2 -0
- package/dist/src/services/infrastructure/index.js +1 -1
- package/dist/src/types/callbackKeys.d.ts +1 -1
- package/dist/src/types/callbackKeys.js +1 -1
- package/dist/src/types/callbacks.d.ts +22 -0
- package/dist/src/types/config/entitlements.d.ts +9 -0
- package/dist/src/types/config/orgConfig.d.ts +6 -0
- package/dist/src/types/deployEvent.d.ts +10 -3
- package/dist/src/types/deployEvent.js +1 -1
- package/dist/src/types/deploymentEventSchema.d.ts +1 -0
- package/dist/src/types/deploymentEventSchema.js +1 -1
- package/dist/src/types/destruction.d.ts +212 -0
- package/dist/src/types/destruction.js +1 -0
- package/dist/src/types/detection/patternTypes.d.ts +9 -4
- package/dist/src/types/detection/patternTypes.js +1 -1
- package/dist/src/types/drift.d.ts +72 -0
- package/dist/src/types/drift.js +1 -0
- package/dist/src/types/frameworkBuilder.d.ts +14 -0
- package/dist/src/types/index.d.ts +44 -4
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/operations.d.ts +2 -1
- package/dist/src/types/params.d.ts +142 -0
- package/dist/src/types/remediation.d.ts +126 -0
- package/dist/src/types/remediation.js +1 -0
- package/package.json +6 -4
|
@@ -6,7 +6,9 @@ import type { ApiClientInterface } from "./apiClient.js";
|
|
|
6
6
|
import type { OrgConfig } from "./config/orgConfig.js";
|
|
7
7
|
import type { DockerProvider } from "../orchestration/dockerInterface.js";
|
|
8
8
|
import type { DomainDeployProvider } from "../orchestration/domainInterface.js";
|
|
9
|
+
import type { PinRemediationReport } from "../orchestration/remediation/pinRemediation.js";
|
|
9
10
|
import type { ApprovalGate, ApprovalGatePlanDetail } from "./approval.js";
|
|
11
|
+
import type { DestructionConsent, DestructionConsentGate, DestructionOutcome, DestructionTicket } from "./destruction.js";
|
|
10
12
|
import type { FailureAnalysis } from "@fjall/util/aws";
|
|
11
13
|
import type { DockerBuildSecretRef } from "@fjall/util/manifest/schemas";
|
|
12
14
|
export interface DeployParams {
|
|
@@ -76,6 +78,26 @@ export interface DeployParams {
|
|
|
76
78
|
* the gate even when this is omitted.
|
|
77
79
|
*/
|
|
78
80
|
approvalGate?: ApprovalGate;
|
|
81
|
+
/**
|
|
82
|
+
* Optional interactive destruction-consent resolver — the ceremony seam for
|
|
83
|
+
* the UNCONDITIONAL destruction gate (mirrors `approvalGate`'s injected-
|
|
84
|
+
* resolver mechanism). Consulted ONLY when the gate ticketed destructive
|
|
85
|
+
* rows and no `options.destructionConsents` were supplied; the returned
|
|
86
|
+
* pairs are re-evaluated engine-side (exact-match + digest TOCTOU), so the
|
|
87
|
+
* resolver can never widen consent beyond what the `--remediate` flags
|
|
88
|
+
* could. Omitted ⇒ the gate withholds fail-closed exactly as before. No
|
|
89
|
+
* flag can disengage the gate; this only changes HOW consent is obtained.
|
|
90
|
+
*/
|
|
91
|
+
destructionConsentGate?: DestructionConsentGate;
|
|
92
|
+
/**
|
|
93
|
+
* The user's fjall infrastructure config source, consumed by the pin arm
|
|
94
|
+
* when a destructive change is consented with `pin`: the engine composes an
|
|
95
|
+
* edit-ready codemod against it and returns the result for surface-side
|
|
96
|
+
* write-back — the engine never writes the file. Absent (worker surfaces
|
|
97
|
+
* with no config checkout) the pin arm degrades to report-only outcomes
|
|
98
|
+
* carrying the exact config lines.
|
|
99
|
+
*/
|
|
100
|
+
infrastructureSource?: InfrastructureSource;
|
|
79
101
|
/**
|
|
80
102
|
* Asked before the post-deploy database-endpoint reconcile restarts the
|
|
81
103
|
* application's ECS services (fires only when a deploy replaced the
|
|
@@ -85,6 +107,34 @@ export interface DeployParams {
|
|
|
85
107
|
* non-interactive CLI) must not block on consent.
|
|
86
108
|
*/
|
|
87
109
|
confirmDatabaseEndpointRestart?: (request: DatabaseEndpointRestartRequest) => Promise<boolean>;
|
|
110
|
+
/**
|
|
111
|
+
* Optional stack-boundary lease gate (§5.3). Invoked immediately before each
|
|
112
|
+
* stack's first mutating CloudFormation operation. The engine passes the
|
|
113
|
+
* stack name and the caller's shutdown signal; the resolver returns the lease
|
|
114
|
+
* verdict:
|
|
115
|
+
* - "denied" ⇒ the deployment's lease is gone (swept, superseded, adopted
|
|
116
|
+
* by another runner, or force-released). The engine aborts BEFORE
|
|
117
|
+
* starting that stack with a typed `LeaseDeniedError`; already-completed
|
|
118
|
+
* stacks stand.
|
|
119
|
+
* - "unknown" ⇒ the liveness probe could not reach the server. Fail OPEN
|
|
120
|
+
* and proceed — leases are a liveness signal, not a safety gate, and
|
|
121
|
+
* CloudFormation's own ClientRequestToken is the fencing backstop.
|
|
122
|
+
* - "ok" ⇒ proceed.
|
|
123
|
+
* Omitted ⇒ no gate (fully backward-compatible). The CLI wires this to the
|
|
124
|
+
* DeploymentTracker's on-demand heartbeat; the worker omits it.
|
|
125
|
+
*/
|
|
126
|
+
assertLeaseForStack?: (stackName: string, abortSignal?: AbortSignal) => Promise<StackLeaseVerdict>;
|
|
127
|
+
}
|
|
128
|
+
/** Verdict of the stack-boundary lease gate (§5.3 heartbeat protocol). */
|
|
129
|
+
export type StackLeaseVerdict = "ok" | "denied" | "unknown";
|
|
130
|
+
/**
|
|
131
|
+
* The infrastructure config source handed to the pin arm — the surface that
|
|
132
|
+
* owns the config checkout supplies both halves so codemod diagnostics and
|
|
133
|
+
* the eventual write-back target the same file.
|
|
134
|
+
*/
|
|
135
|
+
export interface InfrastructureSource {
|
|
136
|
+
content: string;
|
|
137
|
+
filePath: string;
|
|
88
138
|
}
|
|
89
139
|
/**
|
|
90
140
|
* Context handed to `confirmDatabaseEndpointRestart` so an interactive
|
|
@@ -182,6 +232,22 @@ export interface DeployOptions {
|
|
|
182
232
|
* validated through `DockerBuildSecretRefSchema` (CLI) before it reaches here.
|
|
183
233
|
*/
|
|
184
234
|
flagBuildSecrets?: readonly DockerBuildSecretRef[];
|
|
235
|
+
/**
|
|
236
|
+
* Destruction-gate consents: exact, case-sensitive `{physicalName, verb}`
|
|
237
|
+
* pairs from the repeatable `--remediate <name>=<verb>` / `--allow-replace
|
|
238
|
+
* <name>` flags (or a surface's pre-authorisation). The unconditional gate
|
|
239
|
+
* fail-closes unless EVERY ticketed resource is covered; surplus, misspelt
|
|
240
|
+
* or wrong-verb consents fail closed with a verdict table. `autoApprove`,
|
|
241
|
+
* `skipConfirmation`, `force` and approval tokens never satisfy the gate.
|
|
242
|
+
*/
|
|
243
|
+
destructionConsents?: readonly DestructionConsent[];
|
|
244
|
+
/**
|
|
245
|
+
* The `ticketDigest` the consents were minted against (webapp pre-auth /
|
|
246
|
+
* resumed runs). Re-verified against the digest recomputed at apply time;
|
|
247
|
+
* a mismatch fail-closes every consent (TOCTOU discipline). Flag-minted
|
|
248
|
+
* consents omit it — they are supplied at apply time by definition.
|
|
249
|
+
*/
|
|
250
|
+
destructionConsentDigest?: string;
|
|
185
251
|
}
|
|
186
252
|
export type DeploymentType = "application" | "organisation";
|
|
187
253
|
export interface DeployResult {
|
|
@@ -265,6 +331,73 @@ export interface DeployResult {
|
|
|
265
331
|
* resume token never computed one).
|
|
266
332
|
*/
|
|
267
333
|
planDetail?: ApprovalGatePlanDetail;
|
|
334
|
+
/**
|
|
335
|
+
* Destruction-gate: set when the unconditional gate withheld the deploy —
|
|
336
|
+
* the plan contained destructive rows without full named consent (or a
|
|
337
|
+
* consented verb has no execution arm yet). Nothing was mutated. Surfaces
|
|
338
|
+
* map this to exit code 4 (distinct from rejection/failure).
|
|
339
|
+
*/
|
|
340
|
+
destructionPending?: boolean;
|
|
341
|
+
/**
|
|
342
|
+
* Destruction-gate: the ticket enumerating every destructive resource, its
|
|
343
|
+
* finding, cause and legal verbs. Present with `destructionPending`, and on
|
|
344
|
+
* an `awaitingApproval` plan-only result whose plan carries destructive
|
|
345
|
+
* rows (so a plan consumer can mint consents against `ticketDigest`).
|
|
346
|
+
*/
|
|
347
|
+
destructionTicket?: DestructionTicket;
|
|
348
|
+
/**
|
|
349
|
+
* Destruction-gate: WHY the deploy was withheld. Present with
|
|
350
|
+
* `destructionPending`. Surfaces branch on this so a user who consented
|
|
351
|
+
* (`consent-not-executable`) or declined (`declined`) is never shown the
|
|
352
|
+
* generic "requires named consent" message or told to redo their consent.
|
|
353
|
+
*/
|
|
354
|
+
destructionOutcome?: DestructionOutcome;
|
|
355
|
+
/**
|
|
356
|
+
* Destruction-gate: the halt/decline reason lines (identifier-only,
|
|
357
|
+
* pre-masked by construction) — e.g. "verb 'repair' is accepted vocabulary
|
|
358
|
+
* but not yet executable in this release for resource-deleted". Present
|
|
359
|
+
* with `destructionPending`; may be empty.
|
|
360
|
+
*/
|
|
361
|
+
destructionHaltReasons?: string[];
|
|
362
|
+
/**
|
|
363
|
+
* Destruction-gate: a fresh approval token re-minted at withhold time for
|
|
364
|
+
* approval-gated runs, bound to the withheld run's assembly digest with the
|
|
365
|
+
* consent-ceremony TTL (`DESTRUCTION_RESUME_TTL_MS`). The original approval
|
|
366
|
+
* token's 15-minute TTL expires during a ceremony that can take hours; the
|
|
367
|
+
* consented re-queue MUST carry this token instead. Present with
|
|
368
|
+
* `destructionPending` only when the run was approval-gated. NOT a secret —
|
|
369
|
+
* digest-bound capability, same trust model as `approvalToken`.
|
|
370
|
+
*/
|
|
371
|
+
destructionResumeToken?: string;
|
|
372
|
+
/**
|
|
373
|
+
* Destruction-gate: ISO expiry of `destructionResumeToken`. Present
|
|
374
|
+
* together with it.
|
|
375
|
+
*/
|
|
376
|
+
destructionResumeExpiresAt?: string;
|
|
377
|
+
/**
|
|
378
|
+
* Pin arm: set when consented `pin` verb(s) ran the pre-bootstrap
|
|
379
|
+
* live-value probes and the deploy stopped for config write-back. Nothing
|
|
380
|
+
* was mutated — CloudFormation never ran. Surfaces render `pinReport` and
|
|
381
|
+
* re-run the deploy once the config change lands (the plan then carries no
|
|
382
|
+
* pinned rows). Distinct from `destructionPending` (consent withheld) —
|
|
383
|
+
* pin consent was GIVEN and its arm executed.
|
|
384
|
+
*/
|
|
385
|
+
pinPending?: boolean;
|
|
386
|
+
/**
|
|
387
|
+
* Pin arm: per-resource outcomes, plus the composed `modifiedContent` when
|
|
388
|
+
* at least one target reached edit-ready. Present with `pinPending`. The
|
|
389
|
+
* surface that supplied `DeployParams.infrastructureSource` owns writing
|
|
390
|
+
* `modifiedContent` back to the config file.
|
|
391
|
+
*/
|
|
392
|
+
pinReport?: PinRemediationReport;
|
|
393
|
+
/**
|
|
394
|
+
* Pin arm: count of consented NON-pin change(s) (e.g. recreate rows) the
|
|
395
|
+
* pin stop deferred — they did not run in this deploy and re-consent
|
|
396
|
+
* against the recomputed plan on the next one. Present with `pinPending`;
|
|
397
|
+
* 0 when the consent set was pure-pin. Surfaces MUST NOT claim "no
|
|
398
|
+
* --remediate needed" on the re-run when this is non-zero.
|
|
399
|
+
*/
|
|
400
|
+
pinDeferredConsents?: number;
|
|
268
401
|
}
|
|
269
402
|
/**
|
|
270
403
|
* Parameters for the destroy entry point.
|
|
@@ -302,6 +435,15 @@ export interface DestroyParams {
|
|
|
302
435
|
* (mirrors DeployParams.abortSignal).
|
|
303
436
|
*/
|
|
304
437
|
abortSignal?: AbortSignal;
|
|
438
|
+
/**
|
|
439
|
+
* Optional stack-boundary lease gate (§5.3) — the destroy twin of
|
|
440
|
+
* `DeployParams.assertLeaseForStack`, same resolver and verdict semantics:
|
|
441
|
+
* "denied" aborts BEFORE the stack's DeleteStack (already-destroyed stacks
|
|
442
|
+
* stand), "unknown" fails open, absent ⇒ no gate. Consulted immediately
|
|
443
|
+
* before each stack's DeleteStack; a parallel destroy group gates once on
|
|
444
|
+
* entry.
|
|
445
|
+
*/
|
|
446
|
+
assertLeaseForStack?: DeployParams["assertLeaseForStack"];
|
|
305
447
|
}
|
|
306
448
|
export interface DestroyOptions {
|
|
307
449
|
/** Skip interactive confirmation prompts */
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The remediation-journal contract for the two-deploy `forget` orchestration
|
|
3
|
+
* and its snapshot-flip `recreate` variant (drift-remediation plan § 3.2 /
|
|
4
|
+
* Phase 7). Declared ONCE here; the CLI re-exports, never redeclares (coupled
|
|
5
|
+
* discriminated unions share a source at 2 occurrences).
|
|
6
|
+
*
|
|
7
|
+
* Phases are strictly ordered: `captured → flip-verified → flip-applied →
|
|
8
|
+
* removal-applied → done`. Every phase re-derives its precondition from live
|
|
9
|
+
* state before acting, so a lost journal degrades to correct re-detection via
|
|
10
|
+
* the in-template `fjall:forget` / `fjall:recreate` marker [G3] — the journal
|
|
11
|
+
* is the local resume record and audit trail, not the sole authority.
|
|
12
|
+
* Exception: targets advanced via the FLIPLESS fast-path (`fliplessTargets` —
|
|
13
|
+
* live policies already satisfied the flip spec, so no UpdateStack ran and no
|
|
14
|
+
* marker was stamped; 2026-07-12 live defect #5) and via the
|
|
15
|
+
* FLIPLESS-BY-NECESSITY path (`fliplessByNecessity` — the flip was
|
|
16
|
+
* structurally impossible and the target verified physically deleted; same
|
|
17
|
+
* incident, second direction) carry no AWS-side resume state — their
|
|
18
|
+
* lost-journal degradation is re-consent at the ceremony, never a silent
|
|
19
|
+
* skip.
|
|
20
|
+
*/
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
export declare const REMEDIATION_PHASES: readonly ["captured", "flip-verified", "flip-applied", "removal-applied", "done"];
|
|
23
|
+
export declare const RemediationPhaseSchema: z.ZodEnum<{
|
|
24
|
+
captured: "captured";
|
|
25
|
+
"flip-verified": "flip-verified";
|
|
26
|
+
"flip-applied": "flip-applied";
|
|
27
|
+
"removal-applied": "removal-applied";
|
|
28
|
+
done: "done";
|
|
29
|
+
}>;
|
|
30
|
+
export type RemediationPhase = z.infer<typeof RemediationPhaseSchema>;
|
|
31
|
+
/** Ordinal comparison for phase progression checks. */
|
|
32
|
+
export declare function remediationPhaseRank(phase: RemediationPhase): number;
|
|
33
|
+
export declare const RemediationTargetSchema: z.ZodObject<{
|
|
34
|
+
logicalId: z.ZodString;
|
|
35
|
+
resourceType: z.ZodString;
|
|
36
|
+
physicalId: z.ZodString;
|
|
37
|
+
}, z.core.$strict>;
|
|
38
|
+
export type RemediationTarget = z.infer<typeof RemediationTargetSchema>;
|
|
39
|
+
/**
|
|
40
|
+
* Placeholder physicalId for a target whose live physical id is unknown —
|
|
41
|
+
* an adopted foreign-op target recovered from the `fjall:forget` marker, or
|
|
42
|
+
* a confirmed finding whose membership listing could not resolve an id. The
|
|
43
|
+
* shape is structurally recognisable so probe paths can refuse to treat it
|
|
44
|
+
* as an owning-service address: probing `MyStack/MyKey` against
|
|
45
|
+
* kms:DescribeKey returns an authoritative NotFound for a resource that may
|
|
46
|
+
* be live. Coupled values, one home — every minting site routes through this
|
|
47
|
+
* builder: the CLI's journal targets, the drift-repair ticket's [G6]
|
|
48
|
+
* `physicalName` fallback (which must byte-agree with those targets so the
|
|
49
|
+
* consent covers what is operated on), and the deploy destruction ticket's
|
|
50
|
+
* unpinned-name fallback (the same resource renders on both tickets in the
|
|
51
|
+
* blocked-deploy → repair flow); deploy-core's closure probe recognises the
|
|
52
|
+
* shape via the predicate below.
|
|
53
|
+
*/
|
|
54
|
+
export declare function remediationPlaceholderPhysicalId(stackName: string, logicalId: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* True when the target's physicalId is the placeholder minted by
|
|
57
|
+
* `remediationPlaceholderPhysicalId` — never a probeable address.
|
|
58
|
+
*/
|
|
59
|
+
export declare function isRemediationPlaceholderPhysicalId(target: RemediationTarget, stackName: string): boolean;
|
|
60
|
+
/** Proof record that the retain flip was verified metadata-only (§3.2 ph 2). */
|
|
61
|
+
export declare const RemediationFlipProofSchema: z.ZodObject<{
|
|
62
|
+
diffGuardPassed: z.ZodBoolean;
|
|
63
|
+
changeSetMetadataOnly: z.ZodBoolean;
|
|
64
|
+
noChanges: z.ZodBoolean;
|
|
65
|
+
provenAt: z.ZodString;
|
|
66
|
+
}, z.core.$strict>;
|
|
67
|
+
export type RemediationFlipProof = z.infer<typeof RemediationFlipProofSchema>;
|
|
68
|
+
/**
|
|
69
|
+
* The verbs with an orchestrated surgery arm. `forget` retains-and-abandons
|
|
70
|
+
* (converge removes the declaration); `recreate` snapshot-flips and surgically
|
|
71
|
+
* removes so the converge re-CREATEs under the same pinned name. The opId
|
|
72
|
+
* derivation deliberately excludes the verb — both orchestrators verb-guard
|
|
73
|
+
* the journal they read, failing closed on a cross-verb collision.
|
|
74
|
+
*/
|
|
75
|
+
export declare const RemediationVerbWithSurgerySchema: z.ZodEnum<{
|
|
76
|
+
forget: "forget";
|
|
77
|
+
recreate: "recreate";
|
|
78
|
+
}>;
|
|
79
|
+
export type RemediationVerbWithSurgery = z.infer<typeof RemediationVerbWithSurgerySchema>;
|
|
80
|
+
export declare const RemediationJournalRecordSchema: z.ZodObject<{
|
|
81
|
+
version: z.ZodLiteral<1>;
|
|
82
|
+
opId: z.ZodString;
|
|
83
|
+
verb: z.ZodEnum<{
|
|
84
|
+
forget: "forget";
|
|
85
|
+
recreate: "recreate";
|
|
86
|
+
}>;
|
|
87
|
+
accountId: z.ZodString;
|
|
88
|
+
region: z.ZodString;
|
|
89
|
+
stackName: z.ZodString;
|
|
90
|
+
appName: z.ZodOptional<z.ZodString>;
|
|
91
|
+
targets: z.ZodArray<z.ZodObject<{
|
|
92
|
+
logicalId: z.ZodString;
|
|
93
|
+
resourceType: z.ZodString;
|
|
94
|
+
physicalId: z.ZodString;
|
|
95
|
+
}, z.core.$strict>>;
|
|
96
|
+
phase: z.ZodEnum<{
|
|
97
|
+
captured: "captured";
|
|
98
|
+
"flip-verified": "flip-verified";
|
|
99
|
+
"flip-applied": "flip-applied";
|
|
100
|
+
"removal-applied": "removal-applied";
|
|
101
|
+
done: "done";
|
|
102
|
+
}>;
|
|
103
|
+
createdAt: z.ZodString;
|
|
104
|
+
updatedAt: z.ZodString;
|
|
105
|
+
liveTemplateDigest: z.ZodOptional<z.ZodString>;
|
|
106
|
+
forensicsPath: z.ZodOptional<z.ZodString>;
|
|
107
|
+
proof: z.ZodOptional<z.ZodObject<{
|
|
108
|
+
diffGuardPassed: z.ZodBoolean;
|
|
109
|
+
changeSetMetadataOnly: z.ZodBoolean;
|
|
110
|
+
noChanges: z.ZodBoolean;
|
|
111
|
+
provenAt: z.ZodString;
|
|
112
|
+
}, z.core.$strict>>;
|
|
113
|
+
consentedPhysicalNames: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
114
|
+
retainedByRedeclaration: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
115
|
+
fliplessTargets: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
116
|
+
fliplessByNecessity: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
117
|
+
recreatedResources: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
118
|
+
snapshotPolicies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
|
|
119
|
+
Snapshot: "Snapshot";
|
|
120
|
+
Delete: "Delete";
|
|
121
|
+
}>>>;
|
|
122
|
+
orphanedResources: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
123
|
+
unverifiedRemovals: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
124
|
+
completedAt: z.ZodOptional<z.ZodString>;
|
|
125
|
+
}, z.core.$strict>;
|
|
126
|
+
export type RemediationJournalRecord = z.infer<typeof RemediationJournalRecordSchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as e}from"zod";const t=["captured","flip-verified","flip-applied","removal-applied","done"],r=e.enum(t);function p(i){return t.indexOf(i)}const o=e.object({logicalId:e.string().min(1),resourceType:e.string().min(1),physicalId:e.string().min(1)}).strict();function a(i,n){return`${i}/${n}`}function m(i,n){return i.physicalId===a(n,i.logicalId)}const s=e.object({diffGuardPassed:e.boolean(),changeSetMetadataOnly:e.boolean(),noChanges:e.boolean(),provenAt:e.string().min(1)}).strict(),l=e.enum(["forget","recreate"]),d=e.object({version:e.literal(1),opId:e.string().min(1),verb:l,accountId:e.string().min(1),region:e.string().min(1),stackName:e.string().min(1),appName:e.string().min(1).optional(),targets:e.array(o).min(1),phase:r,createdAt:e.string().min(1),updatedAt:e.string().min(1),liveTemplateDigest:e.string().min(1).optional(),forensicsPath:e.string().min(1).optional(),proof:s.optional(),consentedPhysicalNames:e.array(e.string()).optional(),retainedByRedeclaration:e.array(e.string().min(1)).optional(),fliplessTargets:e.array(e.string().min(1)).optional(),fliplessByNecessity:e.array(e.string().min(1)).optional(),recreatedResources:e.array(e.string().min(1)).optional(),snapshotPolicies:e.record(e.string().min(1),e.enum(["Snapshot","Delete"])).optional(),orphanedResources:e.array(e.string().min(1)).optional(),unverifiedRemovals:e.array(e.string().min(1)).optional(),completedAt:e.string().min(1).optional()}).strict();export{t as REMEDIATION_PHASES,s as RemediationFlipProofSchema,d as RemediationJournalRecordSchema,r as RemediationPhaseSchema,o as RemediationTargetSchema,l as RemediationVerbWithSurgerySchema,m as isRemediationPlaceholderPhysicalId,p as remediationPhaseRank,a as remediationPlaceholderPhysicalId};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/deploy-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.30.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",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"scripts": {
|
|
49
49
|
"clean": "rm -rf ./dist ./sourcemaps",
|
|
50
50
|
"build": "npm run clean && tsc && node ../scripts/minify-dist.mjs dist",
|
|
51
|
+
"prepack": "node ../scripts/check-dist-freshness.mjs",
|
|
51
52
|
"watch": "npm run build && tsc --watch --preserveWatchOutput",
|
|
52
53
|
"watch:only": "tsc --watch --preserveWatchOutput",
|
|
53
54
|
"typecheck": "tsc --noEmit",
|
|
@@ -76,14 +77,15 @@
|
|
|
76
77
|
"@aws-sdk/client-kms": "^3.1065.0",
|
|
77
78
|
"@aws-sdk/client-organizations": "^3.1038.0",
|
|
78
79
|
"@aws-sdk/client-ram": "^3.1038.0",
|
|
80
|
+
"@aws-sdk/client-rds": "^3.1038.0",
|
|
79
81
|
"@aws-sdk/client-s3": "^3.1038.0",
|
|
80
82
|
"@aws-sdk/client-secrets-manager": "^3.1038.0",
|
|
81
83
|
"@aws-sdk/client-sqs": "^3.1067.0",
|
|
82
84
|
"@aws-sdk/client-ssm": "^3.1038.0",
|
|
83
85
|
"@aws-sdk/client-sso-admin": "^3.1038.0",
|
|
84
86
|
"@aws-sdk/client-sts": "^3.1038.0",
|
|
85
|
-
"@fjall/generator": "^2.
|
|
86
|
-
"@fjall/util": "^2.
|
|
87
|
+
"@fjall/generator": "^2.30.0",
|
|
88
|
+
"@fjall/util": "^2.30.0",
|
|
87
89
|
"@smithy/node-http-handler": "^4.6.1",
|
|
88
90
|
"aws-cdk": "^2.1128.1",
|
|
89
91
|
"tsx": "^4.21.0",
|
|
@@ -94,5 +96,5 @@
|
|
|
94
96
|
"typescript": "^6.0.3",
|
|
95
97
|
"vitest": "^4.1.5"
|
|
96
98
|
},
|
|
97
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "ec35b16db566dfa5feb714c16f132c55b4663c86"
|
|
98
100
|
}
|