What's Changed
[1.5.8] — 2026-09-05
Added
- CloudFormation —
AWS::IoT::ThingGroupprovisions — a stack carrying a thing group rolled back withUnsupported resource typewhile the thing-group API worked. The type now provisions throughCreateThingGroup(ThingGroupPropertiesandParentGroupNameapplied, a name generated whenThingGroupNameis omitted),Refreturns the thing group id andFn::GetAttservesArnandId, as the resource reference documents;ThingGroupPropertiesupdates in place, whileThingGroupNameandParentGroupNamerequire replacement, a parent change under an unchanged custom name getting CloudFormation's own refusal.QueryString(dynamic groups) andTagsare accepted without effect: the service models neither. Contributed by @iot-rocket. - CloudFront — the policy, OAC and function types provision from CloudFormation —
AWS::CloudFront::CachePolicy,OriginRequestPolicy,ResponseHeadersPolicy,OriginAccessControlandFunctionhad complete APIs and no provisioner, so a CDK app declaring any of them rolled the stack back withUnsupported resource type. Each now provisions by converting its properties to the element the service's own config parser accepts,Ref/Fn::GetAttreturn the documented values (policyId, OACId, functionFunctionARN), deletes are wired, and an update replaces rather than mutating in place. Contributed by @mm-salesqueze. - S3 — Multi-Region Access Points deploy and serve —
AWS::S3::MultiRegionAccessPointrolled the stack back withUnsupported resource typeand the MRAP hostname resolved nowhere. The type now provisions, minting the.mrap-suffixed alias S3 uses and remembering its member buckets, and<alias>.accesspoint.s3-global.amazonaws.comresolves onto the existing virtual-hosted S3 path — the member whose bucket region matches the request region is served, else the first. SigV4A is not verified, consistent with the documented no-SigV4 stance, and the s3control control plane is not included. Contributed by @mm-salesqueze. - RDS — planned Aurora MySQL switchover runs on the data plane —
SwitchoverGlobalCluster(andFailoverGlobalClusterwithout data loss allowed) on a provisioned two-member Aurora MySQL 8 global cluster now performs a coordinated no-data-loss writer exchange: the source writer is fenced and drained, GTID convergence awaited, replication reversed and verified, and the promoted target verified writable, with conflicting mutations blocked mid-operation and recovery state persisted across restarts — an interrupted switchover is repaired by retrying the same request. Non-native configurations andAllowDataLoss=truekeep the metadata-only path. Contributed by @Areson. - RDS —
FailoverDBClusterpromotes replicated PostgreSQL readers — withMINISTACK_RDS_PG_CLUSTER_REPLICATION=1, failover now callspg_promote()on the selected hot standby, makes it the writer endpoint, and re-clones the former writer withpg_basebackupas a read-only standby. Metadata changes only after promotion succeeds; shared-container clusters retain their existing metadata-only behavior. Contributed by @Kiran01bm.
Fixed
- CloudFormation — stack updates stop destroying resources — a changed property on a type without an update handler fell through to a destructive re-create: generated-identity types came back empty under a new id with the old resource orphaned (Cognito pools and clients, Secrets Manager secrets, API Gateway authorizers and deployments), name-keyed ones wiped their data (Kinesis records, ECR images, group members, alarm state and history), and others failed the stack outright (any Route53 record edit, any EventBus property change). Nineteen types now update in place through their service's own APIs —
AWS::Cognito::UserPool/UserPoolClient/IdentityPool/UserPoolGroup(includingEnabledMfasviaSetUserPoolMfaConfig),AWS::SecretsManager::Secret(a changed value becomes the newAWSCURRENT, same ARN, history kept),AWS::Kinesis::Stream,AWS::ECR::Repository,AWS::DynamoDB::GlobalTable,AWS::Events::EventBus,AWS::Events::Rule,AWS::CodeBuild::Project,AWS::Route53::RecordSet,AWS::Scheduler::Schedule,AWS::StepFunctions::StateMachine,AWS::CloudWatch::Alarm,AWS::IAM::Policy,AWS::ApiGateway::Authorizer,AWS::ApiGateway::DeploymentandAWS::KMS::Alias— only the properties the resource references mark Replacement replace (the new resource is created before the old one is removed, and a custom-named resource requiring replacement gets CloudFormation's own refusal), and a property the template drops reverts to its create default. The engine gains real replacement semantics: when an update returns a new physical id, the predecessor is deleted in a cleanup phase, as CloudFormation does afterUPDATE_COMPLETE. Contributed by @iot-rocket. - CloudFormation —
AWS::Lambda::Permissionis replaced on update and removed on delete — a stack update that changed a permission fell through to the create handler and appended a second statement, a permission declared without the legacyIdwas never removed at all, andEventSourceToken,FunctionUrlAuthType,InvokedViaFunctionUrl,PrincipalOrgIDandSourceAccountwere dropped on the way to the statement. Every property of the type requires replacement, so an update now removes the old statement and adds the new one under a fresh generated Sid — the resource's physical id, the shape real CloudFormation mints — and all nine documented properties reach the statement as conditions. Contributed by @iot-rocket. - CloudFormation — a failed update keeps the pre-existing resources when it rolls back — the rollback of a failed stack update deleted every resource the run had touched, and a run touches every resource in the template: unchanged resources and resources updated in place went down together with what the update had actually created. The rollback now deletes only what the update created and replacements under a new physical id; a resource that kept its physical id is left standing. An in-place change is not reverted, and a replacement's old resource, already removed by the update, is not recreated. Contributed by @iot-rocket.
- CloudFormation — a rolled-back update reports what the stack ran before — after
UPDATE_ROLLBACK_COMPLETE,GetTemplatereturned the template that failed andDescribeStacksthe failed update's parameters and tags, so acdk diffafter a failed deploy compared against the wrong base. The rollback now restores the previous template body, parameters and tags together with the resources and outputs. Contributed by @iot-rocket. - CloudFormation — an export counts as in use only when a stack imports it —
DeleteStacksearched the serialized templates of every other stack for the export name, so a stack that merely carried the name in a string value blocked the delete, while an import through a resolvedFn::ImportValueargument did not. The check now walks the other stacks'Fn::ImportValueuses and resolves their arguments against those stacks' own parameters, as CloudFormation does. Contributed by @iot-rocket. - CloudFormation —
UpdateStackwithout changes is refused — an identicalTemplateBody, orUsePreviousTemplatewith unchanged parameters, ran an empty update where CloudFormation answersValidationError: No updates are to be performed., so a "deploy until nothing changes" loop never ended. The request is refused when the template, every resolved parameter and the tags (when sent) equal what the stack runs; a changed parameter value or tag set is still an update. Contributed by @iot-rocket. - CloudFormation — unrecognized resource types are rejected up front,
Fn::GetAttto a missing attribute fails the stack — a template with a resource type the emulator does not know provisioned every resource ahead of it before rolling back;CreateStack,UpdateStack,CreateChangeSetandValidateTemplatenow refuse it synchronously with CloudFormation's ownTemplate format error: Unrecognized resource types: [...]and leave no stack behind, and dynamic references ({{resolve:ssm:...}},{{resolve:secretsmanager:...}}), which the emulator does not resolve, are refused the same way.Fn::GetAttto an attribute a resource does not expose answered with the physical id, a silently wrong value; it now fails the operation withRequested attribute X does not exist in schema for T, and outputs are resolved before the success path commits, so a failing output rolls back too and registers no export. Contributed by @iot-rocket. - CloudFormation —
DeleteChangeSetof a change set that does not exist succeeds — it answeredChangeSetNotFound(404) where a real account answers a plain success, so the CDK — which removes a possible leftovercdk-deploy-change-setbefore every deploy and only toleratesChangeSetNotFoundException— aborted everycdk deployof an already deployed stack. The stack is now resolved by name or stack ID first; a stack that does not exist is still aValidationError. Contributed by @iot-rocket. - CloudFormation —
AWS::Events::Rulereports the rule ARN the EventBridge service reports —Fn::GetAttArnwas built with the bus name in every case, so a rule on the default bus answeredrule/default/<name>whileDescribeRulefor the same rule answeredrule/<name>. The provisioner now derives the ARN through the service's own helper: no bus segment on the default bus,rule/<bus>/<name>on a custom one. Contributed by @iot-rocket. - CloudFormation —
AWS::Cognito::UserPoolreadsUserPoolName— the provisioner readPoolName, the API's name for the property, where the resource reference definesUserPoolName, so every pool declared with the documented property came up under a generated<stack>-<logical id>name.UserPoolNameis honoured now;PoolNamestays accepted for templates written against MiniStack. Contributed by @iot-rocket. - CloudWatch —
PutMetricAlarmkeeps the state timestamp of an existing alarm — re-putting an alarm stamped a freshStateUpdatedTimestampon every call, so an alarm that had been inALARMfor an hour reported a state change that never happened whenever its configuration was touched. The state, its reason and its timestamp now stay across the re-put and onlyAlarmConfigurationUpdatedTimestampmoves, as the API reference documents; both request encodings. Contributed by @iot-rocket. - IAM enforcement — the remaining S3 operations authorize as S3 documents them — with
AUTH=true, a browserPOST Objectwas checked ass3:DeleteObject, a request naming aversionIdas the unversioned action,DeleteObjectsonce against the bucket ARN (so a grant onarn:aws:s3:::bucket/*denied every batch delete),CopyObject/UploadPartCopywithouts3:GetObjecton the source, and fifteen sub-resources fell to the method default. Each now maps to the action the S3 reference lists, aversionIdresolves to the*Version*action, and both enforcement sites run the per-request checks (per key, source object, attributes pair, governance bypass). Contributed by @iot-rocket. - DynamoDB — PartiQL and validation parity measured against real DynamoDB —
ExecuteStatementservesSELECTfrom"table"."index"(membership, projection, ordering and consumed capacity follow the index; an LSI reaches back to the base table for unprojected attributes, a GSI rejects them), document paths inSET/REMOVE,ORpredicates andRETURNING MODIFIED OLD/NEW *computed from the paths actually changed;BatchExecuteStatementreports per-statement error entries andExecuteTransactionvalidates every member before applying anything.QueryandScananswer theSelect/ProjectionExpressionrefusals with real DynamoDB's wording, aKeyConditionExpressionon a nested attribute is rejected (KeyConditionExpressions cannot have conditions on nested attributes),ConsumedCapacitylands on the index arm for index reads, and writes validate secondary-index key values — wrong-typed or empty as aValidationExceptionon single writes and as a positional cancellation reason in transactions. Reported by the paritysuite.org project. - Lambda — durable executions emit the complete history event set — four of the documented history event types were never emitted. Each handler invocation now records
InvocationCompleted;DurableConfig.ExecutionTimeoutis enforced — the execution landsTIMED_OUTwith anExecutionTimedOutevent and every in-flight chained invoke gets its ownChainedInvokeTimedOut;StopDurableExecutionmarks in-flight chained invokes withChainedInvokeStopped; andChainedInvokeStartedis on the log before a fast child can complete. - Cognito — the PreSignUp trigger fires on plain
SignUp— only federated sign-ups invoked it; a pool'sLambdaConfig.PreSignUpnow runs before the user is persisted, fail-closed:autoConfirmUserconfirms the account (no code delivery),autoVerifyEmail/autoVerifyPhonemark the attributes, and a rejecting or failing trigger blocks the sign-up withUserLambdaValidationException, per the trigger's documented contract. - STS — sessions expire and the store stops growing —
GetCallerIdentitywith expired temporary credentials answers403 ExpiredToken("The security token included in the request is expired", the documented STS error), and expired sessions are evicted as new ones register — previously every AssumeRole and vended identity-pool credential lived in memory forever.