-- Operator-run only: psql -v ON_ERROR_STOP=1 -v runtime_role=btcdata_archiver -f sql/setup.sql -- Create the login separately with a password supplied through secure operator tooling. BEGIN; CREATE SCHEMA IF NOT EXISTS btcdata_archive; CREATE TABLE IF NOT EXISTS btcdata_archive.weeks ( week_start timestamptz PRIMARY KEY, week_end timestamptz NOT NULL, format_version integer NOT NULL CHECK (format_version = 1), status text NOT NULL CHECK (status IN ('exporting','verified','pruning','complete','failed')), object_key text NOT NULL, object_version_id text, file_sha256 text CHECK (file_sha256 ~ '^[0-9a-f]{64}$'), row_counts jsonb, deletion_counts jsonb, attempt_time timestamptz NOT NULL, completion_time timestamptz, last_error text, CHECK (week_end - week_start = interval '168 hours'), CHECK (extract(isodow FROM week_start AT TIME ZONE 'UTC') = 1), CHECK ((week_start AT TIME ZONE 'UTC')::time = time '00:00:00'), CHECK (status NOT IN ('verified','pruning','complete') OR (object_version_id IS NOT NULL AND object_version_id <> 'null' AND file_sha256 IS NOT NULL)) ); REVOKE ALL ON SCHEMA btcdata_archive FROM PUBLIC; REVOKE ALL ON btcdata_archive.weeks FROM PUBLIC; GRANT CONNECT, TEMPORARY ON DATABASE :"DBNAME" TO :"runtime_role"; GRANT USAGE ON SCHEMA public, btcdata_archive TO :"runtime_role"; GRANT SELECT, DELETE ON public.binance_price, public.strike_price, public.kraken_minute TO :"runtime_role"; GRANT SELECT, INSERT, UPDATE ON btcdata_archive.weeks TO :"runtime_role"; COMMIT;