feat: P1 storage service, tables, probe and conformance suite #4

Merged
KofTwentyTwo merged 8 commits from feature/p1-storage-service into develop 2026-10-12 22:25:38 +00:00
KofTwentyTwo commented 2026-10-12 21:28:47 +00:00 (Migrated from github.com)

P1: the storage service

Implements P1 of the object storage design (QRun-IO/qqq#1089).

What is in it

  • ObjectStorage.bucket(alias) and ObjectStorage.asSystem(caller, runId).bucket(alias): put (stream, multipart above 16 MB), get (ranges), head, copy (multipart for very large objects), updateHeaders, delete (versioned delete marker, private trash, or permanent), restore, list, purgeKeys (batch with single-delete fallback), presigned GET/PUT/POST, publicUrl.
  • Key building and URL encoding (StorageKeys), header policy (object_storage_header_rule), PublicUrlResolver, StorageChangeListener, StorageReferenceProvider, alert sink SPI.
  • Config from code, upserted into visible object_storage_* tables; secret references with an allow-list; per-bucket and per-connection record security locks.
  • Capability model, the probe, and the Test connection record actions (standard streamed ETL: Review, Result), including clock skew and presign-host checks.
  • object_storage_operation audit log; protection rules; SF1 to SF5 for backups (BACKUP role, object lock on put, system-caller permanent delete, probes skip locked backup buckets, system-caller context).
  • Admin -> Storage app with a real home (buckets, data health, recent changes, cache headers, usage trend, connections).
  • Conformance suite (ObjectStorageConformanceSuite) against MinIO (digest-pinned Chainguard build) and Garage (digest-pinned) with Testcontainers.

Stand-in

P0 (QQQ S3 module on SDK v2, qqq#1095) ships in RC.5. Until then ConnectionRuntime is a small internal AWS SDK v2 client factory, marked for replacement with core's S3ClientFactory. It does not leak into the public API.

Deviations from the spec text (all noted in code)

  • ObjectStorage.asSystem(..) returns a SystemStorage (a static and an instance bucket cannot share a name).
  • Test connection is two actions ("Test connection", "Test connection with write tests") instead of a tick box, so the write variant can be permission-gated to object_storage.admin.
  • No withTableNamePrefix: the object_storage_ prefix is fixed by the owner naming rule.
  • A folder record has no "subfolders" child list (core does not allow a self join as an exposed join); subfolders are reachable by filtering Folders on the parent.

🤖 Generated with Claude Code

## P1: the storage service Implements P1 of the object storage design (QRun-IO/qqq#1089). ### What is in it - `ObjectStorage.bucket(alias)` and `ObjectStorage.asSystem(caller, runId).bucket(alias)`: put (stream, multipart above 16 MB), get (ranges), head, copy (multipart for very large objects), `updateHeaders`, delete (versioned delete marker, private trash, or permanent), restore, list, `purgeKeys` (batch with single-delete fallback), presigned GET/PUT/POST, `publicUrl`. - Key building and URL encoding (`StorageKeys`), header policy (`object_storage_header_rule`), `PublicUrlResolver`, `StorageChangeListener`, `StorageReferenceProvider`, alert sink SPI. - Config from code, upserted into visible `object_storage_*` tables; secret references with an allow-list; per-bucket and per-connection record security locks. - Capability model, the probe, and the **Test connection** record actions (standard streamed ETL: Review, Result), including clock skew and presign-host checks. - `object_storage_operation` audit log; protection rules; SF1 to SF5 for backups (BACKUP role, object lock on put, system-caller permanent delete, probes skip locked backup buckets, system-caller context). - Admin -> Storage app with a real home (buckets, data health, recent changes, cache headers, usage trend, connections). - Conformance suite (`ObjectStorageConformanceSuite`) against MinIO (digest-pinned Chainguard build) and Garage (digest-pinned) with Testcontainers. ### Stand-in P0 (QQQ S3 module on SDK v2, qqq#1095) ships in RC.5. Until then `ConnectionRuntime` is a small internal AWS SDK v2 client factory, marked for replacement with core's `S3ClientFactory`. It does not leak into the public API. ### Deviations from the spec text (all noted in code) - `ObjectStorage.asSystem(..)` returns a `SystemStorage` (a static and an instance `bucket` cannot share a name). - Test connection is two actions ("Test connection", "Test connection with write tests") instead of a tick box, so the write variant can be permission-gated to `object_storage.admin`. - No `withTableNamePrefix`: the `object_storage_` prefix is fixed by the owner naming rule. - A folder record has no "subfolders" child list (core does not allow a self join as an exposed join); subfolders are reachable by filtering Folders on the parent. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.