- DDL 103:run_type 插入后不可变触发器(评测性锚点钉死);生产只读角色 muse_read + RLS(评测候选对生产读默认不可见,app.eval_visible opt-in 才可见);已验证 root可见/muse_read不可见/opt-in可见 - invariant_checks.py:常设不变量(从靠预防迁到靠发现)——I1评测候选未接受/I2正文来源不追溯评测候选/I3评测质量结果可过滤/I4 oracle红线/I5 COMPLETED轮次封存(声明==实际落库),已跑通全PASS - 原则1/2(口号升级/代价明账)已落 SoT;原则3/4/5/6 实现层完成
49 lines
2.3 KiB
PL/PgSQL
49 lines
2.3 KiB
PL/PgSQL
-- 评测隔离引擎强制(harness 改造原则 4:强制收拢到引擎单点 + run_type 钉死)。
|
||
-- 设计拍板 2026-08-01(docs/2026-08-01-评测harness改造设计.md 原则 4/6)。
|
||
-- 核心:评测与生产同库,靠逻辑隔离(访问分离);强制必须压到引擎单点,不靠每条查询自觉过滤。
|
||
-- 1) run_type 插入后不可变——评测性这个锚点钉死,不能先改成 production 再接受。
|
||
-- 2) (eval, accepted) 永不可达——既有 trg_example_candidate_no_eval_accept 已守;run_type 不可变后更硬。
|
||
-- 3) 生产只读角色 muse_read + RLS——评测行对生产读默认不可见,显式 opt-in(app.eval_visible)才可见。
|
||
-- 注意:root 是 superuser,RLS 对其无效;muse_read 是非超级用户角色,RLS 对它生效。
|
||
-- 生产读路径应改用 muse_read 连接(切换为后续代码改动),admin/看板用 root 可见全部(含评测,带标记)。
|
||
|
||
-- ── 1) run_type 插入后不可变 ──
|
||
CREATE OR REPLACE FUNCTION reject_run_type_change()
|
||
RETURNS TRIGGER
|
||
LANGUAGE plpgsql
|
||
AS $$
|
||
BEGIN
|
||
IF NEW.run_type IS DISTINCT FROM OLD.run_type THEN
|
||
RAISE EXCEPTION 'run_type 插入后不可变(评测隔离引擎强制,原 % 新 %)', OLD.run_type, NEW.run_type;
|
||
END IF;
|
||
RETURN NEW;
|
||
END;
|
||
$$;
|
||
|
||
CREATE OR REPLACE TRIGGER trg_example_candidate_run_type_immutable
|
||
BEFORE UPDATE ON example_candidate
|
||
FOR EACH ROW EXECUTE FUNCTION reject_run_type_change();
|
||
|
||
-- ── 2) 生产只读角色 muse_read(非超级用户,RLS 对其生效)──
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'muse_read') THEN
|
||
CREATE ROLE muse_read NOLOGIN;
|
||
END IF;
|
||
END
|
||
$$;
|
||
|
||
GRANT SELECT ON example_candidate TO muse_read;
|
||
GRANT SELECT ON example_run TO muse_read;
|
||
GRANT SELECT ON example_run_receipt TO muse_read;
|
||
GRANT SELECT ON example_quality_result TO muse_read;
|
||
|
||
-- ── 3) RLS:评测候选对生产读默认不可见,显式 opt-in(app.eval_visible='true')才可见 ──
|
||
ALTER TABLE example_candidate ENABLE ROW LEVEL SECURITY;
|
||
ALTER TABLE example_candidate FORCE ROW LEVEL SECURITY;
|
||
|
||
DROP POLICY IF EXISTS eval_isolation_candidate ON example_candidate;
|
||
CREATE POLICY eval_isolation_candidate ON example_candidate
|
||
FOR SELECT
|
||
USING (run_type IS DISTINCT FROM 'eval' OR current_setting('app.eval_visible', true) = 'true');
|