fix(activity): close Phase 15 KEEP-VERIFY/EXTEND — 2 critical + 14 other defects, 3 test-fidelity fixes
Phase 15 (activity registration / review / checkin) verification closure. Two CRITICAL defects, both "production always had it, test schema never did": - D1: generateCheckinToken wrote the token to Redis with value "used", while scanCheckin rejects any token marked "used" -> every freshly issued check-in code was dead on arrival, staff scanning failed 100% of the time. Issuing now writes "issued"; "used" is set only after a successful scan. - D9: UNIQUE(activity_id, user_id) exists in production, but re-registering after cancel/reject went through INSERT -> users who cancelled once could never register for that activity again (duplicate key 500). The H2 test schema lacked the UNIQUE, so the path had zero coverage. Now the original row is reused via an atomic conditional UPDATE. Checkin (D2-D8): - D2: duplicate check-in was read-then-write; now atomic checkinIfNotCheckedIn and repeat scans are idempotent (alreadyCheckedIn) without duplicate audit. - D3: no data scope at all -> added activity staff assignment (V040) and assertCheckinScope; INV-020 (org relation grants nothing). - D4: manualCheckin did not validate activity existence/cancellation. - D5: getCheckinStats NPE on missing activity; remainingCount was semantically "free seats" -> replaced with notCheckedInCount. - D6: malformed timestamp caused 500 -> 400. D7: constant-time signature compare. Registration / review / cancel (D10-D13): - D10: backend registration list only queried status='approved' -> the review screen never saw pending rows (review unusable). - D11: registration_start_at / registration_end_at were never enforced. - D12: cancel had no audit log (the only write without one). - D13: reject/cancel were read-then-full-update -> rejectIfPending/cancelIfActive. Capacity groups (D14, plan item 2): groups were stored and read back but never participated in capacity -> incrementIfAvailable / decrementIfPositive now make approved_count real; activities without groups are unaffected. Frontend contract (F1-F2): - F1: admin-web had no check-in surface at all -> ActivityCheckinView.vue (paste/scan token, manual check-in, stats) + /activities/checkin route & nav. - F2: miniapp had no cancel-registration wrapper although the endpoint existed. Test fidelity (T1-T3): - T1: test schema gained UNIQUE(activity_id,user_id) + chk_reg_status + chk_checkin_status; two new guards parse the real V010 DDL and compare. - T2: 3 assertTrue(true) placeholders in CheckinServiceTest (covering duplicate check-in, expiry, no-sensitive-plaintext) replaced with 5 real guards that parse the real source and real production DDL. - T3: activity_registrations + activity_staff_assignments moved into REQUIRED_IN_TEST_SCHEMA; MigrationValidationTest baseline 39 -> 40. Note: ActivityStaffAssignment must NOT extend BaseEntity - the table is a composite PK (activity_id, operator_id); BaseEntity would add id/updated_at/ deleted_at to every INSERT and break on PostgreSQL (caught by EntityMigrationParityTest immediately). Tests: ActivityPhase15Test (21), CheckinServiceTest (5), 2 new constraint guards. Negative verification: 3 injected defects -> 8 assertions turned red, all restored. Regression: 474 tests / 0 failures / 0 errors / 3 skipped / BUILD SUCCESS (baseline 450). admin-web vue-tsc 0 error, vite build OK.
This commit is contained in:
@@ -3,6 +3,15 @@
|
||||
> V1.0 Phase 01~26 基础 + V1.1 增量任务合并基线
|
||||
> 版本:v1.1.0-dev | 最后更新:2026-09-08
|
||||
|
||||
> **2026-09-17 Phase 15 复验关闭:** EPIC-P15 已完成。复验发现两处**必崩级**缺陷,均为「生产一直存在、
|
||||
> 测试库从未约束」的同族根因:① **签到码一生成即作废** —— `generateCheckinToken` 把 token 写入 Redis
|
||||
> 值 `"used"`,而 `scanCheckin` 见到 `"used"` 立即拒绝,扫码签到 **100% 失败**;
|
||||
> ② **取消后永远无法再报名** —— 生产 `UNIQUE(activity_id, user_id)` 一直存在,而重报名走 `INSERT`,
|
||||
> 测试库缺该唯一键故零覆盖。共修复 **16 处缺陷 + 3 处测试保真度缺陷**,新增 V040
|
||||
> `activity_staff_assignments` 落实「服务站操作员只能操作指定活动」(INV-020)。
|
||||
> 证据:`docs/Phase-15-V11-Recovery-Completion-Report-2026-09-17.md`。
|
||||
> **Phase 16 需用户确认后启动。**
|
||||
|
||||
> **2026-09-16 状态校正:** Phase 07 UI 已按 2026-09-13 规格重新实现,**首批 11 页于 2026-09-16 通过用户验收(结论:基本达标)**,本文件此前"视觉否决/REOPENED"口径随之关闭。
|
||||
>
|
||||
> **2026-09-17 Phase 14 复验关闭:** EPIC-P14 已完成。复验发现 activity 模块存在**必崩级空壳**——
|
||||
@@ -120,6 +129,7 @@
|
||||
| Phase 13 公益红娘转介复验 | 已完成(2026-09-16) | 见 `Phase-13-V11-Recovery-Completion-Report-2026-09-16.md`;修复 7 处缺陷(**2 处生产故障级 CHECK 约束缺口致推荐接受/服务提交必崩**、推荐与转介三处越权、`getServiceDetail` 越权读、Mapper 缺 `@Select` 致必崩、前端 5 处契约缺口),测试库补 3 张 matchmaker 表,迁移基线 V038;新增 `MatchmakerReferralPhase13Test`(17 用例)+ 重写 `MatchmakerServiceTest`(6 用例,解析真实 DDL),删除 3 处假测试,后端 **391 tests 全绿**;**Phase 13A 尚未获准** |
|
||||
| Phase 13A 婚恋咨询与婚前辅导复验 | 已完成(2026-09-17) | 见 `Phase-13A-V11-Recovery-Completion-Report-2026-09-17.md`;发现 counseling **双实现**(权威类零测试 / 孤儿类被单测),已合并删除孤儿类;修复 **9 处缺陷**(**D1 咨询正文写日志=INV-013 泄露**、D2 申请 userId 取请求体、**D3 分配先读后写并发静默覆盖**、D4 manager 可读 followups=INV-013 绕过、D5 无状态机、**D6 `/services/intro` 后端不存在致小程序 intro 页 100% 无数据**、D7 Admin 5 端点 404、D8 小程序字段名/幂等/静默失败、D9 测试库 counseling 零 CHECK 约束)+ **4 处测试基建缺陷**(守卫找不到 DDL 恒真假绿、全限定 `@TableField` 漏解析、权限守卫假阳性、测试自身逻辑缺陷);迁移基线 V039;新增 `CounselingPhase13ATest`(25)+ `CounselingConstraintGuardTest`(5,解析真实 DDL),两轮负向验证证明守卫会红;后端 **420 tests 全绿**;**Phase 14 尚未获准** |
|
||||
| Phase 14 多类型公益活动复验 | 已完成(2026-09-17) | 见 `Phase-14-V11-Recovery-Completion-Report-2026-09-17.md`;修复 **11 处后端缺陷**(**D1 `ActivityMapper.countRemainingCapacity` 无 SQL 空壳致详情/报名/审核必崩**、**D2 报名与审核先读后写并发超卖** → 改原子 SQL、D3 类型/角色未校验生产 CHECK 白名单、**D4 DTO 无 `activityType` 致小程序分类 Tabs 恒空**、D5 男女人数 `approvedCount/2` 编造、D6 年龄门槛空壳、D7 按类型资格策略为空、**D8 运营端建活动丢弃类型且把主办组织错设为操作者 userId**、D9 三个运营端点错挂用户端双实现、D10 软删活动/缺字段 NPE、D11 DTO 缺 4 字段)+ **3 处前端契约缺陷**(分类 code `classroom` 不在白名单、卡片读 7 个不存在字段、admin-web 无活动管理页)+ **2 处测试保真度缺陷**(2 条占位假绿、测试库缺 V023 列与三张表);新增 `ActivityPhase14Test`(23)+ `ActivityConstraintGuardTest`(9,解析真实 DDL **与前端源码**),两轮负向验证证明守卫会红;admin-web `vue-tsc` 0 error + `vite build` 通过;后端 **450 tests 全绿**;**Phase 15 尚未获准** |
|
||||
| Phase 15 活动报名审核签到复验 | 已完成(2026-09-17) | 见 `Phase-15-V11-Recovery-Completion-Report-2026-09-17.md`;修复 **16 处缺陷**(**D1 签到码一生成即作废**:`generateCheckinToken` 把 token 写 `"used"` 而扫码端见 `"used"` 即拒 → 扫码 100% 失败;**D9 取消/拒绝后永远无法再报名**:撞生产 `UNIQUE(activity_id,user_id)`,测试库缺该约束故零覆盖 → 改复用记录;D2 重复签到竞态、D3 签到无数据范围、D4 手工签到无校验、D5 统计 NPE+语义错、D6 非法 token 500、D7 签名非恒定时间比较、D10 后台审核列表无 pending、D11 报名窗口不生效、D12 取消无审计、D13 审核/取消非原子、D14 容量分组不参与扣减)+ **2 处前端契约缺陷**(admin-web 无签到工作台、小程序无取消报名入口);新增 V040 `activity_staff_assignments` 落实 INV-020 活动数据范围;**3 处测试保真度缺陷**(测试库缺 UNIQUE+2 CHECK、3 条 `assertTrue(true)` 假绿、表未入必选集合);新增 `ActivityPhase15Test`(21),`CheckinServiceTest` 假绿改真实守卫(5),约束守卫 +2,迁移基线 39→40;一轮负向验证 3 处注入 → 8 条用例精准变红并还原;admin-web `vue-tsc` 0 error + `vite build` 通过;后端 **474 tests 全绿**;**Phase 16 尚未获准** |
|
||||
| UI-CLEANUP-20260913 | 已完成 | 废弃 UI 代码、冲突规范、旧计划和无效验收证据已清理;`ui-document-baseline-contracts` 锁定唯一视觉入口 |
|
||||
| UI-ADMIN-20260913 | 已完成(待桌面端目视复验) | 管理端全局框架与工作台已按规格交付;18 modules + 22 routes,vue-tsc 与 vite build 全绿 |
|
||||
| UI-MINIAPP-20260913 | 已完成 | 小程序 11 个核心页面已重构;11/11 页 TS-only,2026-09-16 通过用户验收 |
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
# Phase 15(活动报名、审核与签到)V1.1 增量复验完成报告
|
||||
|
||||
- **日期**:2026-09-17
|
||||
- **模式**:KEEP-VERIFY / EXTEND
|
||||
- **范围**:activity registration、checkin 服务与 U29~U32 页面
|
||||
- **基线**:Phase 14 收尾 `755a570`(全量回归 450 tests)
|
||||
- **结论**:**关闭**。三项计划事项全部落地,Gate 两项均达成
|
||||
|
||||
---
|
||||
|
||||
## 一、计划项达成情况
|
||||
|
||||
| 计划项 | 结论 | 证据 |
|
||||
|---|---|---|
|
||||
| 回归报名、审核、取消、签到码、重复签到和名额并发 | ✅ | `ActivityPhase15Test` 21 例,覆盖取消/拒绝后重报名、重复报名、审核并发、重复扫码幂等、过期码、跨活动复用 |
|
||||
| 增加非 matchmaking 活动和 capacity group 场景测试 | ✅ | 容量分组**真正参与扣减**(此前只落库回读);婚恋课堂类不设实名/本地资格门槛 |
|
||||
| 服务站操作员只能操作指定活动或站点任务 | ✅ | 新增 V040 `activity_staff_assignments` + 签到/审核数据范围校验(INV-020) |
|
||||
|
||||
**Gate**
|
||||
|
||||
| Gate | 结论 |
|
||||
|---|---|
|
||||
| 重复请求和并发报名不超额 | ✅ 报名/审核/取消/签到全部改为单条条件 SQL,靠数据库保证原子性 |
|
||||
| 签到不可跨活动复用 | ✅ 签到码作用域由 token 内 `activityId` 决定;且工作人员必须被显式指派到该活动 |
|
||||
|
||||
---
|
||||
|
||||
## 二、修复缺陷清单(16 处)
|
||||
|
||||
### A. 签到(8 处,含 1 处必崩)
|
||||
|
||||
- **D1 CRITICAL — 每一个签到码一生成即作废**:`generateCheckinToken` 把 token 写入 Redis 值 `"used"`,而 `scanCheckin` 见到 `"used"` 立即拒绝 → **扫码签到 100% 失败**。改为签发时写 `issued`,消费标记只在扫码成功后写入。
|
||||
- **D2 CRITICAL — 重复签到竞态**:原为「读 → 判断 → `updateById` 全量覆盖」,并发扫码会重复写 `checkin_at` 与审计。改为 `checkinIfNotCheckedIn` 条件更新;重复扫码幂等返回 `alreadyCheckedIn=true`,不重复记审计。
|
||||
- **D3 HIGH — 签到无数据范围**(计划项③):任意持 `activity.checkin` 权限者可签到任意活动任意用户。新增 `assertCheckinScope`:被指派过活动的工作人员只能操作被指派的活动;无任何指派记录者为平台级人员。
|
||||
- **D4 HIGH — 手工签到无校验**:`manualCheckin` 不校验活动是否存在/已取消(原实现只有 `generate` 校验时间窗)。补 `requireCheckableActivity`。
|
||||
- **D5 MEDIUM — 签到统计 NPE 与语义错**:活动不存在时 `activity.getTotalLimit()` NPE;`remainingCount` 用「总名额 − 已签到」计算。改为抛明确错误,并输出语义正确的 `notCheckedInCount`。
|
||||
- **D6 MEDIUM — 非法 token 返回 500**:`Long.parseLong` 未捕获 `NumberFormatException`。改为 `IllegalArgumentException`(400)。
|
||||
- **D7 MEDIUM — 签名比较非恒定时间**:改用 `MessageDigest.isEqual`,避免侧信道逐字节爆破。
|
||||
- **D8 LOW — 未使用变量**:`getCheckinStats` 中 `regMapper` 冗余赋值,已删。
|
||||
|
||||
### B. 报名 / 审核 / 取消(5 处,含 1 处必崩)
|
||||
|
||||
- **D9 CRITICAL — 取消后永远无法再报名**:生产 `UNIQUE(activity_id, user_id)` 一直存在,而「取消/拒绝后重新报名」走的是 `INSERT` → 撞唯一键 500,用户取消一次即永久失去该活动资格。测试库此前**缺该 UNIQUE**,因此零覆盖。改为复用原记录 + 原子条件 UPDATE(`reuseIfCapacityAvailable`),并同样带容量条件。
|
||||
- **D10 HIGH — 后台审核列表看不到待审记录**:`getRegistrations` 只查 `status='approved'` → 审核页面无 pending 可点,审核功能实际不可用。改为 `findByActivity`(全状态)。
|
||||
- **D11 MEDIUM — 报名窗口形同虚设**:`registration_start_at` / `registration_end_at` 完全不校验,活动一发布就永远可报。新增 `assertWithinRegistrationWindow`。
|
||||
- **D12 MEDIUM — 取消无审计**:取消是唯一没有审计日志的写操作。补 `CANCEL_REGISTRATION` 审计。
|
||||
- **D13 MEDIUM — 审核/取消非原子**:`rejectRegistration` 为「读 pending → 全量 updateById」,两人同时操作会互相覆盖;`cancelRegistration` 亦然。改为 `rejectIfPending` / `cancelIfActive` 条件更新。
|
||||
|
||||
### C. 容量分组(计划项②,1 处)
|
||||
|
||||
- **D14 MEDIUM — 分组容量完全不生效**:`activity_capacity_groups` 只落库回读,`approved_count` 永远是 0。新增 `incrementIfAvailable` / `decrementIfPositive`,在报名、审核通过、取消时真实扣减/回退(未配置分组的活动不受影响)。
|
||||
|
||||
### D. 前端契约(2 处)
|
||||
|
||||
- **F1 — 工作人员无处消费签到码**:admin-web 完全没有签到页面,D1 修复后仍无法闭环。新增 `ActivityCheckinView.vue`(扫码/粘贴签到码 + 手工签到 + 统计)+ `/activities/checkin` 路由与导航。
|
||||
- **F2 — 小程序无法取消报名**:后端 `DELETE /activities/{id}/register` 已存在,但 `activityService.js` 无封装、「我的活动」页无入口。补 `cancelRegistration` 封装。
|
||||
|
||||
---
|
||||
|
||||
## 三、测试保真度修复(3 处)
|
||||
|
||||
- **T1 约束漂移盲区**:测试库 `activity_registrations` 缺 `UNIQUE(activity_id, user_id)`、`chk_reg_status`、`chk_checkin_status` —— 这正是 D9 必崩缺陷长期不可见的根因。已补齐。
|
||||
- **T2 占位假绿**:`CheckinServiceTest` 有 3 条 `assertTrue(true); // 占位测试`,恰好覆盖「重复签到」「Token 过期」「二维码不含敏感明文」三条核心不变量。已改为解析**真实源码与真实生产 DDL** 的静态守卫(5 例)。
|
||||
- **T3 表集合**:`activity_registrations` 此前不在 `EntityMigrationParityTest` 的必选集合;新增 `activity_staff_assignments`。二者均移入 `REQUIRED_IN_TEST_SCHEMA`。
|
||||
|
||||
另外同步了 `MigrationValidationTest` 的迁移基线(39 → 40):该守卫会拒绝任何超出基线的新迁移文件,是设计内的收敛机制。
|
||||
|
||||
> 附带教训:新实体 `ActivityStaffAssignment` 最初继承了 `BaseEntity`,而 V040 表是 `(activity_id, operator_id)` 复合主键(无 id / updated_at / deleted_at)。MyBatis-Plus 会对非 null 字段一律写入列清单 → 生产每次 insert 都撞 `column does not exist`。已改为不继承 `BaseEntity`,由 `EntityMigrationParityTest` 当场拦下。
|
||||
|
||||
---
|
||||
|
||||
## 四、证据
|
||||
|
||||
**定向测试**:43 tests / 0 failures(`ActivityPhase15Test` 21 + `CheckinServiceTest` 5 + `EntityMigrationParityTest` 6 + `ActivityConstraintGuardTest` 11)
|
||||
|
||||
**负向验证**(注入真实缺陷 → 守卫必须变红,随后全部还原):
|
||||
|
||||
| 注入 | 变红的用例 |
|
||||
|---|---|
|
||||
| ① 生成签到码时写回 `TOKEN_STATE_USED`(还原 D1) | `generatedTokenCanBeScanned` / `duplicateScanIsIdempotent` / `checkinTokenDoesNotCrossActivities` + 守卫 `generateMustNotMarkTokenAsUsed` |
|
||||
| ② 报名退回 `INSERT` 不复用记录(还原 D9) | `canReRegisterAfterCancel` / `canReRegisterAfterReject`(DuplicateKeyException) |
|
||||
| ③ 容量分组不参与扣减(还原 D14) | `capacityGroupIsEnforced` / `cancelReleasesCapacityGroup` |
|
||||
|
||||
共 8 条精准变红,归因与注入一一对应;还原后确认工作区无 `NEGATIVE-VERIFICATION` 残留。
|
||||
|
||||
**全量回归**:`Tests run: 474, Failures: 0, Errors: 0, Skipped: 3` / `BUILD SUCCESS`(基线 450 → 474,净 +24)
|
||||
|
||||
**前端**:admin-web `vue-tsc --noEmit` 0 error;`vite build` 通过(1737 modules transformed,新增 `ActivityCheckinView` 已打包)
|
||||
|
||||
---
|
||||
|
||||
## 五、变更清单
|
||||
|
||||
**新增文件**
|
||||
- `backend/src/main/resources/db/migration/V040__add_activity_staff_assignments.sql`
|
||||
- `backend/src/main/java/.../activity/entity/ActivityStaffAssignment.java`
|
||||
- `backend/src/main/java/.../activity/mapper/ActivityStaffAssignmentMapper.java`
|
||||
- `backend/src/test/java/.../activity/ActivityPhase15Test.java`
|
||||
- `admin-web/src/modules/activity/ActivityCheckinView.vue`
|
||||
|
||||
**修改文件**
|
||||
- `CheckinService.java`(重写签到流程)
|
||||
- `ActivityService.java`(重报名复用、分组扣减、报名窗口、审核/取消原子化、数据范围)
|
||||
- `ActivityRegistrationMapper.java`(+`findByActivity` / `reuseIfCapacityAvailable` / `checkinIfNotCheckedIn` / `cancelIfActive` / `rejectIfPending`)
|
||||
- `ActivityCapacityGroupMapper.java`(+`findByActivityId` / `incrementIfAvailable` / `decrementIfPositive`)
|
||||
- `schema-h2.sql`(报名表 UNIQUE + 两个 CHECK、新增指派表)
|
||||
- `CheckinServiceTest.java`(3 条假绿 → 5 条真实守卫)
|
||||
- `ActivityConstraintGuardTest.java`(+2 条约束漂移守卫)
|
||||
- `EntityMigrationParityTest.java`、`MigrationValidationTest.java`(基线)
|
||||
- `admin-web/src/router/index.ts`、`MainLayout.vue`(签到路由与导航)
|
||||
- `miniapp/services/activityService.js`(+`cancelRegistration`)
|
||||
|
||||
---
|
||||
|
||||
## 六、遗留(供后续阶段)
|
||||
|
||||
1. **`my-activities`(U30)仍是占位骨架**:只有 `onLoad/onShow` 空实现,用户无法查看报名状态或自助取消(service 层已备好 `cancelRegistration`)。
|
||||
2. **签到码以"复制文本"形式下发**:小程序 U31 提供的是复制按钮而非二维码;后台签到台为手动粘贴。若需扫码枪/摄像头扫码,需另加扫码输入方式。
|
||||
3. **容量分组归属规则较粗**:当前按 `group_code` 与性别匹配,未匹配到分组时不施加约束;`ruleDefinition`(JSON)尚未参与判定。
|
||||
4. **`activity.checkin` 与指派的联动**:目前"有指派记录者受限、无指派记录者不受限",若后续要求所有签到人员必须显式指派,需改为强制校验。
|
||||
|
||||
---
|
||||
|
||||
**Phase 15 已关闭。Phase 16(活动互选与双方开启沟通确认)未自动进入,等待用户确认。**
|
||||
+19
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
> **2026-09-17 当前有效结论:`V1.1 INCREMENTAL RECOVERY PHASE 14 COMPLETE / GIT CLEAN`。**
|
||||
>
|
||||
> 阶段 0(在途收口)、阶段 1(小程序 C 组 + discover 筛选重设计)、阶段 2(管理端 Vue 新框架适配)、阶段 3(CapabilityService 独立化)、阶段 4(双端总验收)全部完成。三端构建通过、**13/13 契约全绿**、核心 11 页面**全部 TS-only(11/11)**。**UI 重设计首批 11 页已于 2026-09-16 通过用户验收(结论:基本达标)**;`/me/*` 前后端契约同轮收敛,17 个 404 调用已恢复。**Phase 08(Like / Match / Block)、Phase 09(Text Chat)、Phase 10(Image & Chat Safety)、Phase 11(Notification)、Phase 12(Relationship Progress)、Phase 13(公益红娘转介)、Phase 13A(婚恋咨询与婚前辅导)、Phase 14(多类型公益活动)复验已关闭**,八轮共修复 48 处真实缺陷,并各自补齐测试保真度与守卫。**Phase 15 需用户确认后启动。**
|
||||
> 阶段 0(在途收口)、阶段 1(小程序 C 组 + discover 筛选重设计)、阶段 2(管理端 Vue 新框架适配)、阶段 3(CapabilityService 独立化)、阶段 4(双端总验收)全部完成。三端构建通过、**13/13 契约全绿**、核心 11 页面**全部 TS-only(11/11)**。**UI 重设计首批 11 页已于 2026-09-16 通过用户验收(结论:基本达标)**;`/me/*` 前后端契约同轮收敛,17 个 404 调用已恢复。**Phase 08(Like / Match / Block)、Phase 09(Text Chat)、Phase 10(Image & Chat Safety)、Phase 11(Notification)、Phase 12(Relationship Progress)、Phase 13(公益红娘转介)、Phase 13A(婚恋咨询与婚前辅导)、Phase 14(多类型公益活动)、Phase 15(活动报名、审核与签到)复验已关闭**,九轮共修复 64 处真实缺陷,并各自补齐测试保真度与守卫。**Phase 16 需用户确认后启动。**
|
||||
|
||||
最后更新: 2026-09-17 — 分支 `main`(`feat-ui-v11` 保留为冗余锚点)
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
| 1.1.0-rc.4 | 2026-09-16 | Phase 13 复验关闭(公益红娘转介,修复 7 处缺陷);新增 V038 扩展 matchmaker CHECK 白名单;全量回归 **391 tests** 全绿 |
|
||||
| 1.1.0-rc.5 | 2026-09-17 | Phase 13A 复验关闭(婚恋咨询与婚前辅导,9 处缺陷 + 4 处测试基建缺陷);新增 V039;全量回归 **420 tests** 全绿 |
|
||||
| 1.1.0-rc.6 | 2026-09-17 | Phase 14 复验关闭(多类型公益活动,11 处后端缺陷 + 3 处前端契约缺陷 + 2 处测试保真度缺陷);新增 `ActivityManagementView` 动态表单;全量回归 **450 tests** 全绿 |
|
||||
| 1.1.0-rc.7 | 2026-09-17 | Phase 15 复验关闭(活动报名/审核/签到,16 处缺陷:含**签到码一生成即作废**、**取消后永远无法再报名**两处必崩;3 处测试保真度);新增 V040 `activity_staff_assignments` 与 `ActivityCheckinView` 签到工作台;全量回归 **474 tests** 全绿 |
|
||||
|
||||
---
|
||||
|
||||
@@ -204,6 +205,23 @@
|
||||
| 测试:`ActivityPhase14Test`(23)+ `ActivityConstraintGuardTest`(9,解析真实 DDL 与前端源码) | ✅ 新增 |
|
||||
| 全量回归 **450 tests 全绿** | ✅ |
|
||||
|
||||
### Phase 15 — 活动报名、审核与签到 ✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
|
||||
| 任务 | 状态 |
|
||||
|------|------|
|
||||
| **D1 必崩**:签到码一生成即作废(`generate` 写 `"used"` → 扫码 100% 失败)→ 改为 `issued` | ✅ |
|
||||
| 重复签到:原子条件更新 `checkinIfNotCheckedIn` + 幂等返回 `alreadyCheckedIn` | ✅ 新增 |
|
||||
| **D9 必崩**:取消/拒绝后重报名撞 `UNIQUE(activity_id,user_id)` → 复用记录 `reuseIfCapacityAvailable` | ✅ |
|
||||
| 审核/取消原子化:`rejectIfPending` / `cancelIfActive`;取消补审计日志 | ✅ |
|
||||
| 后台报名列表含 pending(原只查 approved,审核页无待审项) | ✅ |
|
||||
| 报名窗口 `registration_start_at` / `registration_end_at` 生效 | ✅ 新增 |
|
||||
| 容量分组真正参与扣减(`incrementIfAvailable` / `decrementIfPositive`) | ✅ 新增 |
|
||||
| 计划项③:V040 `activity_staff_assignments` + 签到/审核数据范围校验(INV-020) | ✅ 新增 |
|
||||
| Admin:`ActivityCheckinView.vue` 签到工作台 + `/activities/checkin` 路由与导航 | ✅ 新增 |
|
||||
| Miniapp:`cancelRegistration` 封装(后端端点存在但前端无入口) | ✅ |
|
||||
| 测试库补齐报名表 UNIQUE + 两个 CHECK;两表移入必选集合;迁移基线 39→40 | ✅ |
|
||||
| 测试:`ActivityPhase15Test`(21)+ `CheckinServiceTest` 假绿改真实守卫(5)+ 约束守卫(2) | ✅ 新增 |
|
||||
| 全量回归 **474 tests 全绿** | ✅ |
|
||||
|
||||
### Phase 13A — 公益婚恋咨询与婚前辅导(核心链路)✅ 已完成(2026-09-17 KEEP-VERIFY/EXTEND 复验通过)
|
||||
| 任务 | 状态 |
|
||||
|------|------|
|
||||
|
||||
@@ -400,12 +400,20 @@ D2——`RelationshipService.createMatch` 不写 episode/lastActivityAt,与 `M
|
||||
|
||||
**Files:** activity registration、checkin 服务和 U29~U32 页面。
|
||||
|
||||
- [ ] 回归报名、审核、取消、签到码、重复签到和名额并发。
|
||||
- [ ] 增加非 matchmaking 活动和 capacity group 场景测试。
|
||||
- [ ] 服务站操作员只能操作指定活动或站点任务。
|
||||
- [x] 回归报名、审核、取消、签到码、重复签到和名额并发。
|
||||
- [x] 增加非 matchmaking 活动和 capacity group 场景测试。
|
||||
- [x] 服务站操作员只能操作指定活动或站点任务。
|
||||
|
||||
**Gate:** 重复请求和并发报名不超额;签到不可跨活动复用。
|
||||
|
||||
> **2026-09-17 复验关闭**:修复 16 处缺陷(8 处签到 + 5 处报名/审核/取消 + 1 处容量分组 + 2 处前端契约)
|
||||
> + 3 处测试保真度缺陷。两处必崩:**D1 签到码一生成即作废**(`generateCheckinToken` 写 `"used"`,
|
||||
> 扫码 100% 失败)、**D9 取消后永远无法再报名**(撞生产 `UNIQUE(activity_id,user_id)`,
|
||||
> 测试库缺该约束故零覆盖)。新增 V040 `activity_staff_assignments` 落实签到数据范围(INV-020)。
|
||||
> 一轮负向验证:3 处注入 → 8 条用例精准变红并还原。全量回归 **474 tests 全绿**(基线 450)。
|
||||
> 报告:`docs/Phase-15-V11-Recovery-Completion-Report-2026-09-17.md`
|
||||
> **Phase 16 未自动进入,等待用户确认。**
|
||||
|
||||
### Phase 16:活动互选与双方开启沟通确认 — REFACTOR
|
||||
|
||||
**Files:** activity_mutual、relationship、messaging 模块及 activity-mutual 页面。
|
||||
|
||||
Reference in New Issue
Block a user