May 24, 2026 · v1.3.48
One new S3 surface and one urgent fix for the persistence-restore path that v1.3.47 introduced.
GetObjectAcl and PutObjectAclBoth ?acl subresource operations are now implemented. GetObjectAcl returns the stored policy or, if none has been set, the AWS default of a single FULL_CONTROL Grant to the request account-id owner. PutObjectAcl accepts either a canned ACL via the x-amz-acl header — private, public-read, public-read-write, authenticated-read, aws-exec-read, bucket-owner-read, bucket-owner-full-control — or a full <AccessControlPolicy> XML body:
import boto3
s3 = boto3.client("s3", endpoint_url="http://localhost:4566")
# Canned-ACL form
s3.put_object_acl(Bucket="b", Key="k", ACL="public-read")
# Round-trips
s3.get_object_acl(Bucket="b", Key="k")
# {'Grants': [{'Grantee': {...}, 'Permission': 'FULL_CONTROL'}, ...]}
Invalid canned-ACL values return InvalidArgument and malformed bodies return MalformedACLError, matching AWS. NoSuchKey is returned for missing keys (the only error modeled in botocore). As with retention, legal-hold and bucket policies, the ACL is stored and round-tripped but not enforced on the data plane — the same lenient stance as ministack's presigned-URL handling. Reported by @smpial.
The v1.3.47 restore-respawn daemon threads called _get_docker(), which was defined further down in the same module. A thread that reached the lookup before the parser finished loading the module raised NameError: name '_get_docker' is not defined and stranded the restored instance in creating with no backing container. The load_state("rds") block now runs at the bottom of the module, after every helper the restore threads can touch — so the race window is closed. Reported by @doodaz.
docker pull ministackorg/ministack:1.3.48 docker run -d -p 4566:4566 ministackorg/ministack:1.3.48
Or pin in compose.yaml:
services:
ministack:
image: ministackorg/ministack:1.3.48
ports:
- "4566:4566"
Issues and PRs welcome on GitHub. Discussion on r/ministack.