feat: Presigned object URLs (s3 driver)

POST /buckets/:id/object-presigns mints SigV4 query-signed GET/PUT
URLs so clients move bytes directly against S3 — large transfers skip
the backend entirely.

- storage.Presigner optional interface; S3Store implements, local
  driver returns a clear error (no external surface to sign).
- TTL 60s–1h (default 15m); download requires read role + existing
  object row (no key probing); upload requires write role.
- S3_PUBLIC_ENDPOINT rewrites the client-facing host for internal
  S3_ENDPOINTs — signatures bind the host, URLs are valid only where
  minted.
- CLI: primora objects:presign <bucket> <key> [--upload] [--ttl].

Verified live against cloudserver: GET fetched the object with no
auth headers; PUT pushed 1 MB direct to S3; unsigned list → 403;
untracked-key download presign → 404.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-24 20:35:21 +02:00
1 parent a84049b8fc
commit fd36389328
22 files changed
+446 -7

No files matched your search

+6 -4
View File
@@ -365,10 +365,12 @@ Ordered loosely by leverage. None committed; each gets scoped when picked.
Runs record trigger source (`manual`/`schedule`/`hook`/`event`).
Remaining candidate: isolated runtimes (sidecar/Firecracker) for
untrusted code — functions still execute with backend host privileges.
- **Phase 10 — Storage backends** — ✅ S3-compatible object storage shipped:
`BACKEND_STORAGE_DRIVER=s3` + `S3_*` env vars, stdlib SigV4, verified
against a real S3 server. Presigned-URL uploads for large files remain a
candidate.
- **Phase 10 — Storage backends** — ✅ shipped: `BACKEND_STORAGE_DRIVER=s3`
+ `S3_*` env vars, stdlib SigV4, verified against a real S3 server.
Presigned upload/download URLs shipped: `POST
/buckets/:id/object-presigns` mints SigV4 query-signed GET/PUT URLs
(`S3_PUBLIC_ENDPOINT` rewrites the client-facing host); local driver
returns a clear error — a presigned URL needs a real object API behind it.
- **HA mode** — ✅ shipped: PostgreSQL advisory-lock leadership for the
scheduler and alert evaluator; failover verified with two replicas.
- **Email surface** — ✅ shipped: templated sends + `core.email_log` +