Phase 24: MinIO SDK — S3 Signature V4 + Core Operations
Goal: Build a zero-dependency Python SDK that wraps the raw S3 REST API with custom Signature V4 signing, integration-tested against live MinIO.
Owner: Dev agent
Repo:
forgejo_admin/minio-sdk (to be created)Depends on: None
Scope
Signature V4 Signing Module
- AWS Signature V4 implementation using only Python stdlib (
hmac,hashlib,urllib.parse) - Canonical request construction (method, URI, query string, headers, payload hash)
- String-to-sign derivation (credential scope, timestamp, canonical request hash)
- Signing key chain (4x HMAC-SHA256: date → region → service → request type)
- Authorization header generation
- Presigned URL generation (query parameter signing variant)
Bucket Operations (8 endpoints)
GET /— list all bucketsPUT /{bucket}— create bucketDELETE /{bucket}— delete bucketHEAD /{bucket}— check bucket exists + regionGET/PUT /{bucket}?versioning— get/set versioningGET/PUT/DELETE /{bucket}?policy— bucket policy (JSON)GET/PUT/DELETE /{bucket}?tagging— bucket tagsGET/PUT/DELETE /{bucket}?lifecycle— lifecycle rules
Object Operations (9 endpoints)
PUT /{bucket}/{key}— upload object (with metadata, ACL, content-type)GET /{bucket}/{key}— download object (supports Range header)HEAD /{bucket}/{key}— get metadata without bodyDELETE /{bucket}/{key}— delete objectPOST /{bucket}?delete— batch delete (up to 1000)PUT /{bucket}/{dest}+x-amz-copy-source— copy objectGET /{bucket}?list-type=2— list objects (pagination, prefix, delimiter)GET/PUT/DELETE /{bucket}/{key}?acl— object ACLGET/PUT/DELETE /{bucket}/{key}?tagging— object tags
Multipart Upload (5 endpoints)
POST /{bucket}/{key}?uploads— initiate (returns upload ID)PUT /{bucket}/{key}?partNumber=N&uploadId=X— upload part (5MB-5GB)POST /{bucket}/{key}?uploadId=X— complete (assemble parts)DELETE /{bucket}/{key}?uploadId=X— abortGET /{bucket}/{key}?uploadId=X— list parts
Presigned URLs
- Generate presigned GET URLs (download without credentials)
- Generate presigned PUT URLs (upload without credentials)
- Configurable expiration (default 1h, max 7d)
SDK Conventions
- Pure Python — only
requests+ stdlib (no boto3, no minio-py, no aws-sdk) - All S3 responses are XML — SDK parses to Python dicts/dataclasses
- Typed return values for all operations
- Published to Forgejo PyPI (same pattern as pal-e-docs-sdk)
MinIO-Specific Gotchas
- API port is 9000 (not 9001 console)
- No regional routing — single URL per MinIO instance
- Signature V4 is identical to AWS — no deviations
AbortIncompleteMultipartUploadlifecycle action not supported- MinIO recommends policies over ACLs
Deliverables
- PR #2 merged (squash) — 2026-03-21
- Custom AWS Signature V4 signing (
signer.py) — 4-chained HMAC-SHA256, presigned URLs MinioClientwith all S3 operations: buckets, objects, multipart, presigned- 16 typed dataclasses for S3 response objects
- XML parser for S3 responses (
xml.etreestdlib) - 62 tests (32 unit + 30 integration against live MinIO) — all passing
- Woodpecker CI pipeline: lint, test, publish to Forgejo PyPI
- Zero third-party S3 SDK dependencies —
requests+ stdlib only
Related
plan-pal-e-platform— parent planplan-2026-02-24-minio-object-storage— original MinIO deployment plan (completed)phase-pal-e-platform-25-minio-api— Phase 25, consumes this SDKphase-pal-e-platform-27-minio-sveltekit— Phase 27, final integration