Thin component that PUTs bytes to S3, isolated so it's testable on its own — and the earliest validation vehicle for real bucket + auth once SecEng grants access.
What to do
- Add
S3BillingUploader: AWS SDK v2 S3Client (DefaultCredentialsProvider, region + optional endpoint-override from BillingS3ExportConfig); upload(key, bytes) → putObject with retry/backoff; idempotent (same key on retry → overwrite).
- Testcontainers + LocalStack S3 integration test: upload an object, read it back, assert content + key.
Acceptance
- IT passes against LocalStack.
- Retries on transient failure; clear error surfaced on give-up.
Thin component that PUTs bytes to S3, isolated so it's testable on its own — and the earliest validation vehicle for real bucket + auth once SecEng grants access.
What to do
S3BillingUploader: AWS SDK v2S3Client(DefaultCredentialsProvider, region + optionalendpoint-overridefromBillingS3ExportConfig);upload(key, bytes)→putObjectwith retry/backoff; idempotent (same key on retry → overwrite).Acceptance