github ministackorg/ministack v1.5.33

4 hours ago

What's Changed

[1.5.33] — 2026-10-26

Added

  • Kinesis — stream and consumer resource policies — PutResourcePolicy, GetResourcePolicy and DeleteResourcePolicy answered InvalidAction; they now store a policy per stream or consumer, persisted and dropped with it, with AWS's checks in AWS's order: the ARN's region (InvalidArgumentException "The region specified in the ARN '' does not match the endpoint region"), the policy ("Policy validation error: This policy contains invalid Json", "Missing required field Version" or "Statement", and per statement the actions a stream or consumer can share and a Resource equal to the ARN, with the statement's line and column), then the resource ("Stream under account not found."). GetResourcePolicy without a policy answers {"Policy": "{}"} and DeleteResourcePolicy "No resource policy found for resource ARN .". Reported by @Jolley71717.
  • Lambda — Kinesis event source mappings across accounts — a function can map a stream in another account in the same region; CreateEventSourceMapping reads the stream first and answers "Received Exception while reading from provided stream. " with the reason ("No account found for the given parameters", "Stream under account not found.", or under AUTH=true the read the stream's policy doesn't allow the function's execution role), and the policy is checked again on every poll. Another region's stream answers "Event source region must match Lambda region ". Reported by @Jolley71717.
  • CloudFormation — AWS::Athena::WorkGroup — created with its Description, State, Tags and WorkGroupConfiguration, updated in place, replaced when Name changes and deleted with the stack; Ref returns the name and Fn::GetAtt CreationTime and the effective engine version. Reported by @mishukdutta-cz.

Fixed

  • S3 — GET, HEAD and DELETE error order and responses — under AUTH=true ordinary header-signed downloads check the endpoint and signing region before the bucket's home region, then credentials and missing buckets, and HeadObject, HeadBucket and DeleteObject check the home region first; a DELETE sent to another regional endpoint no longer deletes the object. In both auth modes a NoSuchKey carries Key, HEAD errors have an empty body and no Content-Length, and HeadBucket reports the bucket's region (also on a denial) and its ARN. Iceberg REST HEAD requests keep their JSON errors. Contributed by @gakuto-cw21.
  • S3 — persisted keys that a file path can't hold survive a restart — with S3_PERSIST=1 a folder marker such as project/Incoming/ came back without its slash, and keys under it, a key under another key's object (a/b beside a) or one with doubled or dot segments (x//y) were lost or rewritten; they are now stored by an encoded name under the bucket's .ministack-keys directory, and every other key keeps its path, so earlier data still loads. Reported by @jasonthagerty.
  • ALB — requests reach targets as sent — instance and IP targets now get the path with its percent-encoding, the query string unchanged, the client's Host as the load balancer sends it (no port on 80 or 443, the listener's port otherwise, unmodified with routing.http.preserve_host_header.enabled), the client's Accept-Encoding, and OPTIONS requests instead of a gateway-made CORS answer. A Lambda target's event carries the last value of a repeated query key, not decoded, no multi-value keys unless enabled, and body: "". Contributed by @skialpine.
  • ALB — responses and actions — the load balancer's own responses (a Lambda target's, fixed-response, redirect, authentication, its errors) carry Server: awselb/2.0 unless routing.http.response.server.enabled is false, it writes its own Date over an instance or IP target's, and the listener's response-header attributes (the CORS ones, strict_transport_security, content_security_policy, x_content_type_options, x_frame_options) are applied. A redirect fills #{protocol}, #{port} and #{query} from the listener and request (http://host:80/path), and authenticate-oidc on a 443 listener names its callback without the client's port. Contributed by @skialpine.
  • CloudFront — response headers — responses carry only the origin's headers plus CloudFront's own, with X-Amz-Cf-Id as URL-safe base64 of 40 bytes and Via: 1.1 <32 hex>.cloudfront.net (CloudFront); Server: CloudFront is added only when a viewer-response function ran and the origin sent none, and a Lambda Function URL origin's response carries a single x-amzn-RequestId. Contributed by @skialpine.
  • All services — status line, Date and Server — HTTP/1.1 status lines carry their reason phrase (HTTP/1.1 200 OK), every response carries one Date, also a WebSocket handshake and Hypercorn's own errors, and no response carries Server: hypercorn-h11. Contributed by @skialpine.
  • API Gateway — an HTTP API's rawQueryString is the query string as sent — ?flag reached the function as flag=; the Lambda proxy and REQUEST authorizer events now carry the request's own query string. Contributed by @skialpine.
  • Lambda — packages, code caches and restore — CreateFunction, UpdateFunctionCode and PublishLayerVersion refuse a package that is not a zip, an empty one included, with InvalidParameterValueException "Could not unzip uploaded file. Please check your file, then try to upload again.", leaving the function's code as it was. Two MiniStacks on one host no longer remove each other's extracted code, and restoring persisted state keeps one copy of code that versions share. Contributed by @skialpine.
  • Lambda — Kinesis event source mapping filters — a FilterCriteria pattern never matched a Kinesis record, so a filtered mapping dropped everything; metadata fields such as partitionKey now match at the top of the pattern and data as base64-decoded JSON, and data that isn't JSON still matches metadata patterns. Contributed by @Jolley71717.
  • DynamoDB — TransactWriteItems follows DynamoDB's check order — an Update whose condition failed is cancelled with ConditionalCheckFailed even when its update expression can't be applied to the item, an update-expression error on one member no longer hides a failed condition on another, a missing table answers ResourceNotFoundException, and a begins_with condition with a number operand answers ValidationException. Contributed by @jun-ut.
  • Step Functions — JSONata on Map, Parallel and variables — an inline Map evaluates Items, ItemSelector, MaxConcurrency, Output and Assign (an Items that isn't an array fails with States.QueryEvaluationError), a Catch on Map or Parallel applies its Output and Assign, and a variable assigned null reads back as null. Contributed by @mishukdutta-cz.
  • Glue — Spark job arguments and botocore — Spark scripts get --JOB_NAME and --JOB_RUN_ID (a run's Arguments still win, pythonshell scripts don't get them), and a job's own botocore loads from where the script asks, so a --py-files zip that holds botocore no longer fails with DataNotFoundError. Contributed by @mishukdutta-cz.
  • OpenSearch — engine heap and the container reaper — engine containers run with a 512 MB heap instead of the image's 1 GB, and the reaper no longer removes a live domain's stopped engine. Contributed by @skialpine.

Don't miss a new ministack release

NewReleases is sending notifications on new releases.