54 lines
2.7 KiB
SQL
54 lines
2.7 KiB
SQL
-- ImageHub: Cloud Import — storage methods + external (referenced, not copied) dataset files.
|
|
-- A storage method holds verified credentials (config_encrypted, never returned to the client)
|
|
-- for an external bucket (S3/GCS/Azure). A dataset file is then EITHER a local content-addressed
|
|
-- blob (blob_sha256 set) OR an external reference (storage_method_id + external_path set) that
|
|
-- streams from the bucket and is never copied to our servers (privacy rule C4). Idempotent
|
|
-- (CREATE/ADD ... IF NOT EXISTS) so the startup runner can apply it to volumes that predate it.
|
|
-- Apply after 018 (no semicolons inside comments or string literals — the runner splitter is naive):
|
|
-- docker exec -i initiative-postgres psql -U initiative -d initiatives < be0/migrations/019_imagehub_cloud_import.sql
|
|
|
|
CREATE TABLE IF NOT EXISTS imagehub_storage_methods (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
provider TEXT NOT NULL CHECK (provider IN ('s3','gcs','azure')),
|
|
access_mode TEXT NOT NULL DEFAULT 'read' CHECK (access_mode IN ('read','readwrite')),
|
|
bucket TEXT NOT NULL,
|
|
region TEXT,
|
|
config_encrypted TEXT NOT NULL,
|
|
verification_status TEXT NOT NULL DEFAULT 'pending' CHECK (verification_status IN ('pending','verified','failed')),
|
|
verification_reason TEXT,
|
|
verification_checked_at TIMESTAMPTZ,
|
|
created_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_imagehub_storage_methods_owner
|
|
ON imagehub_storage_methods (owner_id);
|
|
|
|
-- Allow a dataset file to be an external reference instead of a local blob. Existing rows keep
|
|
-- blob_sha256 set and the new columns NULL, so they satisfy the local-blob branch of the CHECK.
|
|
ALTER TABLE imagehub_dataset_files
|
|
ALTER COLUMN blob_sha256 DROP NOT NULL;
|
|
|
|
ALTER TABLE imagehub_dataset_files
|
|
ADD COLUMN IF NOT EXISTS storage_method_id UUID REFERENCES imagehub_storage_methods(id) ON DELETE RESTRICT;
|
|
|
|
ALTER TABLE imagehub_dataset_files
|
|
ADD COLUMN IF NOT EXISTS external_path TEXT;
|
|
|
|
-- A file is EITHER a local content-addressed blob OR an external reference, never both or neither.
|
|
ALTER TABLE imagehub_dataset_files
|
|
DROP CONSTRAINT IF EXISTS ck_imagehub_file_storage_mode;
|
|
|
|
ALTER TABLE imagehub_dataset_files
|
|
ADD CONSTRAINT ck_imagehub_file_storage_mode CHECK (
|
|
(blob_sha256 IS NOT NULL AND storage_method_id IS NULL AND external_path IS NULL)
|
|
OR
|
|
(blob_sha256 IS NULL AND storage_method_id IS NOT NULL AND external_path IS NOT NULL)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_imagehub_dataset_files_storage_method
|
|
ON imagehub_dataset_files (storage_method_id);
|