-- 元数据只保存结构模具与绑定,不保存任何业务实例值。 CREATE SCHEMA metadata AUTHORIZATION muse_maint; GRANT USAGE ON SCHEMA metadata TO muse_app, muse_eval; CREATE TABLE metadata.type_registry ( type_id text PRIMARY KEY, definition jsonb NOT NULL, content_hash text NOT NULL, state text NOT NULL DEFAULT 'candidate' CHECK (state IN ('candidate', 'published')), policy_revision bigint NOT NULL DEFAULT 0 CHECK (policy_revision >= 0) ); CREATE TABLE metadata.schema_version ( schema_id text NOT NULL, schema_version bigint NOT NULL CHECK (schema_version > 0), type_id text NOT NULL REFERENCES metadata.type_registry(type_id), definition jsonb NOT NULL, content_hash text NOT NULL, state text NOT NULL CHECK (state IN ('candidate', 'published')), PRIMARY KEY (schema_id, schema_version) ); CREATE TABLE metadata.work_extension ( work_id text NOT NULL, schema_id text NOT NULL, base_version bigint NOT NULL, extension_version bigint NOT NULL CHECK (extension_version > 0), definition jsonb NOT NULL, content_hash text NOT NULL, state text NOT NULL CHECK (state IN ('candidate', 'published')), PRIMARY KEY (work_id, schema_id, base_version, extension_version), FOREIGN KEY (schema_id, base_version) REFERENCES metadata.schema_version(schema_id, schema_version) ); CREATE TABLE metadata.policy_version ( type_id text NOT NULL REFERENCES metadata.type_registry(type_id), version bigint NOT NULL CHECK (version > 0), definition jsonb NOT NULL, content_hash text NOT NULL, PRIMARY KEY (type_id, version) ); CREATE TABLE metadata.schema_binding ( target_ref text PRIMARY KEY, work_id text NOT NULL, type_id text NOT NULL REFERENCES metadata.type_registry(type_id), schema_id text NOT NULL, base_version bigint NOT NULL, extension_version bigint, effective_schema_hash text NOT NULL, revision bigint NOT NULL CHECK (revision > 0), FOREIGN KEY (schema_id, base_version) REFERENCES metadata.schema_version(schema_id, schema_version), FOREIGN KEY (work_id, schema_id, base_version, extension_version) REFERENCES metadata.work_extension(work_id, schema_id, base_version, extension_version) ); CREATE TABLE metadata.activation_receipt ( command_id text PRIMARY KEY, request_hash text NOT NULL, result jsonb NOT NULL, reviewed_by text NOT NULL, change_scope text NOT NULL, created_at timestamptz NOT NULL DEFAULT current_timestamp ); -- 候选修改也必须产生新版本;发布只允许改变状态,正文定义永远不可原地覆盖。 CREATE FUNCTION metadata.immutable_definition() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF TG_OP = 'DELETE' THEN RAISE EXCEPTION '元数据历史版本不可删除'; END IF; IF NEW.definition IS DISTINCT FROM OLD.definition OR NEW.content_hash IS DISTINCT FROM OLD.content_hash THEN RAISE EXCEPTION '元数据定义不可修改,必须新增版本'; END IF; RETURN NEW; END; $$; CREATE TRIGGER schema_immutable BEFORE UPDATE OR DELETE ON metadata.schema_version FOR EACH ROW EXECUTE FUNCTION metadata.immutable_definition(); CREATE TRIGGER extension_immutable BEFORE UPDATE OR DELETE ON metadata.work_extension FOR EACH ROW EXECUTE FUNCTION metadata.immutable_definition(); CREATE TRIGGER policy_immutable BEFORE UPDATE OR DELETE ON metadata.policy_version FOR EACH ROW EXECUTE FUNCTION metadata.immutable_definition(); GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA metadata TO muse_app; GRANT SELECT ON ALL TABLES IN SCHEMA metadata TO muse_eval;