-- +goose Up ALTER TABLE order_authorizations ADD COLUMN command_sha256 TEXT CHECK ( command_sha256 IS NULL OR ( length(command_sha256) = 64 AND command_sha256 NOT GLOB '*[^0-9a-f]*' ) ); ALTER TABLE order_authorizations ADD COLUMN delivery_attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (delivery_attempt_count >= 0); ALTER TABLE order_authorizations ADD COLUMN last_delivered_at TEXT; CREATE TABLE device_order_command_ack_requests ( device_id TEXT NOT NULL REFERENCES devices(id) ON UPDATE RESTRICT ON DELETE RESTRICT, idempotency_key TEXT NOT NULL CHECK ( length(trim(idempotency_key)) > 0 AND length(CAST(idempotency_key AS BLOB)) <= 128 ), request_sha256 TEXT NOT NULL CHECK ( length(request_sha256) = 64 AND request_sha256 NOT GLOB '*[^0-9a-f]*' ), task_id TEXT NOT NULL REFERENCES purchase_tasks(id) ON UPDATE RESTRICT ON DELETE RESTRICT, authorization_id TEXT NOT NULL REFERENCES order_authorizations(id) ON UPDATE RESTRICT ON DELETE RESTRICT, created_at TEXT NOT NULL, PRIMARY KEY (device_id, idempotency_key) ); ALTER TABLE task_events RENAME TO task_events_v8; CREATE TABLE task_events ( id TEXT PRIMARY KEY NOT NULL CHECK (length(id) = 36), task_id TEXT NOT NULL REFERENCES purchase_tasks(id) ON UPDATE RESTRICT ON DELETE CASCADE, event_type TEXT NOT NULL CHECK ( event_type IN ( 'TASK_CREATED', 'TASK_CLAIMED', 'TASK_RECLAIMED', 'TASK_RELEASED', 'TASK_STARTED', 'TASK_CANCEL_REQUESTED', 'TASK_CANCELED', 'CANDIDATES_READY', 'ORDER_AUTHORIZATION_CREATED', 'ORDER_AUTHORIZATION_DELIVERED', 'ORDER_AUTHORIZATION_ACKNOWLEDGED' ) ), message TEXT NOT NULL, occurred_at TEXT NOT NULL, actor_user_id TEXT REFERENCES users(id) ON UPDATE RESTRICT ON DELETE RESTRICT, actor_device_id TEXT REFERENCES devices(id) ON UPDATE RESTRICT ON DELETE RESTRICT ); INSERT INTO task_events ( id, task_id, event_type, message, occurred_at, actor_user_id, actor_device_id ) SELECT id, task_id, event_type, message, occurred_at, actor_user_id, actor_device_id FROM task_events_v8; DROP TABLE task_events_v8; CREATE INDEX task_events_task_occurred_idx ON task_events (task_id, occurred_at ASC, id ASC); CREATE INDEX task_events_actor_user_idx ON task_events (actor_user_id, occurred_at DESC, id DESC); CREATE INDEX task_events_actor_device_idx ON task_events (actor_device_id, occurred_at DESC, id DESC); -- +goose Down CREATE TEMP TABLE device_order_commands_v9_down_guard ( allowed INTEGER NOT NULL CHECK (allowed = 1) ); INSERT INTO device_order_commands_v9_down_guard (allowed) SELECT CASE WHEN EXISTS (SELECT 1 FROM device_order_command_ack_requests) OR EXISTS ( SELECT 1 FROM order_authorizations WHERE command_sha256 IS NOT NULL OR delivery_attempt_count > 0 OR last_delivered_at IS NOT NULL OR status IN ('DELIVERED', 'ACKNOWLEDGED') ) OR EXISTS ( SELECT 1 FROM task_events WHERE event_type IN ( 'ORDER_AUTHORIZATION_DELIVERED', 'ORDER_AUTHORIZATION_ACKNOWLEDGED' ) ) THEN 0 ELSE 1 END; DROP TABLE device_order_commands_v9_down_guard; DROP TABLE device_order_command_ack_requests; ALTER TABLE task_events RENAME TO task_events_v9; CREATE TABLE task_events ( id TEXT PRIMARY KEY NOT NULL CHECK (length(id) = 36), task_id TEXT NOT NULL REFERENCES purchase_tasks(id) ON UPDATE RESTRICT ON DELETE CASCADE, event_type TEXT NOT NULL CHECK ( event_type IN ( 'TASK_CREATED', 'TASK_CLAIMED', 'TASK_RECLAIMED', 'TASK_RELEASED', 'TASK_STARTED', 'TASK_CANCEL_REQUESTED', 'TASK_CANCELED', 'CANDIDATES_READY', 'ORDER_AUTHORIZATION_CREATED' ) ), message TEXT NOT NULL, occurred_at TEXT NOT NULL, actor_user_id TEXT REFERENCES users(id) ON UPDATE RESTRICT ON DELETE RESTRICT, actor_device_id TEXT REFERENCES devices(id) ON UPDATE RESTRICT ON DELETE RESTRICT ); INSERT INTO task_events ( id, task_id, event_type, message, occurred_at, actor_user_id, actor_device_id ) SELECT id, task_id, event_type, message, occurred_at, actor_user_id, actor_device_id FROM task_events_v9; DROP TABLE task_events_v9; CREATE INDEX task_events_task_occurred_idx ON task_events (task_id, occurred_at ASC, id ASC); CREATE INDEX task_events_actor_user_idx ON task_events (actor_user_id, occurred_at DESC, id DESC); CREATE INDEX task_events_actor_device_idx ON task_events (actor_device_id, occurred_at DESC, id DESC); ALTER TABLE order_authorizations DROP COLUMN last_delivered_at; ALTER TABLE order_authorizations DROP COLUMN delivery_attempt_count; ALTER TABLE order_authorizations DROP COLUMN command_sha256;