feat(收口): 补齐 8 月迭代缺口并同步 Spec 与证据链
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
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:
@@ -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_id:outbox 仍只 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_item,origins 含 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,人工入队请调用人工入队用例
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user