-- raw 元数据与全文两表:example_raw_lease(租约/元数据)+ example_raw_content(全文,访问控制)。 -- 设计拍板 2026-07-30(docs/2026-07-30-落库与看板设计.md §2.7 + §4 raw 合同改写)。 -- raw 合同已改写(创始人批准):放弃时效语义,改靠**访问控制 + append-only**—— -- 完整 prompt/response/未接受候选/标准答案/原书全文/供应商响应进库可看全文(看板可读), -- 仓外 vault 降级为可选备份;retain_until 只留档、不触发自动删除;密钥/token 绝不入表。 -- 两表都 append-only(禁 UPDATE/DELETE/TRUNCATE)——raw 是不可变证据。 -- 全部对象 IF NOT EXISTS / OR REPLACE,重复 apply 幂等。 -- ══ example_raw_lease:raw 租约/元数据(append-only)══ CREATE TABLE IF NOT EXISTS example_raw_lease ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, vault_id CHAR(32), -- vault 标识(兼容旧 raw_vault 的 vaultId) run_id VARCHAR(64), -- → example_run.run_id(软引用) source_version VARCHAR(128), -- 来源版本 content_hashes JSONB, -- 本租约下内容哈希清单 purpose VARCHAR(64), -- 用途(generation/evaluation/…) status VARCHAR(20) NOT NULL DEFAULT 'open', -- open/migrated/closed(历史状态,不再是删期限闸门) retain_until TIMESTAMP, -- 批准的留存期限(留档溯源;进库后不触发自动删除) archive_id VARCHAR(64), -- 仓外备份标识(若仍做可选备份) archive_sha256 CHAR(64), file_count INTEGER, total_bytes BIGINT, run_authorization_id VARCHAR(128), -- 本次运行授权标识(运行时对象,不查库、不指 96) source_work_id BIGINT, -- raw 来源参考书 → example_reference_work.id(出处溯源) creator VARCHAR(64) NOT NULL DEFAULT '', create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, tenant_id BIGINT NOT NULL DEFAULT 0, CONSTRAINT chk_example_raw_lease_status CHECK (status IN ('open','migrated','closed')) ); CREATE INDEX IF NOT EXISTS idx_example_raw_lease_run ON example_raw_lease(run_id) WHERE run_id IS NOT NULL; CREATE INDEX IF NOT EXISTS idx_example_raw_lease_work ON example_raw_lease(source_work_id) WHERE source_work_id IS NOT NULL; -- ══ example_raw_content:raw 全文(append-only,访问控制)══ -- 访问控制:默认不进普通检索,看全文须显式指定;看板可看全文;密钥/token/凭据列级 + 写入前过滤双禁。 CREATE TABLE IF NOT EXISTS example_raw_content ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, lease_id BIGINT, -- → example_raw_lease.id(软引用,可空) kind VARCHAR(32) NOT NULL, -- prompt/response/source_text/oracle/supplier(无 candidate——候选正文单存候选表) run_id VARCHAR(64), -- → example_run.run_id(软引用) role VARCHAR(32), -- 产生角色(writer/detector/judge/…) content_sha256 CHAR(64) NOT NULL, -- 内容哈希(裸 64 hex) content TEXT NOT NULL, -- 全文 creator VARCHAR(64) NOT NULL DEFAULT '', create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, tenant_id BIGINT NOT NULL DEFAULT 0, CONSTRAINT chk_example_raw_content_kind CHECK (kind IN ('prompt','response','source_text','oracle','supplier')), CONSTRAINT chk_example_raw_content_sha256 CHECK (content_sha256 ~ '^[0-9a-f]{64}$') ); -- 唯一键 (lease_id, content_sha256):同一租约内重试幂等去重;跨租约各留一行(授权归属不串) CREATE UNIQUE INDEX IF NOT EXISTS uk_example_raw_content ON example_raw_content(lease_id, content_sha256); CREATE INDEX IF NOT EXISTS idx_example_raw_content_run ON example_raw_content(run_id) WHERE run_id IS NOT NULL; -- append-only + TRUNCATE 防护(raw 是不可变证据) CREATE OR REPLACE FUNCTION example_reject_truncate() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION '% 是 append-only 表,禁止 TRUNCATE', TG_TABLE_NAME; END; $$; CREATE OR REPLACE FUNCTION reject_example_raw_lease_mutation() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'example_raw_lease 是 append-only 表,禁止 UPDATE/DELETE'; END; $$; CREATE OR REPLACE TRIGGER trg_example_raw_lease_append_only BEFORE UPDATE OR DELETE ON example_raw_lease FOR EACH ROW EXECUTE FUNCTION reject_example_raw_lease_mutation(); CREATE OR REPLACE TRIGGER trg_example_raw_lease_no_truncate BEFORE TRUNCATE ON example_raw_lease FOR EACH STATEMENT EXECUTE FUNCTION example_reject_truncate(); CREATE OR REPLACE FUNCTION reject_example_raw_content_mutation() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'example_raw_content 是 append-only 表,禁止 UPDATE/DELETE'; END; $$; CREATE OR REPLACE TRIGGER trg_example_raw_content_append_only BEFORE UPDATE OR DELETE ON example_raw_content FOR EACH ROW EXECUTE FUNCTION reject_example_raw_content_mutation(); CREATE OR REPLACE TRIGGER trg_example_raw_content_no_truncate BEFORE TRUNCATE ON example_raw_content FOR EACH STATEMENT EXECUTE FUNCTION example_reject_truncate();