August 10, 2026 · v1.4.15
v1.4.15 grows three services and hardens two more. KMS gains HMAC keys with GenerateMac / VerifyMac, RDS wires ManageMasterUserPassword to Secrets Manager, and EventBridge API destinations are now invoked over HTTP on PutEvents. On top of that: a large S3 conformance batch, RDS Data API endpoint fidelity, and SQS, Route 53, and Step Functions parity fixes.
GenerateMac, and VerifyMac. The four HMAC key specs (HMAC_224 / HMAC_256 / HMAC_384 / HMAC_512) with KeyUsage=GENERATE_VERIFY_MAC, RFC 2104 generation and constant-time verification (KMSInvalidMacException on mismatch), and DryRun. HMAC keys are rejected by Encrypt / Decrypt / Sign / Verify / GenerateDataKey*; EnableKeyRotation and DisableKeyRotation reject them with UnsupportedOperationException while GetKeyRotationStatus reports KeyRotationEnabled: false, matching AWS. Contributed by @nafdev.ManageMasterUserPassword wires Aurora clusters to Secrets Manager. The flag was ignored: no secret created, no MasterUserSecret returned. It now generates a random master password, stores it in MiniStack's own Secrets Manager under the AWS naming convention (rds!cluster-<uuid>), and returns MasterUserSecret from create / describe / modify. RotateMasterUserPassword rotates the real login and promotes the new credentials to AWSCURRENT, with AWS-exact rejections validated before anything mutates. Contributed by @kiran01bm.PutEvents. API destinations and connections were control-plane stubs, so a matching rule dropped the event. Matching events now POST (or the configured method) to the InvocationEndpoint with the input-selected payload; connection authorization is honored (BASIC, API_KEY, and OAUTH_CLIENT_CREDENTIALS with token caching, proactive refresh, and one 401/407 retry), header merging follows the AWS precedence rules, and delivery runs on a background thread. Contributed by @t-rech.LAMBDA_KEEPALIVE_MS=0 forces a per-invocation cold start. A LocalStack-compat lever (not an AWS behavior): for Docker RIE runtimes (Ruby / Java / .NET), LAMBDA_KEEPALIVE_MS=0 tears the warm container down after each invocation so the next invoke re-runs INIT, for deterministic cold-start isolation in test suites. Unset or any non-zero value keeps the warm-pool behavior. Reported by @mayankgupta57.file is the body); GetObject with partNumber returns that part as 206 Partial Content; ListObjectVersions emits NextKeyMarker / NextVersionIdMarker when truncated and honors version-id-marker; CompleteMultipartUpload returns 400 MalformedXML for an unparseable body and is idempotent on replay; object owner id is consistent between listings and ACLs; expired presigned URLs return 403 AccessDenied; and conditional deletes honor If-Match (412 PreconditionFailed). Reported by @gaul.CopyObject and HeadObject honour the source versionId. A ?versionId= on the copy source (and on HeadObject) was discarded, so both operated on the current object. CopyObject now copies the exact version and echoes x-amz-copy-source-version-id, HeadObject returns that version's metadata, and a non-existent version is rejected with NoSuchVersion. Reported by @Kaphaalor.NewerNoncurrentVersions survives the lifecycle round-trip. NoncurrentVersionExpiration and NoncurrentVersionTransition dropped the field on PUT/GET, so terraform-provider-aws never converged. It is now emitted and parsed on both rules. Contributed by @sac-outsystems.HttpEndpointNotEnabledException; a missing, deletion-scheduled, or password-less secret returns SecretsErrorException / InvalidSecretException; CommitTransaction / RollbackTransaction require resourceArn and secretArn; and a transaction is bound to its originating cluster (a mismatched transaction returns TransactionNotFoundException from execute/batch and NotFoundException from commit/rollback). Contributed by @Areson.MessageDeduplicationId is now retained for its full 5-minute window from send time regardless of receive/delete. Reported by @giannimassi.ChangeResourceRecordSets DELETE requires the current values to match. A DELETE matched only on name, type, and set identifier, so a delete carrying stale values silently removed the live record. A mismatched DELETE now fails the batch atomically with the AWS-shaped InvalidChangeBatch message, restoring the compare-and-swap semantics guarded-delete workflows rely on. Contributed by @jayjanssen.TagResource / UntagResource / ListTagsForResource only resolved log-group ARNs, so the provider's read-after-create on aws_cloudwatch_log_delivery_source / _destination / _delivery failed with ResourceNotFoundException and broke EventBridge bus-logging stacks. All three now resolve the delivery records' tags. Contributed by @t-rech.VpcSecurityGroups) into an object when it held a single item. Known wrappers now decode to a list for zero, one, or multiple items. Contributed by @Areson.TIMED_OUT. A build stopped by timeoutInMinutes was labelled FAILED, so BatchGetBuilds could not distinguish a timeout from a genuine build failure. It now reports the TIMED_OUT build status, matching AWS.docker pull ministackorg/ministack:1.4.15 docker run -d -p 4566:4566 ministackorg/ministack:1.4.15
Or pin in compose.yaml:
services:
ministack:
image: ministackorg/ministack:1.4.15
ports:
- "4566:4566"
Issues and PRs welcome on GitHub. Discussion on r/ministack.