Loading
feat(datastore): blob_storage_attachments foundation table and helper
Why
The blob_storage_attachments table is outside every format spec and outside S06's storage-layer scope, leaving OCI/Maven/npm Step 1s blocked on foundation work no one owned. This MR ships the unowned half: the partitioned table (64 hash partitions on sha256), the explicit sequence, the namespaces FK, the lookup index, and a shared BlobStorageAttachmentStore datastore. Format Step 1 schemas can now declare their composite FK against a real parent.
Closes #92 (closed). Plan: docs/plans/2026-05-21-blob-storage-attachments-foundation.md. Related: ADR-007, ADR-022, S06 Step 6 (FK lands with blob_storage_blobs), S12.
What
- FK to
blob_storage_blobsdeferred to S06 Step 6 (parent table not yet on trunk). The wrap matches both SQLSTATE 23503 and the blob FK constraint name, so a namespaces FK violation (caller passed a non-existentnamespaceID) takes the generic wrap path, notErrParentBlobMissing. The blob-FK integration test appends to this file in S06 Step 6. - Named-query metric carries a
TODO(#92-followup-S03)marker. A one-line follow-up MR after S03 ships the helper. - Folds in S12 line 280 + 284 spec corrections (id-column shape and PK shape) so spec and migration agree same-day.
Context for LLM agents
Rationale
- Explicit sequence (
DEFAULT nextval(...)+OWNED BY), notGENERATED ALWAYS AS IDENTITY. ADR-022 namespace migration re-inserts rows with source-deploymentidvalues withoutOVERRIDING SYSTEM VALUE. ErrParentBlobMissingwrap omitsPgError.Detail/Where. These can echo attacker-suppliednamespace_idandsha256from the violating key. The defaultfmt.Errorf("%w", pgErr)already excludes them per pgx/v5; the helper structure keeps the omission explicit.
Non-goals
Deletehelper. Every delete callsite is conditional and format-specific; a by-id delete would mislead callers.
Edited by Hayley Swimelar