github ministackorg/ministack v1.5.20

2 hours ago

What's Changed

[1.5.20] — 2026-10-01

Added

  • DynamoDB — global table replicas through UpdateTable ReplicaUpdates — a Create was accepted and ignored, so Terraform / OpenTofu aws_dynamodb_table with a replica block waited forever. A Create now copies the table and its items to the other region and turns on NEW_AND_OLD_IMAGES streams; DescribeTable reports GlobalTableVersion 2019.11.21 and the other regions under Replicas as ACTIVE; writes and TTL settings replicate; Delete removes the replica. Reported by @wparad.
  • IoT — registry events — with a type enabled through UpdateEventConfigurations, the thing, thing type, thing type association, thing group, thing group hierarchy and thing group membership operations publish the AWS payload to $aws/events/..., where MQTT subscribers and topic rules receive it. Contributed by @iot-rocket.
  • ElastiCache — serverless caches — CreateServerlessCache, DescribeServerlessCaches, ModifyServerlessCache and DeleteServerlessCache for valkey (major 7, 8 or 9) and redis (major 7). With Docker each cache gets a TLS-only Valkey or Redis container whose certificate chains to the CA at GET /_ministack/elasticache/ca.pem. ModifyServerlessCache allows a same-engine major upgrade, redis to valkey, and valkey 7 to redis 7. Memcached serverless caches and serverless snapshots are refused with InvalidParameterValue. Contributed by @skialpine.
  • CloudFormation — AWS::Lambda::Version updates FunctionScalingConfig in place — a stack update re-ran the create, which published a new version for every change; a FunctionScalingConfig change now keeps the version, also when the update rolls back. Contributed by @iot-rocket.
  • CloudFormation — AWS::Glue::Database, Table, Partition, Connection, Crawler, Job and Trigger — they failed with Unrecognized resource types; they now create, update and delete through the Glue API, so Athena and the Glue API read a stack's tables. Ref and Fn::GetAtt follow the CloudFormation reference, as do replacing and in-place properties; a DatabaseInput.Name change fails with Database <name> not found and rolls back, as on AWS. Crawlers and jobs are only recorded, never run. Contributed by @fabio-andre-rodrigues.
  • CloudFormation — AWS::ElastiCache::SubnetGroup, ParameterGroup, CacheCluster, ReplicationGroup, User and UserGroup — they failed with Unrecognized resource types; they now go through the ElastiCache API, so a stack's cluster or replication group gets a real container-backed endpoint to pass to a Lambda function or ECS task. Replacement follows the CloudFormation reference (including NumCacheNodes when no Availability Zone is given), everything else updates in place, and Fn::GetAtt on an endpoint the resource does not have fails, as the reference says. Contributed by @fabio-andre-rodrigues.
  • IoT — DescribeEventConfigurations and UpdateEventConfigurations — both answered Unsupported IoT path; they now store the registry event switches per account and region, every type starting disabled, an update changing only the types it names, and creationDate / lastModifiedDate set from the first update on, as on AWS. Contributed by @iot-rocket.
  • CloudFormation — AWS::ServiceDiscovery::HttpNamespace, PrivateDnsNamespace, PublicDnsNamespace, Service and Instance — they failed with Unrecognized resource types, which blocked the CDK ECS Cloud Map constructs; they now go through the Cloud Map API, with Ref, Fn::GetAtt and replacement as in the CloudFormation reference. Namespaces now store Properties.DnsProperties.SOA.TTL, and DeleteNamespace removes the namespace's hosted zone, as on AWS. Contributed by @fabio-andre-rodrigues.
  • Bedrock AgentCore — runtime version history and endpoint pinning — runtime updates now retain version snapshots, GetAgentRuntime retrieves a selected version, and ListAgentRuntimeVersions paginates the history. DEFAULT advances with the latest version while named endpoints stay pinned until updated; invocations use the selected snapshot, with containers isolated by version. Contributed by @pingedbrain.
  • Bedrock AgentCore — ListAgentRuntimes and ListAgentRuntimeEndpoints paginate — both take maxResults and nextToken and return a nextToken only when another page exists. Contributed by @pingedbrain.

Changed

  • botocore 1.43.106 — the service models MiniStack reads move from 1.43.63 to 1.43.106; the images keep awscli 1.45.63, installed on the same botocore instead of its pinned one.

Fixed

  • SES v2 — ListEmailIdentities and ListConfigurationSets answer the routes newer SDKs use — botocore 1.43.106 sends them as POST /v2/email/list-identities and POST /v2/email/list-configuration-sets with NextToken, PageSize and Filter in the body; those paths answered NotFoundException. Both forms page, and the Filter keys are applied.
  • Kinesis — ApproximateArrivalTimestamp keeps milliseconds — it was truncated to whole seconds, so an AT_TIMESTAMP iterator from an SDK that sends fractional seconds skipped records written earlier in the same second.
  • CloudFormation — an empty Capabilities list is accepted — botocore sends it as a bare Capabilities=, which was read as one empty value and refused, so aws cloudformation deploy without --capabilities and Capabilities=[] from an SDK failed with a ValidationError since 1.5.11.
  • API Gateway v2 (HTTP API) — the request path keeps a %25 escape — /items/a%252Eb reached the Lambda's rawPath as /items/a%2Eb, because the path was fully percent-decoded. The HTTP API path now keeps %25 and decodes every other escape as before; rawPath, requestContext.http.path, pathParameters and route matching all use it. Contributed by @skialpine.
  • Step Functions — JSONPath $$. paths read the context object — a Choice rule's Variable and its variable-to-variable comparison paths (including inside And, Or and Not), and a state's InputPath, OutputPath and Map ItemsPath, resolved $$. against the state input, so a Choice on $$.Execution.Input silently took its default branch. They now read the context object, as the AWS context object reference lists for those fields. Contributed by @jayjanssen.
  • CloudFormation — AWS::EC2::VPCGatewayAttachment updates in place — a changed InternetGatewayId or VpnGatewayId moves the attachment under the same IGW|vpc-… / VGW|vpc-… physical id, VpnGatewayId is attached at all, and a VpcId change leaves the gateway attached to the new VPC, or to the old one when the update rolls back. AttachInternetGateway on a gateway already attached to a VPC answers Resource.AlreadyAssociated, and a stack attaching it to a second VPC leaves it on the first, as AWS does. Contributed by @iot-rocket.
  • CloudFormation — AWS::Lambda::Version publishes through PublishVersion — the version takes its Description, a version of a function unchanged since its latest version fails with the AlreadyExists error AWS reports, FunctionScalingConfig on a function without a capacity provider is refused, and a function keeps its CapacityProviderConfig. Contributed by @iot-rocket.
  • AppConfig — hosted configuration version numbers are never reused — a version created after a delete, and the replacement CloudFormation makes for a changed HostedConfigurationVersion, get the next unused number instead of overwriting the live one, and a LatestVersionNumber mismatch reports the AWS message. Contributed by @iot-rocket.
  • CloudFormation — a deleted AWS::AppConfig::Deployment stays in ListDeployments — the stack delete removed the deployment, so a replaced deployment left the environment's history and the next one reused its number; it now stays until its environment is deleted, which, through the API or with its stack, also removes its deployments and their tags. Contributed by @iot-rocket.
  • CloudFormation — AWS::ECS::Service stores NetworkConfiguration and LoadBalancers in the ECS API shape — DescribeServices returns them in camelCase on create and update, and a service from a template registers its tasks in its target groups. Contributed by @iot-rocket.
  • SESv2 — CreateEmailIdentity/GetEmailIdentity return Easy DKIM tokens for a DOMAIN identity — a domain identity created without DkimSigningAttributes answered an empty Tokens list with Status: NOT_STARTED. AWS provides a set of DKIM tokens for its CNAME records in that case (Easy DKIM), so the Terraform aws_sesv2_email_identity resource's dkim_signing_attributes[0].tokens indexing failed. A DOMAIN identity now gets three tokens, SigningAttributesOrigin: AWS_SES and Status: PENDING, unless DkimSigningAttributes brings its own key (BYODKIM); EMAIL_ADDRESS identities are unchanged. Contributed by @skialpine.
  • Lambda — functions reach a USE_SSL=1 gateway — the gateway listener serves only HTTPS, but a function's default AWS_ENDPOINT_URL was plain HTTP in every executor (Docker, the warm worker and the local subprocess), and the Docker executor's Node shim downgraded a function's https.request to the gateway to HTTP, which the listener resets. The default endpoint now follows the gateway's scheme, the shim keeps TLS, and a host process trusts the gateway's certificate through AWS_CA_BUNDLE / REQUESTS_CA_BUNDLE / NODE_EXTRA_CA_CERTS unless they are already set. Without USE_SSL nothing changes. Contributed by @skialpine.
  • RDS — MINISTACK_RDS_PUBLIC_ENDPOINT=1 works with a Compose hostname: — a containerised MiniStack whose container sets a hostname left instances creating, because the self-lookup by HOSTNAME found no container. A containerised MiniStack now detects its network as with the setting off (DOCKER_NETWORK, then the self-lookup). Contributed by @skialpine.
  • IoT — DeleteThingGroup refuses a group with child groups — the delete went through and left the children pointing at a missing parent; it now fails with InvalidRequestException "Cannot delete thing group : {name} when there are still child groups attached to it", and a CloudFormation stack delete that reaches such a group ends in DELETE_FAILED. Contributed by @iot-rocket.
  • IoT — UpdateThing honours removeThingType — the flag was ignored, so the thing kept its type, and an update without attributePayload cleared the attributes. Contributed by @iot-rocket.
  • API Gateway v2 (HTTP API) — a doubled leading slash still selects the route — a request to //items/abc matched no route and answered 404 {"message":"Not Found"}. Route selection and pathParameters now ignore the extra leading slashes; rawPath keeps the path as received. Contributed by @skialpine.
  • Cloud Map — DeleteNamespace refuses a namespace that still has services — it deleted the namespace (and now its hosted zone) anyway. It answers 400 ResourceInUse "Namespace has associated services; delete the services before deleting the namespace", as on AWS.
  • Lambda — PublishVersion of an unchanged function returns the latest version — it published a new version every time; AWS doesn't publish when the code and configuration haven't changed since the last version, and returns that version with its original description.
  • API Gateway v2 (HTTP API) — REQUEST authorizer identity sources — a declared identity source missing from the request answers 401 {"message":"Unauthorized"} without invoking the authorizer, cached or not (it required caching). $context.* sources such as $context.routeKey are resolved from the request instead of counting as missing, so an authorizer caching per route no longer answered 401 to every request. Contributed by @skialpine.
  • ECS — optional task-definition fields stay omitted — registering an EC2 task definition without task-level cpu, memory, or requiresCompatibilities no longer invents 256, 512, or ["EC2"] in register, describe, and deregister responses. Explicitly supplied values remain in the definition. Contributed by @AdrianAcala.
  • IAM — customer-managed permissions use the explicit account — policy evaluation now resolves the complete policy ARN in the principal's account, so a different ambient request account cannot hide that policy or supply a foreign account's document. Permissions continue to follow the policy's current default version. Contributed by @AdrianAcala.
  • Cognito — USER_SRP_AUTH checks the password — PASSWORD_VERIFIER accepted any response, so a wrong password or a disabled or unconfirmed user got tokens. The challenge now carries SRP-6a parameters with a stable salt per user, and a response whose signature does not prove the stored password is refused with NotAuthorizedException; TIMESTAMP must read EEE MMM d HH:mm:ss z yyyy, and a temporary password leads to NEW_PASSWORD_REQUIRED. CUSTOM_WITH_SRP gets the same check. Contributed by @iot-rocket.
  • Cognito — refresh tokens are checked against the pool and client — REFRESH_TOKEN_AUTH (InitiateAuth, AdminInitiateAuth) and GetTokensFromRefreshToken issued tokens for the first user in the pool when the refresh token was malformed, from another pool or of a deleted user, and accepted a token issued to another client; they now answer NotAuthorizedException with the message AWS gives for each case, and the refresh token from a SAML or OIDC federated sign-in now refreshes the federated user's session. Contributed by @iot-rocket.
  • CloudFormation — AWS::S3Tables::TableBucket and AWS::S3Tables::Table update in place — a stack update re-ran the create, which reset the bucket's createdAt and rebuilt the table with a new createdAt and its initial metadata location, dropping committed metadata; a maintenance setting or tag change now keeps both, and a create-only table change under an unchanged name fails with the conflict AWS reports. Contributed by @iot-rocket.
  • RDS — DescribeGlobalClusters lists clusters as GlobalClusterMember — each cluster was a <GlobalCluster> element, so SDKs that match the list member name, such as aws-sdk-go-v2, found none. Contributed by @IamYipi.
  • Amazon MQ — DescribeBrokerInstanceOptions returns supportedEngineVersions as strings — they were {"name": ...} objects, which aws-sdk-go-v2 could not deserialize. Contributed by @IamYipi.
  • EventBridge — UpdateEventBus returns the bus — it answered EventBusArn and LastModifiedTime, which are not response members, so SDKs returned nothing; it now returns Arn, Name and the bus's Description, KmsKeyIdentifier, DeadLetterConfig and LogConfig. Contributed by @IamYipi.
  • CloudFormation — AWS::CodeBuild::Project stores Source, Artifacts and Environment under CodeBuild API names — the template's PascalCase members and BuildSpec were stored as written, so BatchGetProjects dropped them and a build of a stack's project found no buildspec, image or environment variables. Contributed by @IamYipi.
  • Inspector2 — responses aws-sdk-go-v2 can read — timestamps are epoch seconds, ListFilters returns criteria, ownerId, createdAt and updatedAt, CreateFilter returns arn, and coverage scanStatus is {statusCode, reason}. Saved state is converted on restore. Contributed by @IamYipi.
  • EventBridge — PutEvents refuses aws.* sources — an entry whose Source starts with aws. fails with NotAuthorizedForSourceException (Not authorized for the source.) in its result entry and counts in FailedEntryCount, while the rest of the batch is delivered, as on AWS. Events published with an aws.* source through PutEvents to simulate AWS services now get this error. Contributed by @iot-rocket.
  • SQS — QueueUrl matches the gateway's TLS scheme (USE_SSL=1) — CreateQueue/GetQueueUrl/ListQueues always returned http:// URLs, and the AWS SDK v3 uses the QueueUrl itself as the request endpoint (useQueueUrlAsEndpoint defaults true), so a client handed that URL left the TLS-only gateway. The AWS::SQS::Queue CloudFormation provisioner built the same hardcoded scheme and now reuses the shared helper. Contributed by @skialpine.
  • API Gateway v2 (HTTP API) — a request no stage or route matches answers AWS's exact 404 body — an unmatched route answered {"message": "No route found"} and an unknown stage {"message": "Stage '…' not found"}; both now answer {"message":"Not Found"} (compact JSON), as AWS does. Contributed by @skialpine.
  • API Gateway v2 — apiEndpoint follows the gateway's TLS scheme — with USE_SSL=1 the gateway listener serves only HTTPS, but CreateApi and the AWS::ApiGatewayV2::Api CloudFormation resource always returned an http:// apiEndpoint, which nothing answers. They now return https://, or wss:// for a WebSocket API, as AWS does. Without USE_SSL the endpoint keeps http://. Contributed by @skialpine.
  • IAM — condition value lists and request-tag key matching — negated conditions now match only when none of their policy values match, so a StringNotEquals deny listing permitted values no longer denies one of those values. Request-tag condition keys match every tag name without regard to case, including names that differ only by case; affirmative conditions match any of those values and negated conditions match none. Comparisons of tag values keep the selected operator's case rules. Contributed by @AdrianAcala.
  • SSM — parameter tag actions authorize the parameter named by ResourceId — with AUTH=true, AddTagsToResource, RemoveTagsFromResource, and ListTagsForResource checked Name instead, so an exact ARN allow could fail and an exact ARN deny could be missed under a broad allow. Accepted parameter-name and ARN aliases now use the canonical parameter ARN for the IAM check. SSM authorization denials now match AWS's HTTP 400 JSON 1.1 response, including the canonical resource and explicit-deny reason. Contributed by @AdrianAcala.
  • Bedrock AgentCore — a missing runtime answers AWS's message — the control-plane runtime operations answered Agent runtime <id> not found; they now answer ResourceNotFoundException "Agent '' was not found. Please check the agent ID and try again.", as AWS does.

Don't miss a new ministack release

NewReleases is sending notifications on new releases.