-- Dual-mode identity, operations, jobs, artifacts, tool packages, grants. -- shared computers may have many bots; do NOT add UNIQUE(bots.computer_id). ALTER TABLE computers ADD COLUMN IF NOT EXISTS generation INTEGER NOT NULL DEFAULT 1, ADD COLUMN IF NOT EXISTS computer_epoch BIGINT NOT NULL DEFAULT 0, ADD COLUMN IF NOT EXISTS display_backend TEXT NOT NULL DEFAULT 'xvfb_x11vnc'; CREATE TABLE IF NOT EXISTS computer_operations ( id TEXT PRIMARY KEY, computer_id TEXT NOT NULL REFERENCES computers (id) ON DELETE CASCADE, bot_id TEXT NOT NULL, run_id TEXT, payload_hash TEXT NOT NULL, status TEXT NOT NULL, result TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE UNIQUE INDEX IF NOT EXISTS computer_operations_id_hash ON computer_operations (id, payload_hash); CREATE TABLE IF NOT EXISTS computer_jobs ( id TEXT PRIMARY KEY, computer_id TEXT NOT NULL REFERENCES computers (id) ON DELETE CASCADE, generation INTEGER NOT NULL DEFAULT 1, bot_id TEXT NOT NULL, status TEXT NOT NULL, argv JSONB NOT NULL DEFAULT '[]'::jsonb, pin_version TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); ALTER TABLE computer_jobs ADD COLUMN IF NOT EXISTS pin_version TEXT; CREATE TABLE IF NOT EXISTS computer_artifacts ( id TEXT PRIMARY KEY, computer_id TEXT NOT NULL REFERENCES computers (id) ON DELETE CASCADE, bot_id TEXT NOT NULL, relative_path TEXT NOT NULL, sha256 TEXT NOT NULL, size BIGINT NOT NULL DEFAULT 0, operation_id TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS tool_packages ( id TEXT PRIMARY KEY, computer_id TEXT NOT NULL REFERENCES computers (id) ON DELETE CASCADE, package_id TEXT NOT NULL, version TEXT NOT NULL, sha256 TEXT NOT NULL, status TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (computer_id, package_id, version) ); CREATE TABLE IF NOT EXISTS tool_bindings ( id TEXT PRIMARY KEY, package_row_id TEXT NOT NULL REFERENCES tool_packages (id) ON DELETE CASCADE, bot_id TEXT NOT NULL, account_id TEXT, status TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (package_row_id, bot_id) ); CREATE TABLE IF NOT EXISTS tool_grants ( id TEXT PRIMARY KEY, bot_id TEXT NOT NULL REFERENCES bots (id) ON DELETE CASCADE, capability TEXT NOT NULL, account_ref TEXT, expires_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS operation_outbox ( id TEXT PRIMARY KEY, event_key TEXT NOT NULL UNIQUE, payload JSONB NOT NULL, delivered BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT now() );