Files

92 lines
4.8 KiB
PL/PgSQL
Raw Permalink Normal View History

2026-08-26 06:41:07 +08:00
BEGIN;
ALTER TABLE subject_profile
DROP CONSTRAINT IF EXISTS subject_profile_status_check;
UPDATE subject_profile SET status='suspended' WHERE status='inactive';
ALTER TABLE subject_profile
ADD COLUMN language varchar(32) NOT NULL DEFAULT 'zh-CN',
ADD COLUMN timezone varchar(64) NOT NULL DEFAULT 'Asia/Shanghai',
ADD COLUMN profile_data jsonb NOT NULL DEFAULT '{}'::jsonb,
ADD COLUMN conversation_preferences jsonb NOT NULL DEFAULT '{}'::jsonb,
ADD COLUMN created_by uuid,
ADD COLUMN updated_by uuid,
ADD CONSTRAINT subject_profile_status_check
CHECK (status IN ('active', 'suspended', 'deleting', 'deleted')),
ADD CONSTRAINT subject_profile_created_by_tenant_fk
FOREIGN KEY (created_by, tenant_id) REFERENCES user_account (id, tenant_id),
ADD CONSTRAINT subject_profile_updated_by_tenant_fk
FOREIGN KEY (updated_by, tenant_id) REFERENCES user_account (id, tenant_id);
CREATE TABLE subject_fact (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
public_id uuid NOT NULL UNIQUE DEFAULT gen_random_uuid(),
tenant_id uuid NOT NULL REFERENCES tenant(id),
subject_id uuid NOT NULL,
fact_type varchar(64) NOT NULL,
content text NOT NULL,
source_type varchar(40) NOT NULL
CHECK (source_type IN ('subject_statement', 'family_entry', 'model_candidate', 'imported')),
source_ref varchar(300),
confirmation_status varchar(32) NOT NULL DEFAULT 'pending'
CHECK (confirmation_status IN ('pending', 'confirmed', 'rejected', 'superseded')),
sensitivity varchar(24) NOT NULL DEFAULT 'normal'
CHECK (sensitivity IN ('normal', 'sensitive', 'high')),
valid_from timestamptz,
valid_to timestamptz,
version bigint NOT NULL DEFAULT 1 CHECK (version > 0),
created_by uuid NOT NULL,
updated_by uuid NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT subject_fact_subject_tenant_fk
FOREIGN KEY (subject_id, tenant_id) REFERENCES subject_profile (id, tenant_id),
CONSTRAINT subject_fact_created_by_tenant_fk
FOREIGN KEY (created_by, tenant_id) REFERENCES user_account (id, tenant_id),
CONSTRAINT subject_fact_updated_by_tenant_fk
FOREIGN KEY (updated_by, tenant_id) REFERENCES user_account (id, tenant_id),
CONSTRAINT subject_fact_valid_range CHECK (valid_to IS NULL OR valid_from IS NULL OR valid_to >= valid_from),
CONSTRAINT subject_fact_id_tenant_key UNIQUE (id, tenant_id)
);
CREATE INDEX subject_fact_subject_status_idx
ON subject_fact (tenant_id, subject_id, confirmation_status, updated_at DESC);
CREATE TABLE consent_record (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
public_id uuid NOT NULL UNIQUE DEFAULT gen_random_uuid(),
tenant_id uuid NOT NULL REFERENCES tenant(id),
subject_id uuid NOT NULL,
consent_type varchar(64) NOT NULL
CHECK (consent_type IN (
'transcript_storage', 'raw_audio_storage', 'story_extraction',
'personalized_memory', 'family_sharing'
)),
scope jsonb NOT NULL DEFAULT '{}'::jsonb,
policy_version varchar(64) NOT NULL,
notice_digest varchar(128) NOT NULL,
actor_user_id uuid NOT NULL,
evidence_ref varchar(300),
granted_at timestamptz NOT NULL DEFAULT now(),
expires_at timestamptz,
withdrawn_at timestamptz,
version bigint NOT NULL DEFAULT 1 CHECK (version > 0),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT consent_record_subject_tenant_fk
FOREIGN KEY (subject_id, tenant_id) REFERENCES subject_profile (id, tenant_id),
CONSTRAINT consent_record_actor_tenant_fk
FOREIGN KEY (actor_user_id, tenant_id) REFERENCES user_account (id, tenant_id),
CONSTRAINT consent_record_expiry_check CHECK (expires_at IS NULL OR expires_at > granted_at),
CONSTRAINT consent_record_withdrawal_check CHECK (withdrawn_at IS NULL OR withdrawn_at >= granted_at),
CONSTRAINT consent_record_id_tenant_key UNIQUE (id, tenant_id)
);
CREATE INDEX consent_record_subject_type_time_idx
ON consent_record (tenant_id, subject_id, consent_type, granted_at DESC, id DESC);
-- “同一类型最多一条当前有效授权”包含对当前时间的判断,不能由使用
-- now() 的部分唯一索引表达。授予服务必须在锁定 subject_profile 后,于同一
-- 事务中检查 withdrawn_at / expires_at 并追加新记录。
COMMIT;