Health checks reuse a two-second snapshot and bound the schema query. Task SSE writes an error frame when an event cannot be encoded. ResolveDocTask errors when the frozen plan has no duty row, while explicit none-duties stay zero. Drop the unwired semantic-summary replace env, record the intentional dev versus release model split, document the test/main cutover path, and archive pre-goose SQL. Co-authored-by: Cursor <cursoragent@cursor.com>
52 lines
2.2 KiB
SQL
52 lines
2.2 KiB
SQL
-- =============================================================================
|
|
-- Migration: 2026-09-11-message-export-policy.sql
|
|
-- Description: 为 chat_messages 新增正文类型、权威导出策略、版本与 SHA256 哈希
|
|
-- =============================================================================
|
|
|
|
-- 1. 结构变更:新增消息导出权威列
|
|
ALTER TABLE chat_messages
|
|
ADD COLUMN IF NOT EXISTS content_kind TEXT NOT NULL DEFAULT '',
|
|
ADD COLUMN IF NOT EXISTS export_policy TEXT NOT NULL DEFAULT 'none',
|
|
ADD COLUMN IF NOT EXISTS content_revision INT NOT NULL DEFAULT 1,
|
|
ADD COLUMN IF NOT EXISTS content_sha256 TEXT NOT NULL DEFAULT '';
|
|
|
|
-- 2. 导出策略枚举约束检查 (full | copy_only | none)
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM pg_constraint WHERE conname = 'chk_chat_export_policy'
|
|
) THEN
|
|
ALTER TABLE chat_messages
|
|
ADD CONSTRAINT chk_chat_export_policy
|
|
CHECK (export_policy IN ('full', 'copy_only', 'none'));
|
|
END IF;
|
|
END $$;
|
|
|
|
-- 3. 索引优化:快速基于消息与版本校验
|
|
CREATE INDEX IF NOT EXISTS idx_chat_messages_export_policy
|
|
ON chat_messages(id, export_policy);
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
-- 4. 存量消息安全保守回填:旧消息默认为 none,仅纯文本 assistant 消息标记为 copy_only
|
|
UPDATE chat_messages
|
|
SET
|
|
content_kind = CASE
|
|
WHEN role = 'user' THEN 'conversational_text'
|
|
WHEN role = 'system' THEN 'system_notice'
|
|
WHEN role = 'assistant' AND (metadata ? 'interactive_card') THEN 'action_card'
|
|
WHEN role = 'assistant' AND length(trim(content)) > 0 THEN 'document_text'
|
|
ELSE 'conversational_text'
|
|
END,
|
|
export_policy = CASE
|
|
WHEN role = 'assistant' AND NOT (metadata ? 'interactive_card') AND length(trim(content)) >= 10 THEN 'full'
|
|
WHEN role = 'assistant' AND length(trim(content)) > 0 THEN 'copy_only'
|
|
ELSE 'none'
|
|
END,
|
|
content_revision = 1,
|
|
content_sha256 = CASE
|
|
WHEN length(content) > 0 THEN encode(sha256(convert_to(content, 'UTF8')), 'hex')
|
|
ELSE ''
|
|
END
|
|
WHERE export_policy = 'none' AND role = 'assistant' AND length(trim(content)) > 0;
|