接续 88dd570,保存 W20–W24 已实现的共享接口、业务入口、迁移、工作台、测试与文档。 W20/W22/W23 保持 in_progress,W21/W24 保持 verified;此提交不宣称方法或规则正式启用、多轮返修、真实角色评测完成。 W25 新增实验、标定、逐调用交付与角色执行及其迁移/测试/索引留在实施工作树,原有私人和旧实现保留项不纳入。 验证:离线 571、前端 33 通过;PG 469 项通过、2 项浏览器未启用,2 项误带入的 W25 用例已移出本提交;最终任务与交付边界 37 项通过。make 检查、最终类型、84 项资源及 diff 检查通过。未重跑浏览器或 Pi 宿主,不以合成调用认证外部模型效果。 独立整体审查四维通过;证据保存在 R2-20260909/提交W20-W24。
71 lines
3.3 KiB
PL/PgSQL
71 lines
3.3 KiB
PL/PgSQL
-- 数据演进:隔离目标身份与迁移来源/回执;不代替任何业务域的实体或候选表。
|
|
CREATE TABLE public.muse_legacy_target (
|
|
singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
|
|
target_id uuid NOT NULL UNIQUE,
|
|
system_identifier text NOT NULL,
|
|
data_directory text NOT NULL,
|
|
host text NOT NULL,
|
|
port integer NOT NULL CHECK (port BETWEEN 1 AND 65535),
|
|
database_name text NOT NULL,
|
|
database_oid oid NOT NULL,
|
|
role_name text NOT NULL CHECK (role_name='muse_app'),
|
|
run_purpose public.muse_purpose NOT NULL CHECK (run_purpose='production'),
|
|
created_at timestamptz NOT NULL DEFAULT clock_timestamp()
|
|
);
|
|
-- 应用角色不能把任意已有库自行标为隔离目标。
|
|
REVOKE ALL ON public.muse_legacy_target FROM muse_app, muse_eval;
|
|
GRANT SELECT ON public.muse_legacy_target TO muse_app;
|
|
|
|
CREATE TABLE public.muse_legacy_import_record (
|
|
author_id text NOT NULL,
|
|
run_purpose public.muse_purpose NOT NULL CHECK (run_purpose='production'),
|
|
source_key text NOT NULL CHECK (length(source_key)>0),
|
|
source_hash text NOT NULL CHECK (source_hash ~ '^[0-9a-f]{64}$'),
|
|
mapping_hash text NOT NULL CHECK (mapping_hash ~ '^[0-9a-f]{64}$'),
|
|
original jsonb NOT NULL CHECK (jsonb_typeof(original)='object'),
|
|
command_id text NOT NULL,
|
|
route jsonb NOT NULL CHECK (jsonb_typeof(route)='object'),
|
|
frozen_request jsonb,
|
|
state text NOT NULL DEFAULT 'reserved'
|
|
CHECK (state IN ('reserved','mapped','historical','quarantined')),
|
|
reason_code text NOT NULL DEFAULT '',
|
|
targets jsonb NOT NULL DEFAULT '[]'::jsonb CHECK (jsonb_typeof(targets)='array'),
|
|
receipt jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
|
updated_at timestamptz NOT NULL DEFAULT clock_timestamp(),
|
|
PRIMARY KEY (author_id, source_key),
|
|
UNIQUE (author_id, command_id),
|
|
CHECK (state <> 'mapped' OR
|
|
(frozen_request IS NOT NULL AND receipt IS NOT NULL AND jsonb_array_length(targets)>0)),
|
|
CHECK (state = 'mapped' OR (receipt IS NULL AND targets='[]'::jsonb))
|
|
);
|
|
|
|
REVOKE DELETE ON public.muse_legacy_import_record FROM muse_app;
|
|
|
|
CREATE FUNCTION public.muse_guard_legacy_import_record() RETURNS trigger
|
|
LANGUAGE plpgsql AS $$
|
|
BEGIN
|
|
IF (NEW.author_id, NEW.run_purpose, NEW.source_key, NEW.source_hash,
|
|
NEW.mapping_hash, NEW.original, NEW.command_id, NEW.route)
|
|
IS DISTINCT FROM
|
|
(OLD.author_id, OLD.run_purpose, OLD.source_key, OLD.source_hash,
|
|
OLD.mapping_hash, OLD.original, OLD.command_id, OLD.route) THEN
|
|
RAISE EXCEPTION '迁移来源、映射与命令身份不可改写';
|
|
END IF;
|
|
IF OLD.frozen_request IS NOT NULL AND NEW.frozen_request IS DISTINCT FROM OLD.frozen_request THEN
|
|
RAISE EXCEPTION '迁移目标请求已经冻结';
|
|
END IF;
|
|
IF OLD.state <> 'reserved' AND
|
|
(NEW.state, NEW.reason_code, NEW.targets, NEW.receipt, NEW.frozen_request)
|
|
IS DISTINCT FROM
|
|
(OLD.state, OLD.reason_code, OLD.targets, OLD.receipt, OLD.frozen_request) THEN
|
|
RAISE EXCEPTION '迁移终态及回执不可改写';
|
|
END IF;
|
|
NEW.updated_at := clock_timestamp();
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
CREATE TRIGGER muse_legacy_import_record_guard
|
|
BEFORE UPDATE ON public.muse_legacy_import_record
|
|
FOR EACH ROW EXECUTE FUNCTION public.muse_guard_legacy_import_record();
|