May 15, 2026 · v1.3.39
Step Functions JSONata is fully wired across Task, Pass, and Choice states with a real operator surface. Cognito OIDC federation completes the callback that was missing. Step Functions no longer silently stalls under non-default account IDs. Node.js Lambdas can require('@aws-sdk/client-*') the same way real AWS-managed runtimes do.
Arguments and OutputTask states with QueryLanguage: "JSONata" were bypassing local payload construction and dispatching to aws-sdk integrations with an empty JSONPath payload — so every service call from a JSONata workflow failed. Tasks now evaluate Arguments before dispatch and evaluate success and Catch Output against $states.input, $states.result, and $states.errorOutput. Contributed by @jayjanssen.
Pass states accepted Output as a JSONata template and silently ignored it, passing input through unchanged. Choice states accepted Condition: "{% ... %}" and treated every condition as falsy, so workflows always fell through to Default. Both are now wired up: Pass evaluates Output on the way out, and Choice evaluates per-branch Condition and applies per-branch Output on the matched rule.
The evaluator gained the operators real workflows actually use: comparison (= != < <= > >=), arithmetic (+ - * / %), string concat (&), boolean (and or in), unary minus, paren grouping, and the $count / $length / $not / $string / $number functions. Left-associative parsing throughout. Reported by @youngkwangk.
{
"Type": "Pass",
"QueryLanguage": "JSONata",
"Output": {
"greeting": "{% 'Hello, ' & $states.input.name & '!' %}",
"doubled": "{% $states.input.value * 2 %}"
},
"End": true
}
_executions is an AccountScopedDict keyed by get_account_id(), which reads from a contextvars.ContextVar. The background execution thread was spawned via plain threading.Thread, which doesn't propagate contextvars into the new thread — so the worker thread looked up the execution under the default account, found nothing, and silently returned. Any caller using a 12-digit access key (the documented per-account-isolation pattern) saw their executions hang at ExecutionStarted forever.
Fixed with contextvars.copy_context().run on each thread target, with per-thread snapshots at the Parallel branch and Map ThreadPoolExecutor spawn sites — a single Context cannot be entered by two threads concurrently, so naively sharing one snapshot would silently drop concurrent branches/items. Contributed by @michael-denyer.
Federating Cognito to an external OIDC IdP — Keycloak in front of Cognito, Auth0, Google — was half-wired. /oauth2/authorize?identity_provider=<oidc-provider> redirected to the IdP correctly, but routed the IdP's callback at /saml2/idpresponse, which only accepts SAML responses. Every OIDC code+state callback 400'd.
MiniStack now serves the canonical Cognito /oauth2/idpresponse endpoint. It looks up the relay context, exchanges the code against the IdP's token_url (grant_type=authorization_code), decodes the returned id_token without verifying its signature — consistent with how MiniStack treats SigV4 and SAML signatures on the emulator side — applies AttributeMapping to the claims, provisions or refreshes the {provider}_{sub} federated user, and 302s the app back to its redirect_uri with a MiniStack-issued auth code. SAML federation continues to use /saml2/idpresponse unchanged. Reported by @ocr-lasagna.
@aws-sdk/client-* built-in stubsReal AWS Lambda (Node.js 18+) ships the AWS SDK v3 built-in — handlers can require('@aws-sdk/client-ssm') without bundling it. MiniStack's worker runs on the host, where these packages aren't installed; any such require() threw Cannot find module and broke CDK cr.Provider-backed custom resources end-to-end.
The worker now patches Module.prototype.require to intercept @aws-sdk/client-* ids. Real packages (e.g. shipped via a Lambda Layer) take precedence; otherwise a lightweight stub is returned that routes through AWS_ENDPOINT_URL. @aws-sdk/client-lambda gets a dedicated REST stub (Lambda, LambdaClient + InvokeCommand, waitUntilFunctionActiveV2); 28 additional awsJson1.x services — SSM, Step Functions, CloudWatch Logs, Secrets Manager, EventBridge, Kinesis, ECS, DynamoDB, SQS, Glue, Athena, Firehose, Cognito IDP/Identity, EMR, ECR, ACM, WAFv2/WAF/WAF-Regional, Organizations, KMS, CodeBuild, Transfer, ServiceDiscovery, Resource Groups Tagging, CloudTrail — resolve through a generic X-Amz-Target Proxy stub.
Errors carry both err.name and err.code set to the service error type, matching the v3 catch-by-name convention. The HTTPS→HTTP localhost downgrade is extended to cover CDK Provider Framework's cfn-response.js PUT, which calls https.request unconditionally and drops the port. Query-protocol clients (@aws-sdk/client-sns, client-sts, client-cloudwatch) and REST-XML / Query / REST-path services still need bundling or a Layer, same as outside a managed runtime. Contributed by @hiddengearz.
docker pull ministackorg/ministack:1.3.39 docker run -d -p 4566:4566 ministackorg/ministack:1.3.39
Or pin in compose.yaml:
services:
ministack:
image: ministackorg/ministack:1.3.39
ports:
- "4566:4566"
Shipped by the MiniStack community. Contributions credited throughout. GitHub · r/ministack