Files
cmroubao/backend-api/migrations/00008_order_authorizations.sql
T

247 lines
7.6 KiB
SQL

-- +goose Up
ALTER TABLE task_events RENAME TO task_events_v7;
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_v7;
DROP TABLE task_events_v7;
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);
CREATE TABLE order_authorizations (
id TEXT PRIMARY KEY NOT NULL
CHECK (length(id) = 36),
task_id TEXT NOT NULL
REFERENCES purchase_tasks(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
execution_id TEXT NOT NULL
REFERENCES task_executions(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
authorization_version INTEGER NOT NULL
CHECK (authorization_version > 0),
candidate_key TEXT NOT NULL
REFERENCES candidate_observation_identities(candidate_key)
ON UPDATE RESTRICT ON DELETE RESTRICT,
task_content_sha256 TEXT NOT NULL
CHECK (
length(task_content_sha256) = 64
AND task_content_sha256 NOT GLOB '*[^0-9a-f]*'
),
task_version INTEGER NOT NULL
CHECK (task_version > 0),
review_id TEXT NOT NULL
REFERENCES candidate_human_reviews(id)
ON UPDATE RESTRICT ON DELETE RESTRICT,
review_version INTEGER NOT NULL
CHECK (review_version > 0),
user_id TEXT NOT NULL
REFERENCES users(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
device_id TEXT NOT NULL
REFERENCES devices(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
claim_generation INTEGER NOT NULL
CHECK (claim_generation > 0),
original_sku TEXT NOT NULL
CHECK (
length(trim(original_sku)) > 0
AND length(CAST(original_sku AS BLOB)) <= 512
),
quantity INTEGER NOT NULL
CHECK (quantity > 0),
candidate_sku_text TEXT NOT NULL
CHECK (length(CAST(candidate_sku_text AS BLOB)) <= 512),
candidate_price_text TEXT NOT NULL
CHECK (length(CAST(candidate_price_text AS BLOB)) <= 64),
card_signature TEXT NOT NULL
CHECK (
length(card_signature) = 64
AND card_signature NOT GLOB '*[^0-9a-f]*'
),
detail_signature TEXT NOT NULL
CHECK (
length(detail_signature) = 64
AND detail_signature NOT GLOB '*[^0-9a-f]*'
),
detail_evidence_sha256 TEXT NOT NULL
CHECK (
length(detail_evidence_sha256) = 64
AND detail_evidence_sha256 NOT GLOB '*[^0-9a-f]*'
),
specification_evidence_sha256 TEXT NOT NULL
CHECK (
length(specification_evidence_sha256) = 64
AND specification_evidence_sha256 NOT GLOB '*[^0-9a-f]*'
),
status TEXT NOT NULL
CHECK (
status IN (
'PENDING_DELIVERY',
'DELIVERED',
'ACKNOWLEDGED',
'EXECUTING',
'CONSUMED',
'FAILED',
'REVOKED',
'SUPERSEDED'
)
),
supersedes_authorization_id TEXT
REFERENCES order_authorizations(id)
ON UPDATE RESTRICT ON DELETE RESTRICT,
created_by_user_id TEXT NOT NULL
REFERENCES users(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
created_at TEXT NOT NULL,
delivered_at TEXT,
acknowledged_at TEXT,
execution_started_at TEXT,
consumed_at TEXT,
failed_at TEXT,
revoked_at TEXT,
failure_code TEXT,
failure_message TEXT,
UNIQUE (execution_id, authorization_version)
);
CREATE UNIQUE INDEX order_authorizations_active_execution_idx
ON order_authorizations (execution_id)
WHERE status IN (
'PENDING_DELIVERY',
'DELIVERED',
'ACKNOWLEDGED',
'EXECUTING'
);
CREATE INDEX order_authorizations_task_created_idx
ON order_authorizations (task_id, created_at DESC, id DESC);
CREATE TABLE admin_order_authorization_requests (
actor_user_id TEXT NOT NULL
REFERENCES users(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 (actor_user_id, idempotency_key)
);
-- +goose Down
CREATE TEMP TABLE order_authorizations_v8_down_guard (
allowed INTEGER NOT NULL
CHECK (allowed = 1)
);
INSERT INTO order_authorizations_v8_down_guard (allowed)
SELECT CASE
WHEN EXISTS (SELECT 1 FROM order_authorizations)
OR EXISTS (
SELECT 1
FROM task_events
WHERE event_type IN (
'CANDIDATES_READY',
'ORDER_AUTHORIZATION_CREATED'
)
)
THEN 0
ELSE 1
END;
DROP TABLE order_authorizations_v8_down_guard;
DROP TABLE admin_order_authorization_requests;
DROP TABLE order_authorizations;
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'
)
),
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);