feat(sync): ov inbox ad 分支与 sender adId 推导(disabled/墓碑=删投影行)

- dto.ts SYNC_ENTITY_TYPES 追加 'ad'(对齐契约 SyncEntityType)。
- decideAndApply ③依赖检查豁免 ad:albumId 恒空串,不豁免则事件被永久
  暂存且无解锁路径(slot-state 同款空 albumId 危害)。
- project() 新增 ad 分支:全量快照直投 ads_ov;墓碑或 enabled=false 均
  deleteMany(disabled=公开不可见=无投影);albumIds 整体替换;createdAt
  取 cn 原值、updatedAt 为 ov 应用时刻(载荷无该字段)。
- sender.toWireEvent 新增 ad 分支:entityId 取载荷 adId(outbox 表无列),
  泛化 categoryId/assetId 兜底之前,缺料 fail-fast。
- e2e ads.e2e-spec:手工构造 outbox 行(绕过 CRUD,Task 7 才有)走真实
  sender→HTTP→inbox 链路,5 用例覆盖快照落位/disable 删行/复活 upsert/
  迟到旧版本不回滚/墓碑删行;reset-ov 增清 ads_ov。
- db-ov schema 附带注释修:ads_ov updatedAt 语义纠正(迁移头过度声明,
  迁移文件不动防 checksum 漂移)+ sync_inbox.entityType 枚举补 ad。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-28 23:18:37 +08:00
parent d86f452bed
commit 4db90b0e9e
6 changed files with 333 additions and 9 deletions
+2 -1
View File
@@ -21,10 +21,11 @@ export const RESET_TABLES_OV: readonly string[] = [
// 同步账本(Task 4 inbox 消费)。
'sync_inbox',
'sync_state',
// 副本域(photos 先于 albums;展示位副本相册无关,随副本域一并清)。
// 副本域(photos 先于 albums;展示位/广告位副本相册无关,随副本域一并清)。
'photos_ov',
'albums_ov',
'embed_slots_ov',
'ads_ov',
];
/** TRUNCATE photo_ov 中 RESET_TABLES_OV 里**实际存在**的表(空库安全)。 */