Phase 24: MinIO SDK — S3 Signature V4 + Core Operations

phase-pal-e-platform-24-minio-sdk Phase

phase
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 buckets
  • PUT /{bucket} — create bucket
  • DELETE /{bucket} — delete bucket
  • HEAD /{bucket} — check bucket exists + region
  • GET/PUT /{bucket}?versioning — get/set versioning
  • GET/PUT/DELETE /{bucket}?policy — bucket policy (JSON)
  • GET/PUT/DELETE /{bucket}?tagging — bucket tags
  • GET/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 body
  • DELETE /{bucket}/{key} — delete object
  • POST /{bucket}?delete — batch delete (up to 1000)
  • PUT /{bucket}/{dest} + x-amz-copy-source — copy object
  • GET /{bucket}?list-type=2 — list objects (pagination, prefix, delimiter)
  • GET/PUT/DELETE /{bucket}/{key}?acl — object ACL
  • GET/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 — abort
  • GET /{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
  • AbortIncompleteMultipartUpload lifecycle 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
  • MinioClient with all S3 operations: buckets, objects, multipart, presigned
  • 16 typed dataclasses for S3 response objects
  • XML parser for S3 responses (xml.etree stdlib)
  • 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
  • plan-pal-e-platform — parent plan
  • plan-2026-02-24-minio-object-storage — original MinIO deployment plan (completed)
  • phase-pal-e-platform-25-minio-api — Phase 25, consumes this SDK
  • phase-pal-e-platform-27-minio-sveltekit — Phase 27, final integration