Files
creator-hub/internal/phasea/migrations/001_phase_a.sql
T

108 lines
4.0 KiB
PL/PgSQL

CREATE TABLE credential_reference (
id text PRIMARY KEY,
provider text NOT NULL CHECK (provider IN ('os_keyring', 'secret_manager')),
reference_key text NOT NULL UNIQUE,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE social_account (
id text PRIMARY KEY CHECK (id ~ '^[a-z0-9][a-z0-9-]{0,31}$'),
credential_reference_id text NOT NULL UNIQUE REFERENCES credential_reference(id),
profile_id text NOT NULL UNIQUE,
version bigint NOT NULL DEFAULT 1 CHECK (version > 0),
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'paused')),
paused_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE runtime_instance (
id text PRIMARY KEY,
account_id text NOT NULL REFERENCES social_account(id),
runtime_id text NOT NULL,
acquired_at timestamptz NOT NULL DEFAULT now(),
lease_until timestamptz NOT NULL,
released_at timestamptz
);
CREATE UNIQUE INDEX one_active_runtime_per_account
ON runtime_instance (account_id) WHERE released_at IS NULL;
CREATE UNIQUE INDEX one_account_per_active_runtime
ON runtime_instance (runtime_id) WHERE released_at IS NULL;
CREATE TABLE content_draft (
id text PRIMARY KEY,
account_id text NOT NULL REFERENCES social_account(id),
version bigint NOT NULL CHECK (version > 0),
content text NOT NULL,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE confirmation (
id text PRIMARY KEY,
account_id text NOT NULL REFERENCES social_account(id),
account_version bigint NOT NULL CHECK (account_version > 0),
draft_id text NOT NULL REFERENCES content_draft(id),
draft_version bigint NOT NULL CHECK (draft_version > 0),
version bigint NOT NULL CHECK (version > 0),
confirmed_by text NOT NULL DEFAULT 'local-user' CHECK (confirmed_by = 'local-user'),
confirmed_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE operation_task (
id text PRIMARY KEY,
idempotency_key text NOT NULL UNIQUE,
account_id text NOT NULL REFERENCES social_account(id),
account_version bigint NOT NULL CHECK (account_version > 0),
draft_id text NOT NULL REFERENCES content_draft(id),
draft_version bigint NOT NULL CHECK (draft_version > 0),
confirmation_id text REFERENCES confirmation(id),
confirmation_version bigint CHECK (confirmation_version > 0),
state text NOT NULL DEFAULT 'queued' CHECK (state IN (
'queued', 'executing', 'succeeded', 'failed',
'needs_confirmation', 'policy_hold', 'cancelled'
)),
lease_owner text,
lease_until timestamptz,
current_attempt_id text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CHECK ((confirmation_id IS NULL) = (confirmation_version IS NULL))
);
CREATE TABLE execution_attempt (
id text PRIMARY KEY,
task_id text NOT NULL UNIQUE REFERENCES operation_task(id),
started_at timestamptz NOT NULL DEFAULT now(),
finished_at timestamptz,
outcome text CHECK (outcome IN ('succeeded', 'failed', 'uncertain', 'policy_hold')),
result jsonb NOT NULL DEFAULT '{}'::jsonb
);
ALTER TABLE operation_task
ADD CONSTRAINT operation_task_current_attempt_fk
FOREIGN KEY (current_attempt_id) REFERENCES execution_attempt(id);
CREATE TABLE audit_event (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
event_type text NOT NULL,
account_id text REFERENCES social_account(id),
confirmation_id text REFERENCES confirmation(id),
confirmation_version bigint,
attempt_id text REFERENCES execution_attempt(id),
task_id text REFERENCES operation_task(id),
details jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE FUNCTION reject_audit_event_mutation() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE EXCEPTION 'audit_event is append-only';
END;
$$;
CREATE TRIGGER audit_event_append_only
BEFORE UPDATE OR DELETE ON audit_event
FOR EACH ROW EXECUTE FUNCTION reject_audit_event_mutation();