oh-my-muse/muse-cloud/sql/muse/V36__ai_generated_fulltext_transient.sql
lili fcd0623a18 feat(ai): S7b 瞬态全文载体 + SSE chunk 送达 + 决定即清
分支①第二步:新增独立瞬态加密表 muse_ai_generated_fulltext(V36:fulltext_content 经
EncryptTypeHandler AES 加密、expires_at TTL 30min、content_hash/length 供脱敏、决定即删),
仿 MuseAiRuntimePayloadStore 范式建 Store(write/read/purge/cleanupExpired)。执行器拿到成功
RuntimeResult 后把 fullOutput 写瞬态 Store(不在终态 finally purge——出向正文须存活到用户决定);
投影在 done 之前发一条非终态 chunk 引用行(payload 只含 {contentRef:taskId,sequenceNo},绝不带
正文,不落 outbox、不受终态唯一索引);SSE chunkData 遇 contentRef 回瞬态 Store 取正文填 content,
缺失(purge/过期)→空串,兼容旧内联行。采纳(merge facade)/放弃(reject 两路)即 purge。

主权红线(四重亲验):完整正文只存于执行线程内存/瞬态加密表/SSE 传输/客户端,永不进 chunk payload
(只放 ref)、永不进 muse_ai_suggestion/muse_content_block 任何长期列;content_snapshot.content 仍
写脱敏摘要(S7a 口径未动);DO toString 排除正文、Store 日志只算 sha256/length。

验证:ai 模块 528 用例全绿(新增 Store 6 + 投影/流/建议/合并各扩展),BUILD SUCCESS(-am 防 stale)。
真 PG 一次真生成端到端(chunk 携全文/决定后 purge/重连回取)并入 M1 harness,本步未造新 live IT(避
内容过滤器)。DDL:V35 由 S6 占,本表 V36,当前 V34→V36 临时空号,S6 落 V35 填平(Flyway 允许)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 00:29:29 -07:00

35 lines
1.9 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- S7b 瞬态出向完整正文载体。
-- 该表只承载「本次 AI 生成的完整正文」出向 SSE 送达 + 断线重连的临时载荷fulltext_content 经 MyBatis
-- EncryptTypeHandler 加密写入TTL 到期或用户决定(采纳/放弃即物理删除audit / suggestion / content_block 一律
-- 只保存 length/hash 或脱敏摘要,不读取、不投影本表正文。
--
-- 主权红线:这是瞬态出向载体,非系统记录,永不作为正文来源落 Canonicalmuse_content_block或候选表
-- muse_ai_suggestion任何长期列完整正文只允许存在于「执行线程内存 / 本瞬态加密表TTL+决定即清)/ SSE 传输 / 客户端」。
-- 版本协调:当前最大 V34S6 的 runtime_batch_id 迁移预留 V35本瞬态表取 V36勿撞号
CREATE TABLE muse_ai_generated_fulltext (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
task_id BIGINT NOT NULL,
fulltext_content TEXT NOT NULL,
content_length INT NOT NULL,
content_hash CHAR(64) NOT NULL,
expires_at TIMESTAMP NOT NULL,
creator VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
tenant_id BIGINT NOT NULL DEFAULT 0,
CONSTRAINT uk_muse_ai_generated_fulltext_task UNIQUE (tenant_id, task_id)
);
CREATE INDEX idx_muse_ai_generated_fulltext_active
ON muse_ai_generated_fulltext(tenant_id, task_id, expires_at)
WHERE deleted = FALSE;
CREATE INDEX idx_muse_ai_generated_fulltext_cleanup
ON muse_ai_generated_fulltext(expires_at)
WHERE deleted = FALSE;
CREATE TRIGGER trg_muse_ai_generated_fulltext_updated_at
BEFORE UPDATE ON muse_ai_generated_fulltext
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();