github ministackorg/ministack v1.3.43

4 hours ago

What's Changed

New Contributors

  • @m7w made their first contribution in #524

[1.3.43] — 2026-05-18

Added

  • AWS IoT Core (Phase 1) — new service covering the control plane and a WebSocket-only MQTT data plane. Control plane: CreateThing / DescribeThing / ListThings / UpdateThing / DeleteThing, CreateThingType and group, CreateThingGroup + AddThingToThingGroup / RemoveThingFromThingGroup, certificates via a new in-process Local CA (CreateKeysAndCertificate, RegisterCertificate, UpdateCertificate, DeleteCertificate, ListCertificates), AttachThingPrincipal / DetachThingPrincipal / ListThingPrincipals / ListPrincipalThings, policies with versioning (CreatePolicy, CreatePolicyVersion, GetPolicyVersion, ListPolicyVersions, SetDefaultPolicyVersion, DeletePolicyVersion), policy attachment (AttachPolicy, DetachPolicy, ListAttachedPolicies, ListTargetsForPolicy), and DescribeEndpoint returning a per-account hostname. Data plane: HTTP iot-data Publish at POST /topics/{topic} with QoS 0/1 and ?retain=true, plus MQTT 3.1.1 over WebSocket multiplexed on the gateway port (clients use the mqtt Sec-WebSocket-Protocol value and connect to the address returned by DescribeEndpoint). Multi-tenancy enforced by transparent topic prefixing in the bridge layer — the account ID is resolved from the SigV4 credential at WebSocket upgrade and topics are prefixed before they hit the in-process pub/sub registry, so two accounts publishing to the same topic name never see each other's traffic. Persistent sessions (cleanSession=0), QoS 1 in-flight tracking + retransmit with DUP flag, Last Will and Testament on ungraceful disconnect, duplicate-client-id force-disconnect, and retained-message delivery on subscribe all implemented per MQTT 3.1.1. Local CA root certificate exposed at GET /_ministack/iot/ca.pem so test code can configure SDK trust; CA + broker state (retained messages, persistent sessions) persist across restarts when PERSIST_STATE=1. Deferred to later phases: Device Shadows, mTLS on 8883, ListRetainedMessages queries, Rules Engine, Jobs, Fleet Provisioning. IoT policy documents are stored but not enforced on the data plane. Plain TCP 1883 is intentionally not exposed (real AWS IoT requires TLS or SigV4 on every connection). Requires the cryptography package (declared in the [full] optional dependency); slim image users hit a clean RuntimeError on first IoT call. Contributed by @jgrumboe.
  • Athena ↔ Glue catalog integration + S3 result persistenceStartQueryExecution now resolves database.table references against Glue's GetTable to find the underlying S3 location, so queries against Glue-managed tables work without hand-written read_csv('s3://...') paths. Completed query results are written to the configured OutputLocation as <id>.csv plus a <id>.csv.metadata companion (column names + Athena-mapped types) — the CSV file includes the column-name header row as the first line, matching real Athena's output format. Mixed queries combining Glue tables with explicit s3:// URIs in the same statement also resolve correctly. Contributed by @m7w.

Fixed

  • EventBridge rule targets pointing at Step Functions state machines — targets with an ARN of the form arn:aws:states:<region>:<account>:stateMachine:<name> previously fell through to the "unsupported target type" warning and silently dropped events. The dispatcher now calls into the existing stepfunctions._start_execution, which runs the execution on a daemon thread with a contextvars.copy_context() snapshot so the request's account context is preserved. The transformed payload (post Input / InputPath / InputTransformer) is passed verbatim as the execution input, so Input* features work for free. RoleArn on the target is accepted and ignored, matching how the existing Lambda/SQS/SNS dispatchers handle it. Contributed by @DaviReisVieira.
  • Step Functions StartExecution accepts version and alias ARNs — real AWS lets callers (and EventBridge targets) reference a state machine by its base ARN, a published-version ARN (stateMachine:<name>:<version>), or an alias ARN routed via CreateStateMachineAlias. Previously only the base ARN resolved — versions and aliases returned StateMachineDoesNotExist. A new resolver walks the base / version / alias stores; alias dispatch picks the highest-weighted version in the routing configuration (ties → first listed) for deterministic test behaviour. EventBridge → Step Functions dispatch leans on the same resolver, so EB rules pinning a target to a specific version or alias now actually fire.
  • Athena DuckDB queries no longer stall the event loopStartQueryExecution previously scheduled the DuckDB run via asyncio.create_task, but DuckDB's conn.execute() is a blocking C call so the asyncio loop sat idle for the full query duration, stalling every other in-flight request on the single-process server. Wrapped in asyncio.to_thread so multiple concurrent Athena queries run on worker threads and the loop stays free.
  • Step Functions aws-sdk:lambda integrationarn:aws:states:::aws-sdk:lambda:getAlias and getFunctionConfiguration now dispatch through the Lambda REST emulator with JSONPath-resolved FunctionName, Name, and Qualifier parameters. Unblocks readiness workflows that verify a Lambda alias and its published version before invoking it. The dispatcher captures the caller's account ID from the request contextvar and embeds it in the synthetic Authorization header (instead of hardcoding test), so SFN executions running under a non-default 12-digit account correctly resolve Lambdas in their own account scope. Contributed by @jayjanssen.
  • Lambda published-version readiness propagates from $LATEST — published version snapshots created while $LATEST is still Pending/InProgress now transition to Active/Successful with the function, so GetFunctionConfiguration --qualifier <version> converges instead of staying stuck after the alias points at the version. Contributed by @jayjanssen.

Don't miss a new ministack release

NewReleases is sending notifications on new releases.