From 328bbf88d2839baa0c78c171404812be217a8caf Mon Sep 17 00:00:00 2001 From: windyboy Date: Thu, 10 Sep 2026 08:55:43 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=20message-lifecycle.?= =?UTF-8?q?md=E2=80=94=E2=80=94=E4=B8=8A=E6=B8=B8=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E7=94=9F=E5=91=BD=E5=91=A8=E6=9C=9F=E5=94=AF=E4=B8=80=E8=A7=84?= =?UTF-8?q?=E8=8C=83=EF=BC=88=E4=BA=94=E4=BA=8B=E5=AE=9E/=E5=B4=A9?= =?UTF-8?q?=E6=BA=83=E6=81=A2=E5=A4=8D/=E6=B0=B4=E4=BD=8D/=E8=B6=85?= =?UTF-8?q?=E6=9C=9F=E8=A1=A5=E5=86=99/=E5=8E=86=E5=8F=B2=E7=A7=AF?= =?UTF-8?q?=E5=8E=8B/=E4=BF=A1=E7=AE=B1=E6=B8=85=E9=99=A4=20A/B/=E5=87=BA?= =?UTF-8?q?=E7=AB=99=E5=A5=91=E7=BA=A6=EF=BC=89=EF=BC=8C=E7=99=BB=E8=AE=B0?= =?UTF-8?q?=20Q9/Q10/Q11=EF=BC=8CREADME=20=E7=B4=A2=E5=BC=95=E4=B8=8E=20ar?= =?UTF-8?q?chitecture/design=20=E6=8C=87=E9=92=88=E8=A1=A5=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/README.md | 1 + docs/architecture.md | 2 +- docs/design.md | 2 +- docs/message-lifecycle.md | 210 ++++++++++++++++++++++++++++++++++++++ docs/user-stories.md | 3 + 5 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 docs/message-lifecycle.md diff --git a/docs/README.md b/docs/README.md index 83ac977..ad95e4e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,6 +6,7 @@ |---|---| | [architecture.md](architecture.md) | 系统边界、模块职责、FIFO、单写者、数据库归属。 | | [design.md](design.md) | 管道流程、处理/投递状态、恢复与运行配置。 | +| [message-lifecycle.md](message-lifecycle.md) | 信箱消息全生命周期的唯一现行规范:五事实、状态、水位、回填与清除。 | | [flight-state.md](flight-state.md) | 航班设计的唯一现行规范:当前态、表关系、事务流程和开放问题。 | | [user-stories.md](user-stories.md) | US/OPS 验收目标,不能用“当前基础”替代完成证据。 | | [旧系统行为基线](legacy/msgexchange-api-legacy-user-stories.md) | msgexchange-api 现役行为基线与 KEEP/FIX 来源,Q8 对拍参考;不作为 v2 设计依据。 | diff --git a/docs/architecture.md b/docs/architecture.md index 4f58797..c914630 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -12,7 +12,7 @@ msgexchange-v2 是机场 OMMS 的上游报文处理中间件,用于替换旧 - **输出**:Kafka 的 `msg` / `schd` 消息、共享 MySQL 的 `COUTMSGS` 出站信箱,以及查询 HTTP 接口;不直接推送前端。 - **当前范围(阶段 A)**:航班当前态落自有 PostgreSQL(`FLIGHT_SCHD` + 资源明细表 + `FLIGHT_ROUTE_POINT`,权威口径见 [flight-state.md](flight-state.md))。无 Redis 依赖;ES 历史投影属暂缓的阶段 B。 -本文描述架构约束,不代表所有能力已实现;实现缺口见第 9 节。模块交互、状态机和参数详见 [design.md](design.md),需求见 [user-stories.md](user-stories.md)。历史报文契约仍以 [SIS 接口规范](legacy/SIS_AODB_RMS-V0.1.md) 和 [XSD](legacy/unisysaodbsis.xsd) 为兼容依据,其他 legacy 资料仅作参考,旧系统行为基线的职责见 [README](README.md) 职责表。 +本文描述架构约束,不代表所有能力已实现;实现缺口见第 9 节。模块交互、状态机和参数详见 [design.md](design.md),消息生命周期与信箱清除见 [message-lifecycle.md](message-lifecycle.md),需求见 [user-stories.md](user-stories.md)。历史报文契约仍以 [SIS 接口规范](legacy/SIS_AODB_RMS-V0.1.md) 和 [XSD](legacy/unisysaodbsis.xsd) 为兼容依据,其他 legacy 资料仅作参考,旧系统行为基线的职责见 [README](README.md) 职责表。 现场供库时目标为 Oracle 11g,否则自建 PostgreSQL;当前只有 PG 实现可运行,Oracle 不是已支持的平台。 航班表结构和处理逻辑见 [运营航班状态设计](flight-state.md)。 diff --git a/docs/design.md b/docs/design.md index 41999b1..5b5a40a 100644 --- a/docs/design.md +++ b/docs/design.md @@ -25,7 +25,7 @@ | `BACKFILL_TODO` | 共享信箱回填重试 | 回填意图与业务终态同事务预登记,提交后回填成功即删除;待办再次落账失败的崩溃窗口仍在(§10)。 | | `PROC_STATE_HST` | 终态处理记录的归档目标 | 尚未建表;不得改写为共享库历史表。 | -字段与索引定义以 `src/main/resources/db/migration/V1__flight_state_baseline.sql` 为准;Oracle 11g 的迁移形态见 `src/main/resources/db/migration/oracle11g/`(占位,未接入任何 Flyway 配置)。报文原文仍从共享信箱读取,因此必须协调原文保留期,不能在消息尚需处理或重放时提前清理。 +字段与索引定义以 `src/main/resources/db/migration/V1__flight_state_baseline.sql` 为准;Oracle 11g 的迁移形态见 `src/main/resources/db/migration/oracle11g/`(占位,未接入任何 Flyway 配置)。报文原文仍从共享信箱读取,因此必须协调原文保留期,不能在消息尚需处理或重放时提前清理;生命周期、回填与清除契约的唯一定义见 [message-lifecycle.md](message-lifecycle.md)。 ### 2.2 消息、身份与决策 diff --git a/docs/message-lifecycle.md b/docs/message-lifecycle.md new file mode 100644 index 0000000..00f2edc --- /dev/null +++ b/docs/message-lifecycle.md @@ -0,0 +1,210 @@ +# 上游消息生命周期设计 + +## 本文范围与读者 + +本文定义 msgexchange-v2(下称"本系统")对共享 MySQL 信箱中报文的完整生命周期:从上游写入、本系统处理、处理标记回信箱,到信箱数据最终清除。各阶段的输入输出、幂等方式、故障恢复方法,以及本系统与信箱库管理方之间的分工,都在本文界定。 + +- 模块协作、状态机与配置参数见 [design.md](design.md);系统边界与"不建表、不改结构"的红线见 [architecture.md](architecture.md);验收口径见 [user-stories.md](user-stories.md)。 +- 读者包括本系统开发与运维人员、以及负责共享 MySQL 的库方接口人;§6、§7 中标注 Q 编号的条款即需要与库方书面确认的开放项。 + +**角色与术语约定**(全文沿用): + +- **上游**:向信箱写入报文的源头系统(CIIMS、AODB 等)。 +- **信箱**:共享 MySQL 中的入站信箱表 `CMINMSGS`;出站方向为 `COUTMSGS`(§7)。 +- **库方**:共享 MySQL 的管理方;表结构变更与数据清除只能由库方执行或书面授权。 +- **处理标记**:信箱行上表示"本系统已处理"的约定字段;逻辑名 `DATE_PROCESSED` / `STATUS`,实际列名以库方契约为准(legacy 为 `CMINMSGS_DATE_PROCESSED` 等真实列)。 +- **自有 PG**:本系统唯一的业务数据库 PostgreSQL;信箱与自有 PG 之间不存在跨库事务。 + +## 1. 五个独立事实 + +消息的认定分为五个环节,每个环节都有独立的证据,互不替代:上游写入了不等于本系统接手了,本系统处理完了也不等于信箱标记已写、下游已收到。 + +| 环节 | 认定依据 | 执行方 | +|---|---|---| +| 落信:报文进入信箱 | `CMINMSGS` 中存在该行 | 上游 | +| 入队:本系统开始处理 | 自有 PG 建立 `PROC_STATE` 记录 | `InboxPoller` | +| 处理完成:业务有结论 | `PROC_STATE` 到达终态(SUCCEEDED / SKIPPED / DEAD) | 主泵 | +| 已回填:信箱写入处理标记 | 信箱行持有处理标记 | 回填与补偿通道 | +| 下游确认:下游已接收 | `MSG_EVENT` 置 `SENT` | `delivery`(Dispatcher / flushSchd) | + +分环节的原因是存储边界:信箱与自有 PG 之间的写入不共享事务。前三个环节以自有 PG 为准;"已回填""下游确认"两个环节各自独立重试,都可能单独失败。 + +## 2. 状态总纲 + +```text +信箱行 未标记 ────────────────→ 已处理标记 ────────→ 已归档 ────────→ 已清除 + ↑ 回填/超期补写 §6(库方执行) +PROC_STATE PENDING / FAILED ──→ SUCCEEDED(成功) + ├→ SKIPPED(业务重复) + └→ DEAD(MALFORMED / PROTOCOL / EXHAUSTED,人工处置) +MSG_EVENT PENDING ──→ SENT + └──→ PENDING(退避重试)──→ DEAD(DLQ) +``` + +- `PENDING` 与 `FAILED` 是处理中的状态,`FAILED` 继续退避重试并占用 FIFO 队头;`SUCCEEDED / SKIPPED / DEAD` 是终态,到达后队列方可推进。 +- `DEAD` 与 `FAILED` 不是不可逆:经人工批准,指定错误类别的记录可重新置回 `PENDING` 处理(放行范围见 §9 / design.md §6.1)。重放处理的是当前状态,不恢复历史处理顺序。 +- 航班变更、待发事件、处理终态与回填待预登记四类写入位于同一个 PG 事务,一起提交或一起回滚;信箱处理标记写在该事务之后,依赖 `BACKFILL_TODO` 补偿记录最终写入。 + +## 3. 处理阶段 + +| 阶段 | 输入 | 输出 | 幂等依据 | 失败处理 | +|---|---|---|---|---| +| 收报 | `DATE_PROCESSED IS NULL` 的信箱行 | `PROC_STATE(PENDING)` | `MSG_ID` 主键 | 下轮扫描补入队 | +| 取队头 | 最小未完成 `MSG_ID` | 本批处理消息 | 表状态即队列 | 无队头则等待 | +| 解码与身份 | 信箱原文 | `DecodedMessage`、`IDENTITY_KEY` | 身份唯一约束 | 报文非法→`DEAD`;处理能力不足→`FAILED` 退避 | +| 事务处理 | 当前完整状态 + 报文载荷 | 航班变更、终态、事件、回填待办 | 消息 ID + 业务身份 | 事务整体回滚重试 | +| 提交后回填 | 终态消息 | 信箱处理标记 | 标记单调(§11) | 记入 `BACKFILL_TODO` 重试 | +| 投递 | `MSG_EVENT` | 下游确认 | `EVENT_ID` | 退避至 `DEAD`;至少一次 | +| 补偿作业 | 回填待办 / 到期批次 | 追平标记 | 待办主键 | 指数退避,独立线程执行 | + +处理器只在持有 `PIPELINE_LOCK` 的事务内写入自有 PG 状态,不操作信箱与 Kafka;全部外部副作用发生在事务提交之后。 + +## 4. 故障恢复 + +恢复的唯一依据是各存储中已持久化的记录,不依赖任何进程内存中的状态: + +| 中断位置 | 重启后的判定 | 恢复动作 | +|---|---|---| +| 已落信、未入队 | 信箱无标记且 PG 无记录 | 重扫补建入队记录 | +| 事务执行中 | PG 无该消息终态 | 事务整体回滚,按 `PENDING` 重新处理 | +| 事务已提交、标记未写 | `BACKFILL_TODO` 存在待办 | 仅补写标记;业务处理结果保持不变 | +| 回填待办登记失败(与业务同事务) | 事务未提交 | 同"事务执行中",不构成独立窗口 | +| 标记写入中途 | 标记仍为空 | 重新写入;重复写入同一值无副作用 | +| 下游已接收、`SENT` 未置 | 事件仍 `PENDING` | 允许重发,下游按事件身份去重 | + +两个缺口在闭环前不能宣称恢复完整: + +1. 事务提交后、补偿开始前仍存在崩溃窗口; +2. 补偿重试尚未证明"最终一定完成"。 + +两项登记于 design.md §10(事务与外部副作用)与 user-stories.md US-09。 + +## 5. 消费水位、超期补写与历史积压 + +### 5.1 消费水位 W + +水位 `W` 定义为信箱 ID 的连续上界:从最小 ID 到 `W` 的区间已全部读入自有 PG,无空洞;遇到空洞即停止推进。`W` 只随新 ID 的成功入队推进,不依赖处理完成或标记回写。 + +水位的有效性依赖两条需要库方确认的承诺(合计为 Q2): + +1. **ID 单调**:信箱 ID 按提交顺序分配,晚提交的较小 ID 不参与。承诺缺失时,`W` 只能作为快路径的提示,不能证明该区间收齐。 +2. **最大提交时延**:上游提交到 ID 可见的最长时间。补偿扫描窗口(`NOW − 最大提交时延`)的宽度由此确定。 + +日常执行方式:快路径从 `ID > W` 起按升序有限批次扫描;另按周期对窗口内可能迟到或空洞的行做补偿扫描。需要区分:水位表示"读取进度",与"已处理标记"是两个事实,不能互相替代。 + +### 5.2 超期标记补写 + +两类信箱行无法通过正常回填获得处理标记:报文残缺且缺少元数据的死信,以及回填通道长期失败的行。处理规则为: + +**已达 `PROC_STATE` 终态、且接收时间超期(`DATE_RECEIVED < NOW − R`)仍无标记的信箱行,由回填通道补写一个库方认可的"已处理"类标记。** + +- 期限 `R` 必须不小于(人工重放期限 + 人工处置期限)之和。提前补写会使仍可重放的消息失去原件资格。 +- 中间态(`PENDING` / `FAILED`)不适用本规则:处理未完成时不打标,也不允许被清除。 +- 补写值仅限于库方认可的 legacy 值集(Q7);死信、业务重复等内部原因记录在 `PROC_STATE` 与审计日志,不在信箱新增枚举。 +- 补写只针对空标记;已有值不回撤、不覆盖,重复执行无副作用。 + +该规则同时保证三件事成立:收报表不被永不回填的记录占满(Q2 中"积压挡批"场景)、§6 的清除边界可以达到、重放期限与信箱保留期具备可核验的下限关系(§9)。 + +### 5.3 历史积压消息的处理方案 + +"历史积压"指信箱中成规模的未处理存量:上线前遗留、停机期间累积、或消量未完成的批次。处理方案分三步,并约束四条行为红线。 + +**第一步:摸底。** 处理动作开始前,先确定积压的范围与构成:ID 区间、条数、时间跨度、报文类型分布(SCHD / FLOP / FDEL / ADFT 等),并与库方确认其中哪些仍需业务处理、哪些按约定跳过(跳过基调只在该批确认时成立,值集见 Q7)。 + +**第二步:先入队,后处理。** 两阶段执行,禁止边收边处理一辆长队: + +1. 消化阶段只做入队:`InboxPoller` 按升序有限批次将历史行全部建为 `PROC_STATE(PENDING)`,水位随之推到积压末端。此阶段只写自有 PG,不触碰信箱标记。 +2. 入队完成后交给主泵按最小未完成 ID 顺序消化。顺序与阈限与日常完全相同:不加速、不分流、不走旁路。 + +这样做的理由:入队是便宜操作(可大批量),处理是昂贵操作(解码 + 事务),把两者分开后,入库阶段的中断恢复只涉及重扫(§4 第一行),不会把半处理的事务复杂化;同时水位可以尽早到达完整上界,快路径与补扫窗口立即生效。 + +**第三步:等待过程中的四个边界。** + +- 不插队:主泵按 FIFO 消化,积压期间到达的实时消息排在积压之后。本设计不允许并行队头,也不允许实时通道跳过积压。 +- 不失控:队头滞留上限(head-deadline,当前 10 分钟)对积压同样生效;队头长期失败按既有规则转 `DEAD(EXHAUSTED)` 并告警,不会因积压而延长容忍。 +- 报文类型的处理方式不变:旧的全量日计划(SCHD-DNLD)按最近一份覆盖即可正确收敛,但仍逐条执行;动态增量(FLOP / FDEL / ADFT)持有时序语义,必须逐条。 +- 可放弃但必须留痕:摸底批中经库方确认"不再处理"的行,处置方式为——`PROC_STATE` 置 `SKIPPED` 并记录跳过原因,到达终态后走 §5.2 通道补写标记;本方案不支持任何"整段 DELETE"的快速通道。 + +**验收口径**:积压消化期间持续输出三项指标——剩余积压条数、最老未处理信龄、预计消化时长;期间不允许出现 FIFO 越序、身份去重失效或头行滞留超时未告警。红线依据:architecture.md §5(消息严格 FIFO)、单写者约束。 + +## 6. 信箱数据清除 + +表结构变更与物理清除由库方执行或书面授权执行;本系统对共享 MySQL 不建表、不改结构(红线见 architecture.md §6)。本系统在清除事务中的义务只有一项:为处理完成的行及时写入处理标记,使可清除范围存在明确边界。 + +具体方案由库方选择(Q9)。以下两种方案均基于 MySQL 自身能力:支持 `RANGE` 分区与 `TRUNCATE / DROP PARTITION`,不支持 `EXCHANGE PARTITION`。 + +**方案 A:按日分区(首选)**,适用于库方可以为表增加分区的场合。 + +1. `CMINMSGS` 按 `DATE_RECEIVED` 建立日粒度 RANGE 分区; +2. 某分区到达保留期时,确认该分区全部行已持有处理标记(§5.2 保证该条件在有限时间内满足); +3. 将该分区复制入历史表:`INSERT INTO CMINMSGS_HST SELECT`(`NOT EXISTS` 判重); +4. `TRUNCATE / DROP PARTITION` 执行清除:DDL 级操作,无行锁竞争,页外大字段(`CMINMSGS_CLOB_MSG` 列)整块释放,不产生碎片与 binlog 压力。 + +前提:库方确认现场 MySQL 版本支持分区 DDL,并已授权执行。 + +**方案 B:整表轮换**,适用于库方拒绝增加分区的场合。 + +1. `CREATE TABLE CMINMSGS_NEW LIKE CMINMSGS`,并将 `AUTO_INCREMENT` 种子设为 `max(ID) + 1`; +2. 将保留窗内行(`DATE_RECEIVED ≥ NOW − R_keep`)复制至新表; +3. 以单语句原子 `RENAME TABLE` 完成换名; +4. 对账:换名与复制之间新写入及新标记的行,从旧表幂等补回; +5. 旧表中早于保留窗的部分追加写入 `CMINMSGS_HST`(`NOT EXISTS` 判重); +6. `DROP TABLE` 旧表:秒级完成,碎片与大字段一并释放。 + +两种中断均安全:换名前失败则废弃新表重新执行;换名后失败则旧表仍完整,对账与归档语句均可重跑。 + +方案共同前提: + +- 执行清除时,边界内不存在未打标记的行;未达终态的行顺延至处理完成后清除(§5.2 仅对终态行补标); +- 时间比较与换算统一采用机场时区 Asia/Shanghai 及明确的类型转换(口径同 user-stories.md §6); +- 清除保留期 `R_keep` 不小于 max(回填重试上限、重放期限、审计期限);且 §5.2 的 `R` 不大于 `R_keep`,否则尚在重放窗口内的消息会先于重放被清除; +- 信箱 ID 全程不断链:方案 A 天然满足;方案 B 依赖 `AUTO_INCREMENT` 种子,种子缺失时新 ID 与旧记录主键冲突,水位随之失效。 + +## 7. 出站信箱(COUTMSGS) + +本系统一侧的规则(实现中:出站适配与请求协调尚未交付,机制描述见 design.md §4.2): + +出站前在 `REQ_TRACK` 登记 `REGISTERED`;写入 `COUTMSGS` 并确认落信后置 `SENT` 并关联出站记录 ID。"落信"指写入信箱成功,不等于下游已读取或已发送,交付承诺仅到落信为止(US-08)。 + +本系统写入的行由谁消费、按什么顺序消费,**当前未知**。以下事项在 Q10 关闭前按未知处理,不得作为已具备能力描述: + +- 消费方与消费顺序; +- `COUTMSGS_ACK_DATE_RECV / ACK_RESEND_TIMES / DATE_SENT / ERROR` 各列的语义与写入责任; +- 出站行的清除责任与保留期; +- 落信成功但本地未置 `SENT` 时的重复写入风险及下游去重契约。 + +参考事实:legacy 的 SIS 接口规范记载各系统持有各自的 `COUTMSGS` 副本,由 JDBC Adapter 读取后发送至 CIIMS。该机制是否在现场沿用,属于 Q10 的确认范围,不作为现状依据。 + +## 8. 自有记录归档 + +- `PROC_STATE`:终态记录归档至 `PROC_STATE_HST`(尚未建表)。未达终态的记录不归档;归档不得使"同一业务身份只能绑定一条有效处理记录"的去重能力失效(US-11)。 +- `SCHD_SNAP_LOG`:保留 90 天,清理窗口与判据见 design.md §6.2。 +- 航班当前态的清理规则唯一归属 [flight-state.md](flight-state.md) §6;其判据不依赖信箱原文。信箱原文的可用性仅影响重放能力(§9)。 + +## 9. 重放与原文可用性 + +- 可重放的错误类别为 `CODEC_ERROR / UNSUPPORTED / INFRA / EXHAUSTED` 四类(以 design.md §6.1 为准);重放处理当前状态,不恢复历史顺序。 +- 重放的前提是信箱原文仍可读取:`R_keep` 必须覆盖重放期限(§6),属于硬约束。 +- 处理时无法读取原文,一律按 `MALFORMED → DEAD` 处理。若原文缺失源于库方违反保留契约提前清除,按契约违例走运维追责通道;该消息的死信处置本身不变。 + +## 10. 开放问题索引 + +| 编号 | 待确认事项 | 本文相关章节 | +|---|---|---| +| Q2 | 信箱 ID 单调承诺;最大提交时延;空洞与迟到处理 | §5.1 | +| Q7 | 处理标记值集与写权限;原文保留期;处理时间语义 | §5.2、§6 | +| Q9(新增) | 清除执行方与 DDL 授权;方案 A / B 选型 | §6 | +| Q10(新增) | 出站消费方、ACK 列语义、出站清理与去重契约 | §7 | +| Q11(新增) | 上游 `SEQN` 重置规则与业务身份的日期边界 | design.md §2.2 | + +Q9–Q11 的完整登记见 [user-stories.md](user-stories.md) §6 的 Q 表。 + +## 11. 不变量 + +- 五个事实互不替代:入队不引用信箱标记,回填不引用投递,投递不引用回填。 +- 处理终态不可逆:已提交的 `SUCCEEDED` 不因回填或投递失败回改。 +- 处理标记单调:任何路径只将空标写为已处理,不回撤、不覆盖。 +- 水位不越过未入队的 ID;遇空洞即停。 +- 执行清除前,边界内全部行已持有处理标记;物理删除仅发生在归档成功之后(追加写入与分区留档均构成归档成功)。 +- 信箱 ID 全局单调、不断链,在任何清除方案下成立。 +- 对外投递按至少一次设计;端到端恰好一次不在交付范围内。 diff --git a/docs/user-stories.md b/docs/user-stories.md index f54e99f..e71aada 100644 --- a/docs/user-stories.md +++ b/docs/user-stories.md @@ -312,6 +312,9 @@ | Q6 deadline 与重放 | 入队时间作为稳定锚点会把长期排队消息计入滞留;历史重放保留 CREATED_AT 后可能立即过期。 | 明确首次处理/排队过期策略与“本次恢复尝试”计时方式,保留原始时间审计;测试积压恢复和旧 DEAD 重放,不用刷新 UPDATED_AT 绕过超时。 | | Q7 信箱外部契约 | 原目标为成功→SUCCESS、忽略→SKIPPED、重复→DUPLICATE、死信→DEAD;当前 JDBC 写 PROCESSED。新 STATUS 值尚不能假定库方支持。 | 库方认可的状态值、META/缺失字段、权限、原文保留期、出站去重与处理时间语义;若只允许 legacy 集合,显式映射内部原因,不新增外部枚举。 | | Q8 业务覆盖清单 | “29 FLOP、14 RQRD、21 参考类、2 机位类”只是数量,不能直接当字段规范。 | 将 SIS/XSD、现役 KEEP/FIX 基线整理为逐类矩阵与脱敏样例,列明路由、字段、缺失/清空、通知、数据来源优先级、多桥规则及测试文件。资料不全的类型不标完成。 | +| Q9 信箱清除契约 | 清除由谁执行与 DDL 授权、方案 A/B 选型、现场 MySQL 版本与分区 DDL 能力(message-lifecycle.md §6)。 | 库方书面确认清除授权与方案选型。 | +| Q10 出站信箱契约 | `COUTMSGS` 消费方与顺序、`ACK_DATE_RECV / DATE_SENT / ERROR` 等列语义与写入方、出站清理责任与去重契约(message-lifecycle.md §7;legacy 参考见 SIS 规范 COUTMSGS 机制章节)。 | 库方书面确认出站消费、清理与去重契约。 | +| Q11 上游序号重置 | 上游 `SEQN` 重置规则决定业务身份是否加入日期边界(design.md §2.2,默认关闭)。 | 上游确认重置规则;身份算法变更须另行评审。 | 业务日期/日计划采用 `Asia/Shanghai`;持久化与比较使用明确的时间类型和转换规则,不靠服务器默认时区,也不直接比较不同单位的数字。