-- +goose Up -- +goose StatementBegin CREATE TABLE IF NOT EXISTS repos ( id TEXT PRIMARY KEY, name TEXT NOT NULL, remote_url TEXT NOT NULL, default_branch TEXT NOT NULL, workspace_root TEXT NOT NULL, credential_ref TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS workspace_leases ( id TEXT PRIMARY KEY, repo_id TEXT NOT NULL REFERENCES repos(id), slot TEXT NOT NULL, path TEXT NOT NULL, state TEXT NOT NULL, expires_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (repo_id, slot) ); CREATE TABLE IF NOT EXISTS operations ( id TEXT PRIMARY KEY, repo_id TEXT NOT NULL REFERENCES repos(id), type TEXT NOT NULL CHECK (type IN ('clone', 'fetch', 'commit', 'push', 'agent_run')), state TEXT NOT NULL CHECK (state IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')), idempotency_key TEXT CHECK (idempotency_key IS NULL OR btrim(idempotency_key) <> ''), created_by TEXT NOT NULL CHECK (btrim(created_by) <> ''), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX IF NOT EXISTS ux_operations_idempotency ON operations (idempotency_key) WHERE idempotency_key IS NOT NULL; CREATE TABLE IF NOT EXISTS operation_events ( id TEXT PRIMARY KEY, operation_id TEXT REFERENCES operations(id), type TEXT NOT NULL, subject TEXT NOT NULL, payload JSONB NOT NULL DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), published_at TIMESTAMPTZ ); CREATE INDEX IF NOT EXISTS ix_operation_events_operation_ordering ON operation_events (operation_id, created_at, id); CREATE INDEX IF NOT EXISTS ix_operation_events_pending_ordering ON operation_events (created_at, id) WHERE published_at IS NULL; CREATE TABLE IF NOT EXISTS revision_cursors ( repo_id TEXT NOT NULL, branch TEXT NOT NULL, revision TEXT NOT NULL, observed_at TIMESTAMPTZ NOT NULL DEFAULT now(), PRIMARY KEY (repo_id, branch) ); ALTER TABLE revision_cursors DROP CONSTRAINT IF EXISTS revision_cursors_repo_id_fkey; CREATE TABLE IF NOT EXISTS branch_watches ( id TEXT PRIMARY KEY, provider TEXT NOT NULL, repo_id TEXT NOT NULL, branch TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (provider, repo_id, branch) ); CREATE TABLE IF NOT EXISTS provider_deliveries ( id TEXT PRIMARY KEY, provider TEXT NOT NULL, delivery_id TEXT NOT NULL, dedupe_key TEXT NOT NULL, event_id TEXT NOT NULL, repo_id TEXT NOT NULL, branch TEXT NOT NULL, revision TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (provider, dedupe_key) ); CREATE TABLE IF NOT EXISTS provider_configs ( id TEXT PRIMARY KEY, endpoint TEXT NOT NULL CHECK (btrim(endpoint) <> ''), credential_ref TEXT, capabilities BIGINT NOT NULL CHECK (capabilities >= 0), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS agent_run_inputs ( operation_id TEXT PRIMARY KEY REFERENCES operations(id), repo_id TEXT NOT NULL CHECK (btrim(repo_id) <> ''), branch TEXT NOT NULL CHECK (btrim(branch) <> ''), workspace_path TEXT NOT NULL CHECK (btrim(workspace_path) <> ''), instruction TEXT NOT NULL CHECK (btrim(instruction) <> ''), policy_context JSONB NOT NULL DEFAULT '{}', expected_revision TEXT NOT NULL CHECK (btrim(expected_revision) <> ''), created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS webhook_deliveries ( id TEXT PRIMARY KEY, event_id TEXT NOT NULL, subscription_id TEXT NOT NULL, status TEXT NOT NULL CHECK (status IN ('pending', 'sending', 'succeeded', 'retryable', 'failed')), attempt_count INTEGER NOT NULL DEFAULT 0, next_attempt_at TIMESTAMPTZ NOT NULL DEFAULT now(), last_status_code INTEGER NOT NULL DEFAULT 0, last_error TEXT NOT NULL DEFAULT '', created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (event_id, subscription_id) ); CREATE INDEX IF NOT EXISTS ix_webhook_deliveries_pending ON webhook_deliveries (next_attempt_at, status) WHERE status IN ('pending', 'retryable'); -- +goose StatementEnd -- +goose Down -- +goose StatementBegin DROP TABLE IF EXISTS provider_configs; DROP TABLE IF EXISTS webhook_deliveries; DROP TABLE IF EXISTS agent_run_inputs; DROP TABLE IF EXISTS provider_deliveries; DROP TABLE IF EXISTS branch_watches; DROP TABLE IF EXISTS revision_cursors; DROP TABLE IF EXISTS operation_events; DROP TABLE IF EXISTS operations; DROP TABLE IF EXISTS workspace_leases; DROP TABLE IF EXISTS repos; -- +goose StatementEnd