Skip to content
cdkd

Scenario Coverage Matrix

Run vp run scenario-coverage to regenerate.

92 / 92 canonical scenarios have at least one integ fixture exercising them. 194 / 287 integ fixtures carry a .scenarios.json sidecar (with 0+ tags); the rest are un-annotated and contributor-reviewed below.

How this is computed

Each tests/integration/<fixture>/.scenarios.json sidecar declares which canonical real-AWS regression patterns the fixture exercises. The canonical taxonomy lives in scripts/build-scenario-coverage-matrix.ts as KNOWN_SCENARIOS — sidecar tags outside the taxonomy are rejected at parse time so typos surface immediately.

Sidecar shape:

{
  "scenarios": ["vpc-lambda-eni-release", "nat-gateway-cleanup"]
}

Empty [] means "intentionally no canonical scenario applies to this fixture" (per-service smoke tests). Absent file means "not yet annotated" — surfaced in the un-annotated section below.

This report is a visibility tool, not a commit-time gate. Many cdkd fixtures legitimately exercise no canonical scenario, and forcing per-commit annotation would add friction without proportional value. Contrast with the provider-coverage matrix (docs/integ-coverage.md) which IS gated because the "is every registered SDK Provider exercised?" question has a structural answer.

Orphan scenarios

None. Every canonical scenario has at least one integ fixture tagged with it.

Per-scenario coverage (92 scenarios)

Scenario Description Integ Fixture(s)
apigateway-cors-preflight API Gateway CORS preflight (OPTIONS) handling — CDK auto-generates Method with both Integration.IntegrationResponses and MethodResponses arrays. apigateway
auto-import-cfn-generated-name cdkd import AUTO mode (no --resource, no --migrate-from-cloudformation) adopting a resource whose physical name CloudFormation GENERATED, after an upstream cdk deploy. Pins issue #1128: auto mode resolves ids by the template name property, then an aws:cdk:path tag walk that CANNOT match on real AWS (AWS rejects aws:-prefixed tag writes; CloudFormation keeps the value in template Metadata without promoting it to a tag), so a CFn-generated name returned not found until auto mode learned to consult DescribeStackResources. The fixture deliberately sets NO explicit physical name and passes NO override flag — both pre-existing import integs pass one of those and therefore never exercised this path, which is why the defect survived four rounds of #1091 tag-walk work. import-auto-mode
auto-import-composite-physical-id cdkd import AUTO mode adopting a resource whose cdkd physicalId is a COMPOSITE (` ) while CloudFormation's is a single bare segment (the table name). Pins issue #1651, the sibling of #1128 one layer down: #1128 fixed the RESOLUTION of a CFn-generated id, this is the provider REJECTING an id auto mode had already resolved — importTablesplit the bare form on
cc-api-getatt-enrichment-elasticache-replicationgroup CC-API attribute enrichment for AWS::ElastiCache::ReplicationGroup (no SDK provider): Fn::GetAtt(<RG>, PrimaryEndPoint.Address / ReaderEndPoint.* / ConfigurationEndPoint.* / ReadEndPoint.Addresses) must resolve to the real Redis endpoint via DescribeReplicationGroups, not fall through to the physicalId (the RG id). elasticache-replicationgroup-getatt
cc-api-getatt-enrichment-opensearch-domain CC-API attribute enrichment for AWS::OpenSearchService::Domain (no SDK provider): Fn::GetAtt(<Domain>, DomainEndpoint / Arn) must resolve to the real *.es.amazonaws.com endpoint / arn:aws:es:...:domain/... ARN via DescribeDomain, not fall through to the physicalId (the domain name). opensearch-domain-getatt
cc-api-getatt-enrichment-redshift-cluster CC-API attribute enrichment for AWS::Redshift::Cluster (no SDK provider): Fn::GetAtt(<Cluster>, Endpoint.Address / Endpoint.Port) must resolve to the real Redshift endpoint via DescribeClusters, not fall through to the physicalId (the cluster id). redshift-cluster-getatt
cdk-defensive-vpc-deps-relax CDK-defensive route DependsOn relaxation for VPC Lambda parallelization. bench-cdk-sample
cdkd-asset-storage cdkd-owned asset storage lifecycle against real AWS: cdkd bootstrap creates the asset bucket + container repo + per-region marker (default or custom --asset-bucket / --container-repo names), deploy-time asset-mode detection + publish redirection into the marker-named storage, and cdkd bootstrap --destroy marker-driven teardown with zero residue (issues #1002 / #1007 / #1010 / #1011). asset-auto-create
asset-bootstrap
asset-migration
gc-custom-asset-names
cdkd-asset-storage-import Import-driven adoption into a cdkd-assets region against real AWS (issue #1652): a stack deployed by the UPSTREAM cdk deploy (so AWS holds cdk-<qualifier>-assets-* everywhere, including the AWS::IAM::Policy that s3deploy.BucketDeployment grants on the asset bucket) is adopted with cdkd import --migrate-from-cloudformation; state must record the PRE-rewrite cdk-* values, cdkd diff must report a real UPDATE on that policy (pre-fix it classified NO_CHANGE because the rewrite reached state.properties), and the post-import cdkd deploy must leave the LIVE policy document naming the cdkd asset bucket. asset-migration
cdkd-gc cdkd gc garbage-collection precision against real AWS: whole-bucket state-file reference scan keeps every referenced asset, an unreferenced seeded object plus an unreferenced seeded ECR image are the only deletion candidates, --dry-run deletes nothing, --older-than age guard honored (issue #1012). Since issues #1792 / #1793 the ECR half is DISCRIMINATING rather than a re-run of the plain path: two live images are referenced only through WIDENED host forms — an UPPER-cased host carrying an UPPER-cased digest (collected yet unmatchable against ECR lower-case digests before the insert-time fold, so the live image was deleted) and the dual-stack FIPS <acct>.dkr-ecr-fips.<region>.on.aws form the grammar had missed entirely — and both must SURVIVE the run, since a missed reference deletes irreversibly. gc-custom-asset-names
cfn-fallback-cross-stack CloudFormation fallback for cross-stack references (issue #1697): a cdkd-deployed consumer references a producer stack managed by CloudFormation ONLY (no cdkd state record) — Fn::ImportValue via the ListExports fallback AND Fn::GetStackOutput via the DescribeStacks outputs fallback — plus the weak-reference contract (no imports[]/outputReads[] recorded) and the --no-cfn-fallback opt-out failing at resolve time. cross-stack-cfn-fallback
cfn-macro-expansion CloudFormation macro / Fn::Transform expansion via transient CFn changeset round-trip (SAM, AWS::Include, AWS::LanguageExtensions, custom macros). See docs/design/463-cfn-macros.md. macro-expansion
cloudfront-oai-attribute-enrichment CloudFront OAI S3CanonicalUserId attribute enrichment (the attribute is not on GetCloudFrontOriginAccessIdentity directly). s3-cloudfront
conditions-and-if CloudFormation Conditions section + resource-level Condition: key + Fn::If / Fn::Equals / Fn::And / Fn::Or / Fn::Not evaluated by cdkd itself. Two deploys flip a CDK-context-driven CfnParameter Default so the SAME stack is asserted in both settings: condition-gated resource creation (PRESENT vs ABSENT on AWS), Fn::If property + tag branch values reaching AWS, and Fn::If -> AWS::NoValue genuinely OMITTING a property. conditions-and-if
conditions-update-semantics Harder CloudFormation-Conditions-on-UPDATE semantics beyond the simple flip in conditions-and-if (which surfaced #840). A CDK-context phase flip (-c phase=a b) redeploys the SAME stack in place and asserts: a resource that MOVES gating conditions (IsPhaseA-gated -> condition-false -> DELETED) and its reverse (IsPhaseB-gated absent -> CREATED); Fn::If -> AWS::NoValue REMOVING a nested property block (SQS RedrivePolicy) on an in-place UPDATE (same physical id, not a replacement); a condition-gated OUTPUT present vs absent in cdkd state outputs; a DependsOn to a condition-EXCLUDED resource being dropped (the depender still deploys); and a Ref to a condition-excluded resource living inside another condition-excluded resource (both pruned together, no dangling-ref crash).
cross-cutting-deploy-destroy Broad real-AWS regression set (39+ resource VPC+NAT+CF+Lambda+SQS or comparable breadth). Refreshes the integ-broad gate. bench-ccapi
bench-cdk-sample
bench-sdk
full-stack-demo
lambda
microservices
multi-resource
custom-resource-async-poll Custom Resource backed by Lambda + cfn-response via S3 pre-signed URL polling. cloudfront-function-url
custom-resource-provider
destroy-interrupt
vpc-lambda-cr-race
custom-resource-getatt-data Custom Resource response Data consumed via Fn::GetAtt(CR, 'Data.<key>') / Fn::GetAtt(CR, '<key>') into ANOTHER resource's property (e.g. an SSM Parameter Value) — the fragile CR response-Data attribute path (#756 / #804: CR attributes only exist after the CR Lambda runs). Asserts the dependent's on-AWS value equals the value the CR handler returned, across multiple Data keys + an explicit dependent->CR dependency. A second custom resource carries the NoEcho: true arm (issue #2274) through the SIMPLE-HANDLER response shape, asserting both directions at once: the dependent's live SSM value is the real token, while the CR's attributes, the dependent's properties, state.outputs and the whole state blob hold none of it -- with the non-NoEcho resource above as the in-fixture negative control. custom-resource-getatt-data
deep-getatt-chain-resolution Long GetAtt chain where each resource POST-CREATE attribute (ARN / generated name only known after the AWS create call) feeds the next resource property, spanning a SDK + CC-API type mix. A wrong / late attribute resolution on either path (SDK attributes write or CC-API stored attributes + constructAttribute fallback) is pinpointed by the failing link. Critical hop: an unregistered CC-API type (AWS::CloudWatch::CompositeAlarm) whose Arn feeds downstream SDK-resource properties (issue: deep-getatt-chains fixture). deep-getatt-chains
deletion-policy-retain DeletionPolicy: Retain skip on destroy (schema v5 recorded value wins over template). deletion-policy-retain
deletion-policy-snapshot DeletionPolicy / UpdateReplacePolicy: Snapshot honored on delete (issues #1352 / #1354 / #1357): final EBS snapshot created + waited to completed on the deploy engine template-removal DELETE path, on the REPLACEMENT delete site (an immutable AvailabilityZone change under --force-stateful-recreation, unblocked by the #1356 EC2 Volume classification), and on the destroy-runner path; --skip-final-snapshot opt-out. deletion-policy-snapshot
deletion-policy-snapshot-heavy DeletionPolicy: Snapshot pre-delete machinery for the CC-routed name-keyed snapshot APIs (issue #1353): Redshift Cluster CreateClusterSnapshot + ElastiCache ReplicationGroup CreateSnapshot, both waited to available before the delete. deletion-policy-snapshot-heavy
deployment-events Structured deployment events to S3 + cdkd events command (issue #808): per-run deployments/{runId}.jsonl + index.json (separate key family from state.json, no schema bump), events survive cdkd destroy, and carry error + metadata ONLY (no resource properties / secrets). deployment-events
destroy-data-guard CloudFormation-parity refusal to force-clean contained data on destroy (issue #1340): a non-empty S3 bucket WITHOUT the auto-delete opt-in and an image-carrying ECR repository WITHOUT EmptyOnDelete both FAIL the destroy with the data intact, while the opted-in siblings (aws-cdk:auto-delete-objects tag / EmptyOnDelete: true) are force-cleaned in the same run; after AWS-native data cleanup a second destroy completes with zero orphans. destroy-data-guard
s3-directory-bucket
destroy-interrupt Graceful SIGINT on destroy (#816 — first Ctrl-C drains in-flight deletes, flushes trimmed state, releases the lock, exits non-zero; no 30m stranded lock) + Custom Resource replay fail-fast on re-run (#804 — the CR delete does NOT stall ~10 minutes invoking GetFunction against the already-deleted backing Lambda; the re-run resumes cleanly and quickly). destroy-interrupt
docker-image-asset-ecr-publish cdkd's deploy-time Docker ASSET pipeline (DockerAssetPublisher): docker build of a local Dockerfile -> ECR auth -> docker push to the CDK-managed container-assets repo, then an AWS::Lambda::Function with PackageType=Image pointing at the pushed image. Distinct from the local-emulation container scenarios (which never touch AWS) — this verifies the real build+push happens during cdkd deploy, the image runs (Lambda invoke), and the pushed image is gone after destroy. docker-image-asset
drift-revert-array-canonicalization cdkd drift no-false-positive on tag-list / resource-id / ARN array REORDER (issue #802 drift-normalize.ts canonicalization) and on an unordered OBJECT array at a provider-declared path (issue #1620 — ELBv2 TargetGroup.Targets, asserted by TWO consecutive clean drift runs, since one run cannot detect a reorder disagreement), while still detecting real value / Action / SG-rule / added-target drift. drift-revert-arrays
drift-revert-roundtrip cdkd drift detection + --revert round-trip via each provider.update(). drift-revert
drift-revert-arrays
drift-revert-vpc
dynamic-reference-resolution CloudFormation dynamic references ({{resolve:secretsmanager:...}} / {{resolve:ssm:...}}) resolved by cdkd itself (resolveDynamicReferences) BEFORE the property reaches the provider — JSON-key (:SecretString:<key>), whole-secret, and version-stage forms + plaintext SSM param; the deployed resource carries the RESOLVED value, never the literal token. Secret-bearing references are additionally REDACTED back to their expression in persisted state, decided by the parameter TYPE rather than the spelling: an ssm: reference to a SecureString parameter is redacted (issue #1901) while a String parameter beside it stays resolved. (ssm-secure: is NOT resolved by cdkd and is intentionally out of scope.) cross-stack-secret-import
dynamic-ref-cross-region
nested-stack-secret
rollback-cross-region-secret
secrets-array-nested
secrets-dynamic-ref
elbv2-listener-tg-lb-deletion-order ELBv2 destroy ordering web: Listener/ListenerRule before TargetGroup (ResourceInUse), TG + Listener before the LoadBalancer, and the LB hyperplane ENI + registered-target ENI release before Subnet/SecurityGroup delete (DependencyViolation). deletion-ordering-complex
eventsourcemapping-fresh-source-race AWS::Lambda::EventSourceMapping created against a FRESH source (SQS/Kinesis/DynamoDB-stream) + a FRESH execution role in the SAME deploy: the ESM create races source-readiness + role/policy propagation (cdkd dispatches with no level barrier), AND the orphan-ESM-on-redeploy collision class (a killed mid-deploy leaves an out-of-state ESM that collides on the next CREATE). The fixture pre-flight-scans for orphan ESMs by stack name, asserts the ESM reaches Enabled + actually delivers a probe message to the Lambda, and asserts no orphan ESM survives destroy. eventsourcemapping-race
export-to-cfn-handover cdkd → CloudFormation migration via 2-phase IMPORT changeset + phase-2 UPDATE. export
exports-index-region-resolve Exports index store (Fn::ImportValue tracking, _index/{region}/exports.json) auto-detects the bucket region via GetBucketLocation before its write/remove, so a cross-region state bucket no longer hits S3 301 PermanentRedirect (issue #819). cross-region-state-bucket
failed-only-journal-retention-cycle Failed-only rollback-journal retention after a CLEAN automatic rollback (issue #1208): the journal survives as a SINGLE popped-and-re-recorded segment (reason=auto-rollback-clean / operations=[] / failedOperations=[], raw S3 read), the next deploy prints the --revert-failed note and its own clean auto-rollback PRESERVES the older failed-only segment (PR #1216, exactly 2 segments), cdkd rollback --force --revert-failed consumes it via the #1198 skip-with-warning for a physical-id-less failed CREATE (exit 2 accepted), and a NO-CHANGE fix-forward deploy (bad resource removed) clears the journal + note (the PR #1212 no-change gap). rollback-sqs-cooldown
fresh-principal-consumer-race A consumer resource created moments after the fresh principal/resource it references in the SAME deploy: IAM InstanceProfile -> EC2 Instance (RunInstances validates the profile), Lambda::Permission granting a fresh S3 source (AddPermission validates SourceArn + function), S3 BucketPolicy referencing a fresh role principal ("Invalid principal in policy"), KMS key policy referencing a fresh role (CreateKey validates principals). Each is a distinct propagation-race edge from the original IAM-propagation-stress integ (Lambda exec role / SFN role / EventBridge target / SQS+SNS policy, #839). Pass condition = deploy SUCCEEDS, so the fixture is a race detector for missing transient-retry coverage in src/deployment/retryable-errors.ts. propagation-races-2
getstackoutput-cross-region Cross-REGION Fn::GetStackOutput (cdkd-specific): a CONSUMER stack deployed in region Y reads a PRODUCER stack output from region X via the Region argument. Works same-account because the cdkd state bucket is account-scoped (not region-scoped) — the resolver reads cdkd/{Producer}/{regionX}/state.json from the same bucket the consumer state lives in. No CFn equivalent (CFn Exports are region-scoped). getstackoutput-crossregion
rollback-cross-region-secret
globaltable-billing-flip-with-gsi DynamoDB GlobalTable PAY_PER_REQUEST -> PROVISIONED billing flip on a table that HAS GSIs (issue #1421). AWS requires per-index ProvisionedThroughput in the SAME UpdateTable call that changes BillingMode, and an index the deploy REMOVES is still live at flip time (its Delete is issued later), so it must carry throughput in that call too — both claims were previously asserted only against a mocked DynamoDB client. Also pins the surviving index + table onto their SeedCapacity rather than MinCapacity, the one context AWS documents the seed for (issue #1435). dynamodb-globaltable
globaltable-cross-region-replica DynamoDB GlobalTable cross-region replica add/remove serialization (AWS rejects multiple ReplicaUpdates per UpdateTable call). dynamodb-globaltable
iam-fresh-role-immediate-assume Race detector: SEVERAL brand-new IAM roles each consumed within ~1s by a DIFFERENT service in ONE deploy (Lambda exec role -> CreateFunction; SFN role -> CreateStateMachine; EventBridge target role -> PutTargets; fresh principal -> SQS QueuePolicy + SNS TopicPolicy). Deploy SUCCESS is the pass condition — a failure is an unprotected consumer racing IAM propagation (the narrow #794/#805/#756 fixes cover only a few consumers). iam-propagation-stress
iam-policy-propagation-retry CREATE retry with exponential backoff after IAM-EC2/Lambda eventual-consistency race. lambda
microservices
propagation-races-2
stepfunctions-logging
import-adopt-live-resource-roundtrip End-to-end cdkd import adoption of a LIVE AWS resource: drop the resource from cdkd state with cdkd orphan (AWS untouched), re-adopt it with cdkd import --resource <logicalId>=<physicalId>, then destroy THROUGH the re-adopted record. Exercises the provider import() + readCurrentState() pair (the observedProperties baseline seeded post-import) and the selective-mode merge that must preserve unlisted sibling rows. Distinct from nested-stack-migrate-from-cfn, which covers the --migrate-from-cloudformation path; NO fixture covered the plain adopt mode before (issue #1090). emr-cluster
intrinsic-hard-arg-shapes Resolver correctness on the harder / less-common intrinsic arg shapes feeding real resource values: Fn::Select over a list-returning intrinsic (Fn::GetAZs / Fn::Split), Fn::FindInMap enhanced 4th-arg {DefaultValue} + Ref-driven top key, Fn::GetAtt with a Ref-valued attribute name, the Fn::Sub ${!Literal} escape, Fn::Base64 of an intrinsic, a triple-nested Fn::If-in-Fn::Sub-in-Fn::Join, and Fn::Cidr IPv6. Sibling of intrinsics-torture (which found bug #838). intrinsics-torture-2
intrinsics-torture Stress-test of cdkd's hand-rolled intrinsic-function resolver (src/deployment/intrinsic-function-resolver.ts), which resolves EVERY intrinsic itself instead of deferring to CloudFormation. Each harder intrinsic computes an AWS::SSM::Parameter Value read back + asserted against an independently-computed expected value: Fn::Cidr (carve a /16 into eight /24s), Fn::FindInMap (Mappings region/env lookup), Fn::GetAZs + Fn::Select, Fn::Base64, nested Fn::Split + Fn::Select + Fn::Join, deeply-nested two-arg Fn::Sub (literal-map var via Fn::Join + ${AWS::Region} + ${Resource.Arn} GetAtt), and ALL pseudo-parameters (AccountId / Region / Partition / StackName / URLSuffix / NotificationARNs). Goes beyond the intrinsic-functions fixture (which covers only Ref / GetAtt / Join / Sub). intrinsics-torture
lambda-vpc-subnet-sg-deletion-order Subnet/SecurityGroup must delete AFTER Lambda::Function to avoid ENI DependencyViolation. bench-cdk-sample
lambda
vpc-lambda
legacy-bucket-name-fallback New region-free cdkd-state-{account} vs legacy cdkd-state-{account}-{region} bucket fallback resolution. legacy-bucket-name-fallback
local-agentcore-from-state cdkd local invoke-agentcore --from-state end-to-end against a real-AWS deployed AgentCore Runtime — verifies the cdkd-port-specific 3-arg createLocalStateProvider shim resolves intrinsic-valued env vars (e.g. Ref: <S3 bucket>) against cdkd state after a real cdkd deploy. local-invoke-agentcore-from-state
local-agentcore-runtime cdkd local invoke-agentcore Bedrock AgentCore Runtime: HTTP /invocations / MCP /mcp / A2A /a2a / AGUI / WebSocket --ws protocols + inbound JWT auth verification + container artifact + CodeConfiguration managed-runtime source build. local-invoke-agentcore
local-invoke-agentcore-from-state
local-apigateway-server cdkd local start-api HTTP server with route discovery + per-Lambda warm container pool. local-start-api
local-start-api-container
local-start-api-rest-v1-non-proxy
local-ecs-awsvpc cdkd local run-task ECS TaskDefinition declaring NetworkMode: awsvpc — accepted and mapped to a docker bridge network with a startup warn (#461; docker cannot emulate ENI-per-task). local-run-task-awsvpc
local-ecs-service cdkd local start-service long-running ECS Service emulator: replica pool, restart-on-exit, SIGINT teardown. local-ecs-service-connect
local-start-service
local-ecs-service-connect cdkd local start-service Service Connect + Cloud Map peer discovery: ServiceConnectConfiguration + ServiceRegistries parsing, in-process Cloud Map registry, docker --add-host DNS overlay (Issue #460). local-ecs-service-connect
local-ecs-task cdkd local run-task ECS TaskDefinition with docker network + AWS-published metadata sidecar. local-run-task
local-run-task-from-state
local-run-task-multi-container
local-from-cfn-stack-substitution `cdkd local invoke start-api
local-from-state-substitution `cdkd local invoke run-task --from-state` substitutes intrinsic-valued env/secret/role references against deployed cdkd state + AWS pseudo parameters.
local-lambda-rie-container cdkd local invoke container-Lambda (Code.ImageUri) against RIE — local-build OR ECR-pull asset resolution. local-invoke-buildkit
local-invoke-container
local-start-api-container
local-lambda-rie-zip cdkd local invoke ZIP-runtime Lambda against the AWS Lambda Runtime Interface Emulator (RIE) container. local-invoke
local-invoke-dotnet
local-invoke-from-cfn-stack
local-invoke-from-cfn-stack-multi-stack
local-invoke-from-state
local-invoke-java
local-invoke-layers
local-invoke-provided
local-invoke-python
local-invoke-ruby
local-region-case-fold Region CASE folding on the cdkd local path (issues #1795 / #1814 / #1836): an upper-cased region is structurally valid and nothing rejects it, while AWS SDK endpoint resolution, the partition table and cdkd's own state-record / marker-key comparisons are all case-SENSITIVE. Covers the two ends a Docker / real-AWS run can observe — the CONTAINER's own AWS_REGION (every SDK client the handler builds) must arrive canonical from an upper-cased shell, and an upper-cased --stack-region must still read the canonically-keyed cdkd/{stack}/{region}/state.json record instead of silently falling back to no state at all. local-invoke
local-invoke-from-state
local-websocket-api cdkd local start-api WebSocket API support: ws upgrade + $connect/$disconnect/$default/custom route dispatch + @connections data plane. local-start-api-websocket
migrate-from-bare-cfn cdkd migrate --from-cfn-stack <name> end-to-end: bare CFn → cdk migrate codegen → 2-pass resource mapping → cdkd state + optional retire. migrate-from-bare-cfn
migrate-from-cfn-handover CloudFormation → cdkd migration via --migrate-from-cloudformation (UpdateStack with Retain + DeleteStack). migrate-from-cfn
multi-asset Asset-publishing layer under concurrency: MANY assets of TWO kinds publish in ONE cdkd deploy — 1 Docker image asset (DockerAssetPublisher -> ECR build+push, ARM_64-pinned) + 3 distinct multi-file directory assets (three distinct FileAssetPublisher S3 uploads, one per zip Lambda) + 1 generic s3_assets.Asset (a 4th S3 upload read back at runtime via cdkd-resolved bucket/key env). Exercises FileAssetPublisher + DockerAssetPublisher concurrency, ECR + S3 in one run, and asset-ref intrinsics. Each Lambda returns a DISTINCT marker so a cross-wired asset (wrong Code ref) fails the test — proving each distinct asset uploaded AND was wired to the correct Lambda. Clean destroy: all 4 Lambdas + OUR pushed ECR image (by tag) gone; the shared bootstrap container-assets repo + asset bucket objects persist by design. multi-asset
multi-region-state-key Same stackName + different regions = independent state files (version: 2 region-prefixed key layout). multi-region-same-stack
multi-stack-getstackoutput Cross-stack Fn::GetStackOutput weak reference resolution (cdkd-specific, no CFn Export). composite-stack
cross-stack-references
getstackoutput-crossregion
multi-stack-deps
multi-stack-importvalue-strong-ref Cross-stack Fn::ImportValue strong-reference + persistent exports index (schema v4 imports[]). import-value-strong-ref
importvalue-chain
multi-stack-outputs-only-export Outputs-only change on an already-deployed producer (issue #875): a downstream consumer starts referencing the producer, so CDK synth adds a new Output/Export to the producer WITHOUT changing any of its resources. The producer redeploy is a no-op at the resource level but must still persist the new export to state + the exports index, otherwise the consumer (deployed with --exclusively, so the producer is not redeployed to paper over the gap) fails to resolve its Fn::ImportValue. Also covers the PREVIEW half (issue #1921): cdkd diff must report the Outputs-only change — human Outputs section naming the [export] row, --fail exiting 1, and the entry in --json outputChanges — where it previously printed "No changes detected" and exited 0, steering the user away from the deploy that publishes the export; paired with a negative arm requiring the freshly-deployed producer to still diff clean. outputs-only-export
nat-gateway-cleanup NAT Gateway destroy + dependent route cleanup (unconditional waitUntilNatGatewayDeleted on destroy). bench-cdk-sample
vpc-nat-gateway
nested-stack-deep-deploy-cascade Recursive cdk.NestedStack deploy + destroy at depth >= 3 (root → child → grandchild → great-grandchild): per-level <parent>~<logicalId> v6 state-key derivation with populated parentStack / parentLogicalId, bidirectional cross-level refs (bottom-up Fn::GetAtt outputs AND top-down Parameters forwarding), state list --tree hierarchy rendering, and the full reverse-DAG destroy cascade that removes every level's resources + state files. nested-stack-3level
nested-stack-migrate-from-cfn CloudFormation → cdkd RECURSIVE nested-stack migration via --migrate-from-cloudformation (recursive DescribeStackResources walk, per-child v6 state writes, recursive DeletionPolicy: Retain injection, parent-side DeleteStack cascade). See #464 PR A. import-nested-stack
ordinary-create-name-cooldown An ORDINARY cdkd deploy (no --replace, no rollback, a fresh process that never deleted anything itself) creating a resource whose NAME is still held by a prior cdkd destroy's asynchronous delete, and riding the cooldown out instead of failing the deploy (issue #2116). Distinct from rollback-reverse-replacement-name-cooldown, which covers the sites where cdkd ITSELF just deleted the name holder and therefore consults isRecreateRetryableError: this one covers the reachable destroy-then-redeploy dev loop, where the only thing that can absorb the window is the generic transient classifier plus the name-cooldown backoff grid. Pass condition = the redeploy exits 0 and prints Deployment completed successfully; coverage is confirmed separately from a --verbose retry line quoting the AWS cooldown message, since a fully-closed window produces the same exit code. CAVEAT on reading this row as coverage: the tag is claimed unconditionally by the fixture, but the arm is OPPORTUNISTIC -- the window is a ~23s real-AWS timing property that the fixture's preceding 200s bucket poll can outlast, so a given run reports either OK: COVERED or INCONCLUSIVE, and the latter is likely the common one. Nothing forces a re-run on INCONCLUSIVE. The standing backstop for the classifier and the 64s backoff grid is the unit suite (tests/unit/deployment/retryable-errors.test.ts + retry.test.ts), which runs every time; this row records that a real-AWS arm EXISTS, not that the last run exercised it. custom-resource-provider
raw-cfn-template-diff-parity Raw CloudFormation template (CfnInclude) carrying Parameters w/ defaults + Mappings + Conditions on resources AND outputs: deploy resolves them, a no-op cdkd diff --fail must exit 0 (no phantom replacement / phantom create — #1027), an inlined-parameter change updates in place, and a condition-false Output is skipped without a Failed to resolve output warn (#1028). raw-cfn-conditions-params
rds-aurora-cluster-instance RDS Aurora cluster + writer instance create/destroy with the 30-min wait budget + DBProxy/DBProxyTargetGroup family. rds-aurora
rds-full-stack Realistic single-instance RDS deployment: L2 rds.DatabaseInstance (db.t3.micro, single-AZ, isolated subnets, no NAT) with an EXPLICIT DBSubnetGroup + DBParameterGroup + SecurityGroup + CDK-managed Secrets Manager credentials, plus an SSM Parameter consuming the DBInstance COMPUTED endpoint via Fn::GetAtt(<DBInstance>, Endpoint.Address). Stresses event-driven DAG ordering (sub-groups before the instance), slow-create propagation (~5-10 min instance create), and intrinsic resolution of a computed attribute only known post-create (the SSM value must equal the live endpoint). A second SSM Parameter consumes Fn::GetAtt(<DbSubnetGroup>, DBSubnetGroupArn) (issue 1824) and must equal the live describe-db-subnet-groups ARN byte for byte — that ARN is read off the CreateDBSubnetGroup RESPONSE, a wire assumption every unit test hand-feeds to a mock, and pre-fix the reference HARD-FAILED the deploy on the resolver *Arn shape guard rather than resolving wrongly. rds-full-stack
remove-protection-bypass --remove-protection flag bypassing AWS-side deletion-protection on supported types. remove-protection
replacement-fanout-propagation Replacement propagation (#807) at FAN-OUT scale: ONE base resource (SNS Topic, TopicName change -> new ARN) referenced by MANY (10) dependents via Fn::Sub of its Ref (10 SSM Parameters + an SNS TopicPolicy). A second deploy with -c phase=b replaces the base; promoteReplacementDependents (src/analyzer/diff-calculator.ts) must propagate the new ARN to EVERY dependent so none keeps the stale phase-a ARN. Catches fan-out gaps the narrow ECS-only #807 case cannot. replacement-fanout
rollback-create-deletion-policy-snapshot DeletionPolicy: Snapshot on a ROLLED-BACK CREATE (issue #1358): a deploy whose second resource fails must snapshot the first one and DELETE it, not orphan it. verify.sh asserts the deploy fails, the old orphan log line is absent, a completed cdkd:final-snapshot-of EBS snapshot of the rolled-back volume exists, the volume is gone from AWS, and state.json is gone. rollback-deletion-policy-snapshot
rollback-failure-injection deploy-engine ROLLBACK path on a RICH multi-resource stack (VPC+SG+IAM Role+Lambda-in-VPC+SSM Parameter): a self-contained env-gated (ROLLBACK_INTEG_FAIL) failing SQS Queue (out-of-range messageRetentionPeriod) wired to depend on the fast siblings forces a deploy failure AFTER siblings complete; verify.sh asserts the completed siblings are rolled back (no orphan VPC/SG/ENI/Role/Lambda/SSM, state empty) and the #808 events captured RESOURCE_FAILED + ROLLBACK_* + RUN_FINISHED=FAILED. rollback-failure-injection
rollback-replay-effective-properties Reverse-replacement rollback records the replay-CREATE's effectiveProperties (issue #1682). Distinct from rollback-failure-injection, which rolls back CREATEs (a delete): here the resource is REPLACED before the failure, so rollback re-creates the OLD one from previousState.properties — a cdkd STATE record, which can carry a malformed block an older binary wrote and which the provider WARNS about and SUBSTITUTES (the #1544 replayWarn downgrade) rather than refusing. Pre-fix the engine typed that call's result as {physicalId, attributes?} and rebuilt the record from prev.properties, discarding the substitution. The vehicle is AWS::EC2::Route rather than the AWS::S3::Bucket #1682 names, because a bucket's reverse-replacement re-create must re-acquire a just-deleted GLOBALLY unique name whose release is not immediate (flaky for an unrelated reason), while a route's ` identity is stack-scoped and deterministic;createRoute's multi-destination warn arm is gated on the same CreateContext.replayingStateflag, so the engine path is identical. verify.sh deploys v1, injects a second destination key into the state record, flips the create-only destination with a failure wired AFTER the route (so rollback classifies reverse-replacement, asserted via the substitution warning), then asserts the post-rollback record restored the v1 destination and DROPPED the injected key, that two consecutivecdkd drift` runs converge, and that destroy leaves 0 orphans.
rollback-reverse-replacement-name-cooldown cdkd rollback reverse-replacement re-create through the SQS same-name ~60s deletion cooldown (issue #1206): a custom-named queue rename-replacement (create-only QueueName, --force-stateful-recreation) plus an injected failing resource under --no-rollback is reverted immediately — the reverse-replacement's initial re-create must hit QueueDeletedRecently, retry through the window (asserted via the --verbose retry lines), restore the old-named queue, delete the new one, and exit 0. rollback-sqs-cooldown
s3-asset-deploy File/ZIP asset publishing during cdkd deploy: a multi-file local directory is zipped + uploaded to the CDK bootstrap asset bucket by FileAssetPublisher (content-addressed, skip-if-exists), the Lambda Code.S3Bucket/Code.S3Key ref is wired to the uploaded object (CodeSize proves it is NOT inline), AND a generic s3_assets.Asset upload is read back at runtime via cdkd-resolved bucket/key env vars. Bootstrap-bucket asset objects persist by design across destroy. s3-asset-deploy
sdk-ccapi-crossref-boundary Heterogeneous SDK-Provider <-> Cloud Control API routing in ONE stack (a silent-drop top-level property flips a resource to the CC path per #614) with Fn::GetAtt cross-references crossing the boundary in BOTH directions — SDK-routed consumer reads a CC-routed producer attribute AND CC-routed consumer reads an SDK-routed producer attribute. Exercises the constructAttribute fallback for CC-API physical-id shapes (memory feedback_silent_drop_forces_cc_api_routing) and the CC delete path bypassing the SDK provider delete() (memory feedback_cc_api_routing_bypasses_sdk_delete_logic). sdk-ccapi-crossref
selective-import-attribute-persistence Selective cdkd import --resource <LogicalId>=<physical> adoption of an already-deployed resource whose provider import() returns a NON-EMPTY attributes map, asserting the map is persisted into the state row (issue #1098: buildStackState hardcoded attributes: {} and dropped it, leaving an adopted resource with no Fn::GetAtt backing while a deployed one had it). Uses AWS::IAM::ManagedPolicy (import() -> { PolicyArn }) after a cdkd state orphan drops state while leaving the AWS resource live. Distinct from migrate-from-cfn-handover, which covers the CFn retirement path rather than the state-row shape. import-attributes
sg-circular-dependency Circular Security Group reference (SG-A ingress from SG-B AND SG-B ingress from SG-A) modeled via standalone AWS::EC2::SecurityGroupIngress resources. DAG builder must not raise a false cycle; destroy must revoke both ingress rules BEFORE deleting either SG (SecurityGroup-after-SecurityGroupIngress implicit-delete-dep) or AWS rejects DeleteSecurityGroup with DependencyViolation. sg-circular-dependency
stack-level-tag-propagation-multitype STACK-LEVEL tags (cdk.Tags.of(app/stack).add(k, v)) propagate to ALL taggable resources across MANY types on BOTH the SDK-provider path (S3 / SNS / SQS / SSM Parameter / IAM Role / Logs LogGroup / Lambda / DynamoDB) AND the Cloud Control API path (Athena WorkGroup, no SDK provider). Each AWS type accepts tags in a DIFFERENT wire shape ({Key,Value}[] list vs { k: v } map vs the CC-API forwarder) — notably AWS::SSM::Parameter.Tags is a CFn MAP (the historical Tags.map() deploy-crash type per feedback_ssm_parameter_tags_is_a_map). verify.sh reads live AWS tags per type via that type-specific list/describe API and asserts ALL stack-level tags landed with the right value; a dropped tag FAILs naming the type. Also asserts post-deploy cdkd drift is clean (no #802 tag-list-reorder false positive). tags-propagation
state-bucket-region-resolve State-bucket S3 clients (state backend + lock manager) auto-detect bucket region via GetBucketLocation regardless of caller-profile region. cross-region-state-bucket
state-schema-migration Legacy v1 / v2 state schema auto-migrates on next write; old binary fails clearly on a newer schema. legacy-state-migration
schema-v5-to-v6-migration
schema-v8-to-v9-migration
undeletable-pending-resource-skip Destroy of a resource AWS itself refuses to delete until it expires server-side — the canonical case is an SNS subscription in PendingConfirmation, which rejects Unsubscribe from EVERY caller and only disappears via ~3-day auto-expiry or topic deletion. The provider must treat the rejection as delete-success (CloudFormation parity: the resource is removed from the stack without unsubscribing) instead of failing the resource and wedging destroy/state-destroy permanently (issue #1301). sns-pending-subscription
update-policy-mutations Second-deploy mutation of CloudFormation template-level ATTRIBUTES (not properties) across a CDK context flip (`-c phase=a b): (1) UpdateReplacePolicy: Retainorphan-on-replace — an S3BucketNamechange forces replacement, the OLD physical bucket must be RETAINED on AWS (not deleted) while the new one is created; (2)DeletionPolicyflip DESTROY->RETAIN on an SSM Parameter — the final destroy must honor the CURRENT (Retain) policy and leave it on AWS; (3)DependsOnadd/remove between SNS topics — a metadata-only change that must update successfully without replacing either topic; (4) metadata-only / no-op identical redeploy reportingNo changes detected. Intentional orphans (Retain bucket + Retain param) are cleaned by captured physical id in the verify.sh trap. Regression net for diff-calculator.tsattribute diff +deploy-engine.ts` Retain-on-replace / DeletionPolicy destroy-skip paths.
update-replace-breadth Second-deploy property mutation exercising BOTH cdkd update paths in one stack: in-place provider.update() (S3 versioning toggle / Lambda env+memory / IAM inline-policy edit / SecurityGroup ingress add — physical id unchanged) AND replacement (S3 BucketName change per the replacement-rules registry — new physical id, old resource cleaned up). Regression net for provider update() paths + #807 replacement propagation + #809 Cloud Control write-only-property UPDATE on non-ECS types. update-replace
vpc-lambda-cr-race Custom Resource invocation against a VPC Lambda mid-deploy (ENI-attach race window). vpc-lambda-cr-race
vpc-lambda-eni-release Lambda hyperplane ENI cleanup after DeleteFunction (5-30 min eventually consistent). bench-cdk-sample
destroy-interrupt
lambda
vpc-lambda
warn-arm-effective-properties A provider warn arm that SKIPS or SUBSTITUTES a malformed DECLARED value must record what it actually SENT (effectiveProperties), not the declared value. The deploy SUCCEEDS, so recording the declared bag makes state describe something AWS does not hold: readCurrentState can never match it, every later cdkd drift re-reports the same difference, and drift --revert re-issues the same skipped call (issues #1591 / #1612 / #1653 / #1654). Only a real deploy can produce the record and only a real read-side run can prove it converges, so a mocked client agrees with whatever wire assumption the author had. Covered arms: the DynamoDB GlobalTable StreamSpecification warn-and-SKIP (retains the PREVIOUS value; drops it when the previous side is malformed too) and the Lambda URL AuthType warn-and-SUBSTITUTE (records the previous value on the substituted arm, drops the key on the OMITTED arm) — each asserting the recorded value, the untouched LIVE resource, and that the corrected template then diffs clean against that record (a cdkd drift assertion would be vacuous here: drift prefers the observedProperties baseline, which is a live read and therefore matches AWS either way). The Lambda arm additionally asserts the security consequence directly (the URL is still IAM-guarded) and that a reverse-replacement replay of a record with no AuthType ANNOUNCES the PUBLIC default it falls back to. dynamodb-globaltable
lambda-url-authtype-replay
wide-dag-throttle-retry Wide (~100-resource: 80 SSM Parameters + 10 IAM Roles + 10 SNS Topics, 10-deep SSM Fn::Sub chain) single-stack burst deployed under a HIGH --concurrency to stress the concurrency limiter + event-driven DAG executor + throttle/retry classifier: a TooManyRequests / Rate exceeded / HTTP 429 during the burst must be RETRIED (deploy still succeeds) not fatal, the chained subset proves strict DAG ordering, and the destroy burst absorbs ~100 deletes with 0 orphans. throttle-wide-dag

Un-annotated fixtures (93)

These integ fixtures have no .scenarios.json sidecar. They may or may not exercise a canonical scenario — contributor review needed. To opt out (per-service smoke tests with no canonical pattern), add a sidecar with { "scenarios": [] }.

Last updated: