Files
foundry-core/db/010-canvas-ai-receipts.sql
T
codex-bot f12c4ad8bd
Foundry Go checks / check (push) Successful in 2m51s
Foundry Go checks / check (pull_request) Successful in 3m6s
Persist queryable AI action outcomes and zero-effect rejection receipts
2026-11-08 00:53:11 +08:00

30 lines
1.6 KiB
PL/PgSQL

BEGIN;
-- Keep transport receipts independently from execution retention. Their absence
-- must never be used as proof that a paid invocation did not happen.
CREATE TABLE canvas_ai_requests (
project text NOT NULL,
workspace_id uuid NOT NULL,
account_id uuid NOT NULL,
request_id uuid NOT NULL,
board_id uuid NOT NULL,
run_id uuid,
action text NOT NULL CHECK(action IN('run.start','run.cancel','run.apply')),
operation_id uuid NOT NULL,
payload_hash text NOT NULL,
outcome text NOT NULL CHECK(outcome IN('applied','not-applied')),
response_status integer NOT NULL,
response_body jsonb NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY(project,workspace_id,account_id,request_id),
FOREIGN KEY(project,workspace_id) REFERENCES workspaces(project,id) ON DELETE CASCADE
);
-- A known zero-effect rejection may be explicitly replanned under another key;
-- a completed logical action must never execute twice under different keys.
CREATE UNIQUE INDEX canvas_ai_request_operation ON canvas_ai_requests(project,workspace_id,account_id,operation_id) WHERE outcome='applied';
-- Preserve accepted canonical requests that predate this receipt table.
INSERT INTO canvas_ai_requests(project,workspace_id,account_id,request_id,board_id,action,operation_id,payload_hash,outcome,response_status,response_body)
SELECT project,workspace_id,account_id,idempotency_key,board_id,'run.start',logical_operation_id,payload_hash,'applied',202,create_response
FROM canvas_ai_runs WHERE logical_operation_id IS NOT NULL AND create_response->>'protocol_version'='2'
ORDER BY created_at,id ON CONFLICT DO NOTHING;
COMMIT;