feat(收口): 补齐 8 月迭代缺口并同步 Spec 与证据链
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled

- 新增六对成对迁移 000232–000237:H5 弹窗类型、退款结算标识与申请人备注、优先轮询事实字段与两个新终态、通道阈值命中留痕、手机号最近解绑人、提现资格校验留痕
- 退款:原因必填与申请人备注、来源支付与渠道流水冻结、线下处理流水号补录审计、按订单查询可选退款方式、企微审批材料补齐且新增字段缺失映射即明确失败
- 优先轮询:人工关闭、有效期到期独立周期任务、失败与过期人工重触发、事实字段与异常重试查询、资产解析端点只读投影
- 通道阈值:命中事实同事务留痕与命中记录查询;员工账单:列表筛选与详情投影;商户池:列表投影与统计周期语义;H5:弹窗类型与类别排序
- 手机号:有效关联数量与最近解绑人、短信验证码失败次数限制;导出:佣金明细十五列与报表序号列
- 时间筛选:三处新增筛选纳入统一严格解析契约,员工账单产生时间参数改名
- 同步 12 份主 Spec 需求、两端点与异步任务证据链,门禁 context-health 与 OpenSpec 校验通过
This commit is contained in:
2026-09-18 15:34:29 +08:00
parent 5e78809b93
commit 5ed6b39deb
142 changed files with 7878 additions and 964 deletions

View File

@@ -62,7 +62,7 @@
| 场景 | 断言 | 期望 → 实际(摘录) |
| --- | --- | --- |
| A Store 生命周期 | 20 PASS | `A1 首次认领命中…→ status=processing claimed_at=2026-09-17 09:24:49+08``A2 超租约(120s>90s)允许接管 → taken=true``A2 租约内(10s<90s)不允许接管 → taken=false``A3 两次 IncrementAttempt 后 attempt_count → 期望=2 实际=2``A3 MarkFailed未累加尝试次数等同 FailFinal 路径)→ attempt_count=0``A3 尝试上限路径 → attempt_count=1``A4 分页归一化 Page=0/PageSize=999 → total=29 returned=20` |
| A Store 生命周期 | 20 PASS | `A1 首次认领命中…→ status=processing claimed_at=2026-09-17 09:24:49+08``A2 超租约(120s>90s)允许接管 → taken=true``A2 租约内(10s<90s)不允许接管 → taken=false``A3 两次 MarkExecutionStarted 后 attempt_count → 期望=2 实际=2``A3 MarkFailed未累加尝试次数等同 FailFinal 路径)→ attempt_count=0``A3 尝试上限路径 → attempt_count=1``A4 分页归一化 Page=0/PageSize=999 → total=29 returned=20` |
| B 消费者 | 15 PASS | `B5 设备载体在事务内冻结的绑定卡数 → 3``B5 活动项行数3 卡 × 4 任务类型) → 12``B6 重复投递只合并:行数不变、触发次数+1、最近触发时间刷新、触发类型集合去重``B7 自动no_valid_package+ 人工manual_trigger合并为同一行``B8 已终态后重复追加同一 event_idoutbox 仍只 1 行``B9 同一 event_id 重投不产生重复审计行EventID 去重) → 1` |
| C 触发分类与前置条件 | 13 PASS | `C10 → renewal_activated` / `purchase_activated``C11 存在 status=0 → HasPendingPackageUsage=true``C12 观测抑制为真 → 不写事件0 行)``C12 无有效套餐 event_id ≤ 48 且主体与载体可区分 → prio:nvp:d:990016999:… len=31` |
| D 读侧权限与范围 | 12 PASS | `D13 超管/平台 → total=18/18``D13 代理 → total=16`(平台卡与范围外卡各 1 行不可见);`D13 企业 → code=1005``D14 详情越权 vs 不存在 → 同一码与文案` |
@@ -70,10 +70,12 @@
| F 审计来源匹配 | 6 PASS | `F polling_priority.enqueue/claim/manual_denied 注册 → primary=polling_priority_itemorigins 含 account/admin_api 与 system_task/worker``F 消费者审计 Actor=system_task / Source=worker` |
| count残留计数 | 10 PASS | 卡/设备/绑定/套餐使用/优先项/审计/outbox/两类孤儿审计资源 **均 = 0**,且 `本批全部自建行已清理干净` |
口径说明(`close-august-iteration-gaps` 引入的重命名2026-09-18 核对):本表 A3 的 Store 方法在本次重命名中由 `IncrementAttempt` 改为 `MarkExecutionStarted``internal/store/postgres/polling_priority_item_store.go`,签名 `(ctx, id, now)`,断言口径不变);人工入队用例文件由 `internal/service/polling/priority_enqueue_service.go` 改名为 `internal/service/polling/priority_manual_service.go`(类型 `PriorityEnqueueService``PriorityManualService``Enqueue` 签名不变,新增 `Close`/`Retrigger`)。
### 2.4 H5 加固:事件通道拒绝 `manual_trigger`2026-09-17 09:24:47
`internal/infrastructure/prioritypolling/event.go``AppendPriorityRequested` 在资源类型校验后显式拒绝
`trigger_type='manual_trigger'`(人工入队由 `internal/service/polling/priority_enqueue_service.go` 直写事实表,不经事件通道)。
`trigger_type='manual_trigger'`(人工入队由 `internal/service/polling/priority_manual_service.go` 直写事实表,不经事件通道)。
```
[PASS] H5-1 经事件通道投递 manual_trigger 返回参数错误 → code=1001 err=优先轮询事件不接受人工入队触发类型 manual_trigger人工入队请调用人工入队用例

View File

@@ -293,7 +293,8 @@
"capability": "asset-device",
"requirements": [
"asset-device::资产业务状态",
"identity-access::数据范围拒绝"
"identity-access::数据范围拒绝",
"asset-device::资产与卡详情的优先轮询状态投影"
],
"classification": "behavior"
},
@@ -544,6 +545,17 @@
],
"classification": "behavior"
},
{
"entry_type": "http",
"entry": "GET /api/admin/carrier-traffic-threshold-hits",
"capability": "carrier-channel-traffic-threshold",
"requirements": [
"carrier-channel-traffic-threshold::通道阈值命中事实留痕与查询",
"export-time-filter::受影响端点与旧格式替换",
"identity-access::数据范围拒绝"
],
"classification": "behavior"
},
{
"entry_type": "http",
"entry": "GET /api/admin/commission/withdrawal-requests",
@@ -1101,7 +1113,8 @@
"order-refund-exchange::订单、退款与换货状态门禁",
"order-refund-exchange::代理退款查询按所属店铺隔离",
"order-refund-exchange::退款终态事实与失败分类",
"order-refund-exchange::退款展示当前退款套餐用量"
"order-refund-exchange::退款展示当前退款套餐用量",
"order-refund-exchange::退款渠道标识与线下处理流水号"
],
"classification": "behavior"
},
@@ -1114,7 +1127,18 @@
"order-refund-exchange::订单、退款与换货状态门禁",
"order-refund-exchange::代理退款查询按所属店铺隔离",
"order-refund-exchange::退款终态事实与失败分类",
"order-refund-exchange::退款展示当前退款套餐用量"
"order-refund-exchange::退款展示当前退款套餐用量",
"order-refund-exchange::退款渠道标识与线下处理流水号"
],
"classification": "behavior"
},
{
"entry_type": "http",
"entry": "GET /api/admin/refunds/order-options",
"capability": "order-refund-exchange",
"requirements": [
"identity-access::数据范围拒绝",
"order-refund-exchange::退款实收金额与方式矩阵"
],
"classification": "behavior"
},
@@ -1169,7 +1193,8 @@
"capability": "identity-access",
"requirements": [
"identity-access::数据范围拒绝",
"business-user-group::店铺负责人和所属组实时推导"
"business-user-group::店铺负责人和所属组实时推导",
"agent-distribution-withdrawal::店铺下级代理数量投影"
],
"classification": "behavior"
},
@@ -1207,7 +1232,8 @@
"capability": "identity-access",
"requirements": [
"identity-access::数据范围拒绝",
"business-user-group::店铺负责人和所属组实时推导"
"business-user-group::店铺负责人和所属组实时推导",
"agent-distribution-withdrawal::店铺下级代理数量投影"
],
"classification": "behavior"
},
@@ -2349,7 +2375,10 @@
"requirements": [
"identity-access::数据范围拒绝",
"order-refund-exchange::订单、退款与换货状态门禁",
"order-refund-exchange::退款实收金额与方式矩阵"
"order-refund-exchange::退款实收金额与方式矩阵",
"order-refund-exchange::退款原因必填与申请人备注",
"order-refund-exchange::退款渠道标识与线下处理流水号",
"order-refund-exchange::企业微信退款审批材料字段"
],
"classification": "behavior"
},
@@ -2383,7 +2412,9 @@
"requirements": [
"identity-access::数据范围拒绝",
"order-refund-exchange::订单、退款与换货状态门禁",
"order-refund-exchange::企业微信唯一终审与审批尝试重提"
"order-refund-exchange::企业微信唯一终审与审批尝试重提",
"order-refund-exchange::退款原因必填与申请人备注",
"order-refund-exchange::企业微信退款审批材料字段"
],
"classification": "behavior"
},
@@ -2397,6 +2428,16 @@
],
"classification": "behavior"
},
{
"entry_type": "http",
"entry": "POST /api/admin/refunds/{id}/offline-settlement",
"capability": "order-refund-exchange",
"requirements": [
"identity-access::数据范围拒绝",
"order-refund-exchange::退款渠道标识与线下处理流水号"
],
"classification": "behavior"
},
{
"entry_type": "http",
"entry": "POST /api/admin/roles",
@@ -2608,7 +2649,8 @@
"identity-access::令牌生命周期",
"personal-customer::个人客户身份",
"phone-asset-association::H5 验证建立关联与数量上限",
"phone-asset-association::H5 绑定与换绑的关联写入"
"phone-asset-association::H5 绑定与换绑的关联写入",
"phone-asset-association::短信验证码校验失败次数限制"
],
"classification": "behavior"
},
@@ -2619,7 +2661,8 @@
"requirements": [
"identity-access::令牌生命周期",
"personal-customer::个人客户身份",
"phone-asset-association::H5 绑定与换绑的关联写入"
"phone-asset-association::H5 绑定与换绑的关联写入",
"phone-asset-association::短信验证码校验失败次数限制"
],
"classification": "behavior"
},
@@ -3699,7 +3742,8 @@
"entry": "POST /api/admin/refunds/{id}/trigger-approval",
"capability": "order-refund-exchange",
"requirements": [
"order-refund-exchange::历史待审批退款可主动接入企业微信审批"
"order-refund-exchange::历史待审批退款可主动接入企业微信审批",
"order-refund-exchange::企业微信退款审批材料字段"
],
"classification": "behavior"
},
@@ -3819,7 +3863,8 @@
"entry": "GET /api/admin/payment-merchant-pools",
"capability": "merchant-payment-routing",
"requirements": [
"merchant-payment-routing::商户池唯一性与轮询配置"
"merchant-payment-routing::商户池唯一性与轮询配置",
"merchant-payment-routing::商户池列表投影"
],
"classification": "behavior"
},
@@ -3837,7 +3882,8 @@
"entry": "GET /api/admin/payment-merchant-pools/{id}",
"capability": "merchant-payment-routing",
"requirements": [
"merchant-payment-routing::商户池唯一性与轮询配置"
"merchant-payment-routing::商户池唯一性与轮询配置",
"merchant-payment-routing::商户池列表投影"
],
"classification": "behavior"
},
@@ -3911,7 +3957,9 @@
"entry": "GET /api/admin/employee-collection-bills",
"capability": "employee-collection-bill",
"requirements": [
"employee-collection-bill::账单余额、状态与关闭"
"employee-collection-bill::账单余额、状态与关闭",
"employee-collection-bill::员工账单列表查询与筛选",
"export-time-filter::受影响端点与旧格式替换"
],
"classification": "behavior"
},
@@ -3929,7 +3977,8 @@
"entry": "GET /api/admin/employee-collection-bills/{id}",
"capability": "employee-collection-bill",
"requirements": [
"employee-collection-bill::账单余额、状态与关闭"
"employee-collection-bill::账单余额、状态与关闭",
"employee-collection-bill::员工账单详情投影"
],
"classification": "behavior"
},
@@ -4026,7 +4075,9 @@
"entry": "POST /api/c/v1/agent-distribution-registrations",
"capability": "agent-distribution-withdrawal",
"requirements": [
"agent-distribution-withdrawal::分销码与待审批代理注册"
"agent-distribution-withdrawal::分销码与待审批代理注册",
"agent-distribution-withdrawal::注册审批材料带出业务员",
"phone-asset-association::短信验证码校验失败次数限制"
],
"classification": "behavior"
},
@@ -4424,7 +4475,8 @@
"capability": "polling-operations",
"requirements": [
"identity-access::数据范围拒绝",
"priority-polling-queue::优先轮询事实与查询的可追溯"
"priority-polling-queue::优先轮询事实与查询的可追溯",
"export-time-filter::受影响端点与旧格式替换"
],
"classification": "behavior"
},
@@ -4438,6 +4490,37 @@
],
"classification": "behavior"
},
{
"entry_type": "http",
"entry": "POST /api/admin/polling-priority-items/{id}/close",
"capability": "polling-operations",
"requirements": [
"identity-access::数据范围拒绝",
"priority-polling-queue::优先项尝试次数与出队",
"priority-polling-queue::优先轮询事实与查询的可追溯"
],
"classification": "behavior"
},
{
"entry_type": "http",
"entry": "POST /api/admin/polling-priority-items/{id}/retrigger",
"capability": "polling-operations",
"requirements": [
"identity-access::数据范围拒绝",
"priority-polling-queue::优先项尝试次数与出队",
"priority-polling-queue::优先轮询事实与查询的可追溯"
],
"classification": "behavior"
},
{
"entry_type": "async",
"entry": "constants.TaskTypePollingPriorityExpiry",
"capability": "priority-polling-queue",
"requirements": [
"priority-polling-queue::优先项尝试次数与出队"
],
"classification": "behavior"
},
{
"entry_type": "async",
"entry": "constants.OutboxEventTypeAssetAutoRenewalResumeRequested",

File diff suppressed because it is too large Load Diff