-- Fresh-only enrollment of empty diagnostic tables. No historical backfill, -- source-generation claim, public registration or automatic cleanup is granted. BEGIN; LOCK TABLE server_probe_executions,server_probe_execution_stages,server_probe_execution_quarantines,mcp_diagnostic_cancellations IN ACCESS EXCLUSIVE MODE; DO $$ BEGIN IF EXISTS(SELECT 1 FROM server_probe_executions) OR EXISTS(SELECT 1 FROM server_probe_execution_stages) OR EXISTS(SELECT 1 FROM server_probe_execution_quarantines) OR EXISTS(SELECT 1 FROM mcp_diagnostic_cancellations) THEN RAISE EXCEPTION 'nonempty legacy diagnostic history prevents fresh storage enrollment'; END IF; IF EXISTS(SELECT 1 FROM pg_catalog.pg_class WHERE relname IN ('server_probe_storage_usage','server_probe_storage_admissions','server_probe_execution_payloads')) THEN RAISE EXCEPTION 'unmarked diagnostic storage relation prevents fresh storage enrollment'; END IF; IF NOT EXISTS(SELECT 1 FROM mcp_settings WHERE id=1 AND requests_retention_days BETWEEN 1 AND 365) THEN RAISE EXCEPTION 'authoritative probe retention setting unavailable'; END IF; END $$; CREATE TABLE server_probe_storage_usage ( scope text PRIMARY KEY CHECK(scope='global' OR (scope LIKE 'owner:%' AND length(scope) BETWEEN 7 AND 206)), admissions bigint NOT NULL DEFAULT 0 CHECK(admissions>=0), reserved_files bigint NOT NULL DEFAULT 0 CHECK(reserved_files>=0 AND reserved_files<=admissions), reserved_bytes bigint NOT NULL DEFAULT 0 CHECK(reserved_bytes>=0), CHECK(reserved_bytes=admissions*32768+reserved_files*262144) ); CREATE TABLE server_probe_storage_admissions ( receipt_id uuid PRIMARY KEY, owner_id text NOT NULL CHECK(length(owner_id) BETWEEN 1 AND 200), identity_kind text NOT NULL CHECK(identity_kind IN ('mcp','rest')), execution_id uuid NOT NULL, binding_proof text NOT NULL CHECK(binding_proof ~ '^[a-f0-9]{64}$'), authority_expires_at timestamptz NOT NULL, claim_token uuid, claim_attempted_at timestamptz, purged_at timestamptz, cancelled_at timestamptz, created_at timestamptz NOT NULL DEFAULT clock_timestamp(), retention_days integer NOT NULL CHECK(retention_days BETWEEN 1 AND 365), safety_ms integer NOT NULL DEFAULT 60000 CHECK(safety_ms BETWEEN 60000 AND 86400000), gc_not_before timestamptz NOT NULL DEFAULT 'infinity', CHECK(gc_not_before>=authority_expires_at+make_interval(days=>retention_days)+safety_ms*interval '1 millisecond'), UNIQUE(identity_kind,execution_id), CHECK(claim_token IS NULL OR (claim_attempted_at IS NULL AND purged_at IS NULL AND cancelled_at IS NULL)), CHECK(cancelled_at IS NULL OR (claim_token IS NULL AND claim_attempted_at IS NOT NULL)) ); CREATE INDEX server_probe_storage_admissions_owner_age ON server_probe_storage_admissions(owner_id,authority_expires_at,receipt_id); CREATE TABLE server_probe_execution_payloads ( receipt_id uuid PRIMARY KEY REFERENCES server_probe_executions(receipt_id), receipt_ciphertext text NOT NULL CHECK(octet_length(receipt_ciphertext) BETWEEN 1 AND 262144), receipt_proof text NOT NULL CHECK(receipt_proof ~ '^[a-f0-9]{64}$') ); INSERT INTO server_probe_storage_usage(scope,admissions,reserved_files,reserved_bytes) VALUES('global',0,0,0); -- PostgreSQL drops table CHECKs dependent on this column together with it. -- The locked empty-table guard precedes this column removal; no data is copied. ALTER TABLE server_probe_executions DROP COLUMN receipt_ciphertext; ALTER TABLE server_probe_executions ADD CONSTRAINT server_probe_storage_terminal_state CHECK( (state='claimed' AND receipt_proof IS NULL AND finished_at IS NULL AND attempted_stages IS NULL AND completed_stages IS NULL) OR(state<>'claimed' AND receipt_proof IS NOT NULL AND finished_at IS NOT NULL AND attempted_stages IS NOT NULL AND completed_stages IS NOT NULL)); -- Predicate only: it performs no DELETE. Every guarded exception below must -- independently satisfy the persisted lifetime, actual current retention and -- original terminal operation. The GUC alone never grants cleanup authority. CREATE FUNCTION server_probe_storage_gc_allowed(id uuid) RETURNS boolean LANGUAGE plpgsql SET TimeZone='UTC' AS $$ DECLARE a server_probe_storage_admissions%ROWTYPE; activity timestamptz; current_retention integer; terminal_at timestamptz; BEGIN IF current_setting('mm.probe_storage_gc',true) IS DISTINCT FROM 'on' THEN RETURN false; END IF; PERFORM pg_advisory_xact_lock(hashtextextended('server-probe-storage-v2',0)); SELECT * INTO a FROM server_probe_storage_admissions WHERE receipt_id=id FOR UPDATE; IF NOT FOUND OR a.gc_not_before>=clock_timestamp() OR a.authority_expires_at>=clock_timestamp() THEN RETURN false; END IF; SELECT settings.requests_retention_days INTO current_retention FROM mcp_settings settings WHERE settings.id=1; IF current_retention IS NULL OR current_retention NOT BETWEEN 1 AND 365 THEN RETURN false; END IF; terminal_at:=a.created_at; IF a.identity_kind='mcp' THEN SELECT GREATEST(o.finished_at,p.expires_at,COALESCE(cancellation.created_at,o.finished_at)) INTO terminal_at FROM mcp_operations o JOIN mcp_plans p ON p.id=o.plan_id AND p.connection_id=o.connection_id JOIN mcp_connections owner_connection ON owner_connection.id=o.connection_id LEFT JOIN mcp_diagnostic_cancellations cancellation ON cancellation.operation_id=o.id WHERE o.id=a.execution_id AND owner_connection.owner_id=a.owner_id AND p.operation_id='servers.probes.run' AND o.state IN ('applied','failed','unknown','rejected','partial','cancelled') AND o.finished_at IS NOT NULL AND (cancellation.operation_id IS NULL OR(cancellation.connection_id=o.connection_id AND cancellation.actor_id=a.owner_id)) FOR UPDATE OF o,p,owner_connection; IF NOT FOUND OR terminal_at IS NULL THEN RETURN false; END IF; END IF; SELECT GREATEST(a.created_at,a.authority_expires_at,terminal_at,COALESCE(a.cancelled_at,a.created_at), COALESCE((SELECT finished_at FROM server_probe_executions WHERE receipt_id=id),a.created_at), COALESCE((SELECT created_at FROM server_probe_execution_quarantines WHERE receipt_id=id),a.created_at), COALESCE((SELECT max(GREATEST(created_at,COALESCE(received_at,created_at))) FROM server_probe_execution_stages WHERE receipt_id=id),a.created_at)) INTO activity; RETURN activity+make_interval(days=>GREATEST(a.retention_days,current_retention))+a.safety_ms*interval '1 millisecond'clock_timestamp() THEN RETURN NEW; END IF; IF OLD.purged_at IS NULL AND NEW.purged_at IS NOT NULL AND NEW.claim_token IS NULL AND NEW.claim_attempted_at IS NOT DISTINCT FROM OLD.claim_attempted_at THEN SELECT GREATEST(OLD.authority_expires_at,COALESCE(e.finished_at,OLD.authority_expires_at),COALESCE(q.created_at,OLD.authority_expires_at)) INTO activity FROM (SELECT 1) x LEFT JOIN server_probe_executions e ON e.receipt_id=OLD.receipt_id LEFT JOIN server_probe_execution_quarantines q ON q.receipt_id=OLD.receipt_id; IF activityGREATEST(OLD.retention_days,current_retention)) THEN RETURN NEW; END IF; END IF; RAISE EXCEPTION 'probe admission transition refused'; END $$; CREATE TRIGGER server_probe_storage_admission_guard BEFORE INSERT OR UPDATE OR DELETE ON server_probe_storage_admissions FOR EACH ROW EXECUTE FUNCTION server_probe_storage_admission_guard(); CREATE FUNCTION server_probe_storage_anchor_guard() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE a server_probe_storage_admissions%ROWTYPE; BEGIN PERFORM pg_advisory_xact_lock(hashtextextended('server-probe-storage-v2',0)); SELECT * INTO a FROM server_probe_storage_admissions WHERE receipt_id=NEW.receipt_id FOR UPDATE; IF NOT FOUND OR a.owner_id<>NEW.actor_id OR a.identity_kind<>NEW.identity_kind OR a.execution_id<>NEW.execution_id OR a.binding_proof<>NEW.binding_proof OR a.authority_expires_at<>NEW.authority_expires_at OR a.purged_at IS NOT NULL OR a.cancelled_at IS NOT NULL OR a.claim_token IS NOT NULL OR a.claim_attempted_at IS NULL OR a.authority_expires_at<=clock_timestamp() THEN RAISE EXCEPTION 'probe anchor has no live consumed admission'; END IF; RETURN NEW; END $$; CREATE TRIGGER server_probe_storage_anchor_guard BEFORE INSERT OR UPDATE ON server_probe_executions FOR EACH ROW EXECUTE FUNCTION server_probe_storage_anchor_guard(); CREATE OR REPLACE FUNCTION server_probe_execution_immutable() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF TG_OP='DELETE' THEN IF server_probe_storage_gc_allowed(OLD.receipt_id) THEN RETURN OLD; END IF; RAISE EXCEPTION 'probe execution lifetime has not elapsed'; END IF; IF OLD.state<>'claimed' OR (to_jsonb(OLD)-ARRAY['state','attempted_stages','completed_stages','receipt_proof','finished_at']) IS DISTINCT FROM (to_jsonb(NEW)-ARRAY['state','attempted_stages','completed_stages','receipt_proof','finished_at']) OR NEW.state='claimed' THEN RAISE EXCEPTION 'probe execution identity or terminal receipt is immutable'; END IF; IF EXISTS(SELECT 1 FROM server_probe_execution_quarantines WHERE receipt_id=OLD.receipt_id) THEN RAISE EXCEPTION 'probe execution quarantined'; END IF; RETURN NEW; END $$; CREATE FUNCTION server_probe_storage_stage_guard() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN PERFORM pg_advisory_xact_lock(hashtextextended('server-probe-storage-v2',0)); PERFORM receipt_id FROM server_probe_storage_admissions WHERE receipt_id=NEW.receipt_id AND purged_at IS NULL AND cancelled_at IS NULL AND claim_token IS NULL AND claim_attempted_at IS NOT NULL AND authority_expires_at>clock_timestamp() FOR UPDATE; IF NOT FOUND THEN RAISE EXCEPTION 'probe stage has no live admission'; END IF; RETURN NEW; END $$; CREATE TRIGGER server_probe_storage_stage_guard BEFORE INSERT OR UPDATE ON server_probe_execution_stages FOR EACH ROW EXECUTE FUNCTION server_probe_storage_stage_guard(); CREATE FUNCTION server_probe_storage_quarantine_guard() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN PERFORM pg_advisory_xact_lock(hashtextextended('server-probe-storage-v2',0)); PERFORM receipt_id FROM server_probe_storage_admissions WHERE receipt_id=NEW.receipt_id AND identity_kind=NEW.identity_kind AND execution_id=NEW.execution_id AND binding_proof=NEW.binding_proof FOR UPDATE; IF NOT FOUND THEN RAISE EXCEPTION 'probe quarantine has no committed matching admission'; END IF; RETURN NEW; END $$; CREATE TRIGGER server_probe_storage_quarantine_guard BEFORE INSERT ON server_probe_execution_quarantines FOR EACH ROW EXECUTE FUNCTION server_probe_storage_quarantine_guard(); CREATE FUNCTION server_probe_storage_payload_guard() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE a server_probe_storage_admissions%ROWTYPE; e server_probe_executions%ROWTYPE; BEGIN PERFORM pg_advisory_xact_lock(hashtextextended('server-probe-storage-v2',0)); IF TG_OP='UPDATE' THEN RAISE EXCEPTION 'probe payload is immutable'; END IF; IF TG_OP='DELETE' THEN PERFORM receipt_id FROM server_probe_storage_admissions WHERE receipt_id=OLD.receipt_id AND purged_at IS NOT NULL FOR UPDATE; IF NOT FOUND AND NOT server_probe_storage_gc_allowed(OLD.receipt_id) THEN RAISE EXCEPTION 'probe payload is not purged'; END IF; RETURN OLD; END IF; SELECT * INTO a FROM server_probe_storage_admissions WHERE receipt_id=NEW.receipt_id FOR UPDATE; IF NOT FOUND OR a.purged_at IS NOT NULL OR a.cancelled_at IS NOT NULL OR a.claim_token IS NOT NULL OR a.claim_attempted_at IS NULL OR a.authority_expires_at<=clock_timestamp() THEN RAISE EXCEPTION 'probe payload has no live admission'; END IF; SELECT * INTO e FROM server_probe_executions WHERE receipt_id=NEW.receipt_id FOR UPDATE; IF NOT FOUND OR e.state='claimed' OR e.receipt_proof<>NEW.receipt_proof OR e.actor_id<>a.owner_id OR e.binding_proof<>a.binding_proof OR e.identity_kind<>a.identity_kind OR e.execution_id<>a.execution_id OR EXISTS(SELECT 1 FROM server_probe_execution_quarantines q WHERE q.receipt_id=NEW.receipt_id OR(q.identity_kind=a.identity_kind AND q.execution_id=a.execution_id)) THEN RAISE EXCEPTION 'probe payload terminal identity mismatch or quarantine'; END IF; RETURN NEW; END $$; CREATE TRIGGER server_probe_storage_payload_guard BEFORE INSERT OR UPDATE OR DELETE ON server_probe_execution_payloads FOR EACH ROW EXECUTE FUNCTION server_probe_storage_payload_guard(); -- Preserve every original INSERT/UPDATE rule; only the already-validated -- lifetime predicate can admit DELETE; no cleanup is scheduled by migration. CREATE OR REPLACE FUNCTION server_probe_stage_immutable() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF TG_OP='DELETE' THEN IF server_probe_storage_gc_allowed(OLD.receipt_id) THEN RETURN OLD; END IF; RAISE EXCEPTION 'probe stage lifetime has not elapsed'; END IF; PERFORM receipt_id FROM server_probe_executions WHERE receipt_id=NEW.receipt_id AND state='claimed' FOR UPDATE; IF NOT FOUND OR EXISTS(SELECT 1 FROM server_probe_execution_quarantines WHERE receipt_id=NEW.receipt_id) THEN RAISE EXCEPTION 'probe attempt is not executable'; END IF; IF TG_OP='INSERT' AND (NEW.stage_index<>(SELECT COALESCE(max(stage_index),0)+1 FROM server_probe_execution_stages WHERE receipt_id=NEW.receipt_id) OR EXISTS(SELECT 1 FROM server_probe_execution_stages WHERE receipt_id=NEW.receipt_id AND state<>'received')) THEN RAISE EXCEPTION 'probe stages must be serial and contiguous'; END IF; IF TG_OP='UPDATE' AND (OLD.state<>'intent' OR NEW.state<>'received' OR (to_jsonb(OLD)-ARRAY['state','outcome','received_at']) IS DISTINCT FROM (to_jsonb(NEW)-ARRAY['state','outcome','received_at'])) THEN RAISE EXCEPTION 'probe stage terminal state is immutable'; END IF; RETURN NEW; END $$; CREATE OR REPLACE FUNCTION server_probe_quarantine_immutable() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF TG_OP='DELETE' AND server_probe_storage_gc_allowed(OLD.receipt_id) THEN RETURN OLD; END IF; RAISE EXCEPTION 'probe quarantine remains immutable'; END $$; CREATE OR REPLACE FUNCTION mcp_diagnostic_cancellation_immutable() RETURNS trigger LANGUAGE plpgsql AS $$ DECLARE original_receipt uuid; BEGIN IF TG_OP='DELETE' THEN SELECT a.receipt_id INTO original_receipt FROM server_probe_storage_admissions a JOIN mcp_operations o ON o.id=a.execution_id AND o.connection_id=OLD.connection_id WHERE a.identity_kind='mcp' AND a.execution_id=OLD.operation_id AND a.owner_id=OLD.actor_id; IF FOUND AND server_probe_storage_gc_allowed(original_receipt) THEN RETURN OLD; END IF; END IF; RAISE EXCEPTION 'diagnostic cancellation lifetime has not elapsed'; END $$; INSERT INTO schema_migrations(id) VALUES ('0037_server_probe_storage_v2') ON CONFLICT (id) DO NOTHING; COMMIT;