feat(mcp): run governed version lifecycle receipts
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
-- Durable external MCP version lifecycle receipts.
|
||||
--
|
||||
-- Safety contract:
|
||||
-- * catalog metadata only; no package install, tool call, credential, raw page,
|
||||
-- request body, response body, or RAG content is stored;
|
||||
-- * additive schema only, so application rollback does not delete evidence;
|
||||
-- * every observation is bound to one run_id / trace_id / work_item_id;
|
||||
-- * tenant RLS remains fail-closed through app.project_id.
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS awooop_mcp_version_lifecycle_run (
|
||||
run_id UUID PRIMARY KEY,
|
||||
trace_id VARCHAR(128) NOT NULL,
|
||||
work_item_id VARCHAR(128) NOT NULL,
|
||||
project_id VARCHAR(64) NOT NULL
|
||||
REFERENCES awooop_projects(project_id) ON DELETE RESTRICT,
|
||||
trigger_kind VARCHAR(32) NOT NULL,
|
||||
status VARCHAR(48) NOT NULL,
|
||||
candidate_count INTEGER NOT NULL DEFAULT 0,
|
||||
observed_count INTEGER NOT NULL DEFAULT 0,
|
||||
baseline_count INTEGER NOT NULL DEFAULT 0,
|
||||
changed_count INTEGER NOT NULL DEFAULT 0,
|
||||
policy_blocked_count INTEGER NOT NULL DEFAULT 0,
|
||||
error_count INTEGER NOT NULL DEFAULT 0,
|
||||
receipt JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
ended_at TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT uix_mcp_version_lifecycle_trace
|
||||
UNIQUE (project_id, trace_id),
|
||||
CONSTRAINT chk_mcp_version_lifecycle_trigger
|
||||
CHECK (trigger_kind IN ('startup','scheduled','operator_replay','test')),
|
||||
CONSTRAINT chk_mcp_version_lifecycle_status
|
||||
CHECK (status IN (
|
||||
'running',
|
||||
'completed_no_change',
|
||||
'completed_no_write_policy_blocked',
|
||||
'partial_degraded',
|
||||
'failed'
|
||||
)),
|
||||
CONSTRAINT chk_mcp_version_lifecycle_counts
|
||||
CHECK (
|
||||
candidate_count >= 0 AND observed_count >= 0 AND baseline_count >= 0
|
||||
AND changed_count >= 0 AND policy_blocked_count >= 0
|
||||
AND error_count >= 0
|
||||
),
|
||||
CONSTRAINT chk_mcp_version_lifecycle_terminal_time
|
||||
CHECK (
|
||||
(status = 'running' AND ended_at IS NULL)
|
||||
OR (status <> 'running' AND ended_at IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS awooop_mcp_version_observation (
|
||||
observation_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
run_id UUID NOT NULL
|
||||
REFERENCES awooop_mcp_version_lifecycle_run(run_id) ON DELETE RESTRICT,
|
||||
trace_id VARCHAR(128) NOT NULL,
|
||||
work_item_id VARCHAR(128) NOT NULL,
|
||||
project_id VARCHAR(64) NOT NULL
|
||||
REFERENCES awooop_projects(project_id) ON DELETE RESTRICT,
|
||||
candidate_id VARCHAR(160) NOT NULL,
|
||||
catalog_source VARCHAR(32) NOT NULL,
|
||||
source_url TEXT NOT NULL,
|
||||
source_url_sha256 VARCHAR(64) NOT NULL,
|
||||
http_status INTEGER,
|
||||
content_sha256 VARCHAR(64),
|
||||
observed_version VARCHAR(128),
|
||||
previous_version VARCHAR(128),
|
||||
discovery_status VARCHAR(32) NOT NULL,
|
||||
change_state VARCHAR(32) NOT NULL,
|
||||
lifecycle_terminal VARCHAR(48) NOT NULL,
|
||||
policy_decision JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
stage_receipts JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
error_class VARCHAR(128),
|
||||
observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT uix_mcp_version_observation_run_candidate
|
||||
UNIQUE (run_id, candidate_id),
|
||||
CONSTRAINT chk_mcp_version_catalog_source
|
||||
CHECK (catalog_source IN ('smithery','mcp-so')),
|
||||
CONSTRAINT chk_mcp_version_source_url_hash
|
||||
CHECK (source_url_sha256 ~ '^[0-9a-f]{64}$'),
|
||||
CONSTRAINT chk_mcp_version_content_hash
|
||||
CHECK (content_sha256 IS NULL OR content_sha256 ~ '^[0-9a-f]{64}$'),
|
||||
CONSTRAINT chk_mcp_version_discovery_status
|
||||
CHECK (discovery_status IN ('observed','source_error','policy_blocked')),
|
||||
CONSTRAINT chk_mcp_version_change_state
|
||||
CHECK (change_state IN (
|
||||
'baseline_created','no_change','version_changed',
|
||||
'content_changed','source_unavailable'
|
||||
)),
|
||||
CONSTRAINT chk_mcp_version_terminal
|
||||
CHECK (lifecycle_terminal IN (
|
||||
'no_write_baseline','no_write_no_change','no_write_policy_blocked',
|
||||
'no_write_source_error','replay_passed_canary_pending',
|
||||
'promoted','rolled_back'
|
||||
))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_mcp_version_lifecycle_recent
|
||||
ON awooop_mcp_version_lifecycle_run (project_id, started_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_mcp_version_observation_candidate_recent
|
||||
ON awooop_mcp_version_observation
|
||||
(project_id, candidate_id, observed_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_mcp_version_observation_run
|
||||
ON awooop_mcp_version_observation (project_id, run_id, observed_at);
|
||||
|
||||
ALTER TABLE awooop_mcp_version_lifecycle_run ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE awooop_mcp_version_lifecycle_run FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE awooop_mcp_version_observation ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE awooop_mcp_version_observation FORCE ROW LEVEL SECURITY;
|
||||
|
||||
DROP POLICY IF EXISTS mcp_version_lifecycle_run_tenant
|
||||
ON awooop_mcp_version_lifecycle_run;
|
||||
CREATE POLICY mcp_version_lifecycle_run_tenant
|
||||
ON awooop_mcp_version_lifecycle_run
|
||||
USING (project_id = current_setting('app.project_id', TRUE))
|
||||
WITH CHECK (project_id = current_setting('app.project_id', TRUE));
|
||||
|
||||
DROP POLICY IF EXISTS mcp_version_observation_tenant
|
||||
ON awooop_mcp_version_observation;
|
||||
CREATE POLICY mcp_version_observation_tenant
|
||||
ON awooop_mcp_version_observation
|
||||
USING (project_id = current_setting('app.project_id', TRUE))
|
||||
WITH CHECK (project_id = current_setting('app.project_id', TRUE));
|
||||
|
||||
GRANT SELECT, INSERT, UPDATE ON awooop_mcp_version_lifecycle_run TO awooop_app;
|
||||
GRANT SELECT, INSERT ON awooop_mcp_version_observation TO awooop_app;
|
||||
GRANT SELECT, INSERT, UPDATE ON awooop_mcp_version_lifecycle_run TO awoooi;
|
||||
GRANT SELECT, INSERT ON awooop_mcp_version_observation TO awoooi;
|
||||
|
||||
COMMENT ON TABLE awooop_mcp_version_lifecycle_run IS
|
||||
'Durable controlled-apply lifecycle run receipts; additive and rollback-safe.';
|
||||
COMMENT ON TABLE awooop_mcp_version_observation IS
|
||||
'Normalized external MCP catalog observations; raw external content is forbidden.';
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user