wal: flush 20260729T2300
This commit is contained in:
@ -29,7 +29,8 @@ chain:
|
||||
- [x] commit W3 `df52fa0` (11 file +2.370/−6) PUSHED
|
||||
- [x] **W3 ĐÓNG — cicd VERDICT=PASS 5/5** (§1 CI 580 + §3 marker [né PASS-GIẢ "Đến lượt bạn duyệt"] = cicd · §2 0-mig/96/142 + §4 smoke transitions THẬT 409-đúng-lời + 404-ProblemDetails + §5 CỜ 13/13/2 = lead 2-nguồn). Synthesis `runs/2026-07-29-S161-khkk-w3-duyet/w3-synthesis.md`. **GĐ2 KHKK trọn vòng đời phiếu trên prod.** Tồn: mark-read chuông cũ (chờ anh) · UAT tay cần WF-type-10 + non-Admin
|
||||
- [x] gate 5-anchor W6 PASS 5/5 (content-exact 0-drift)
|
||||
- [!] wf: W6 đợt-1 `wf_e3b6a2bc-91d` ĐANG CHẠY — 1 lane BE {view per-HĐ 3-site :301/:381/:486 · inbox v2-set + nhánh ADMIN DR-4 · guard trình +PMH; CẤM đụng Reject :49-66 O-A + vùng W3 :217-394} — run-folder `runs/2026-07-29-S161-khkk-w6-duongong/`. Sau: đợt-2 test 5-PIN → reviewer (security-wave) → ship
|
||||
- [x] W6 đợt-1 `wf_e3b6a2bc-91d` XONG (#53, sub-md 3.7KB §0 + code trọn): 3 fix land (+142 ContractFeatures [3-site + inbox v2 + ADMIN tường minh] · +15 CWS guard **kèm chặn null==null lọt guard** `actorUserId is Guid`); build 0E + **suite 580/0 GIỮ** (lead đo); 0 test cũ bám 3 handler (lane verify trước)
|
||||
- [!] wf: W6 đợt-2 `wf_131c8f87-356` test-specialist 5-PIN (+2 bonus: admin-inbox DR-4 + CreatedBy-null-guard) ĐANG CHẠY, đích ≥585 → reviewer security-wave → ship
|
||||
- [ ] W5 (cầu KHKK→HĐ — cần setup WF tay TRƯỚC: type-3 + type-10 3-trạm Designer) → W7 (bản cứng 1-mốc @S161)
|
||||
- [ ] W6 → W5 → W7 theo đồ thị plan-cha (sau W3)
|
||||
- [ ] đợt-2 SAU khi wf về: test-specialist + database-agent (song song) → lead acceptance §③-B (build·test·sqlcmd 96·Down sạch·đo CỜ) → reviewer → commit/push → cicd-monitor 3-chân-kiềng
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
# sub-implementer-backend-0 — W6 Đường ống HĐ V2 (view + inbox + vai-trình)
|
||||
|
||||
> Run: `2026-07-29-S161-khkk-w6-duongong` · Spec: `.claude/workflows/runs/2026-07-29-S160-khkk-dryrun-plan/spec-wave-w6-duong-ong-hd-v2-29-07-2026.md`
|
||||
> Luật lượt này: BE-only · 0 mig · KHÔNG commit/push/slnx · KHÔNG viết test (đợt-2) · KHÔNG đụng `fe-*/` · KHÔNG đụng Reject `:49-66` (O-A) · KHÔNG đụng `ContractSigningPlan*` (KHKK W1-W3 đã ship).
|
||||
> Ghi TỪNG MỤC trong lúc làm (chống #53).
|
||||
|
||||
---
|
||||
|
||||
## §0 — ĐO TRƯỚC KHI SỬA (gate 5-anchor, đọc tươi 2026-07-29)
|
||||
|
||||
| Anchor (spec §③-A) | Đo thật | Khớp? | Nội dung |
|
||||
|---|---|---|---|
|
||||
| `ContractFeatures.cs:334-351` | `:334` `internal static List<ContractPhase> GetEligiblePhases(IReadOnlyList<string> userRoles)` … `:351` `return phases.ToList();` | ✅ | chữ ký CHỈ nhận role ⇒ không biết HĐ nào |
|
||||
| `ContractFeatures.cs:421-430` | `:421` `private static readonly Dictionary<ContractPhase, string[]> PhaseActorRoles = new()` … `:430` `[DangDongDau] = [HrAdmin],` | ✅ | 7 key, **0 key `ChoDuyet`** |
|
||||
| `ContractFeatures.cs:488-489` | `:488` `if (!isDrafter && !isEligibleByRole)` `:489` `throw new ForbiddenException("Bạn không có quyền xem HĐ này.")` | ✅ | 403 detail |
|
||||
| `ContractWorkflowService.cs:73-78` | `:73` `if (!isAdmin && !isSystem` `:74` `&& !actorRoles.Contains(AppRoles.Drafter)` `:75` `&& !actorRoles.Contains(AppRoles.DeptManager))` `:77-78` throw Forbidden "không đủ quyền trình duyệt HĐ." | ✅ | guard trình |
|
||||
| `ContractsController.cs:38-40` | `:38` `[HttpGet("inbox")]` `:39` `Inbox(CancellationToken ct)` `:40` `=> Ok(await mediator.Send(new GetMyInboxQuery(), ct));` | ✅ | endpoint inbox |
|
||||
|
||||
**Gate 5-anchor: PASS 5/5 content-exact.**
|
||||
|
||||
3 call-site `GetEligiblePhases` (grep `src/Backend`, đủ 3 — risk C "sửa chỉ 1/3"):
|
||||
- `ContractFeatures.cs:301` — `ListContractsQueryHandler` (List)
|
||||
- `ContractFeatures.cs:381` — `ListDeletedContractsQueryHandler` (ListDeleted, `IgnoreQueryFilters().Where(IsDeleted)`)
|
||||
- `ContractFeatures.cs:486` — `GetContractQueryHandler` (Detail)
|
||||
- *(`:441-442` là `PhaseActorRoles` của inbox — call-site THỨ 4 của nhánh phase, không phải của `GetEligiblePhases`)*
|
||||
|
||||
Khuôn nguồn để mirror (đọc tươi):
|
||||
- PE detail V2-approver: `PurchaseEvaluationFeatures.cs:886-898` (`AnyAsync(l => l.Step!.ApprovalWorkflowId == awId && l.ApproverUserId == uid)` + `isDraftPhase` S89)
|
||||
- PE inbox admin phase liệt tường minh: `PurchaseEvaluationFeatures.cs:731-742` (+ `ChoDuyet` `:740`)
|
||||
- PE `v2InboxIds` rỗng cho admin: `PurchaseEvaluationFeatures.cs:746-748`
|
||||
- PE `ResolveV2InboxIdsAsync` in-memory join: `PurchaseEvaluationFeatures.cs:817-852`
|
||||
- KHKK (chính tao viết W2): `ContractSigningPlanFeatures.cs:229-264` (Resolve) + `:275-283` (`ResolveUserApprovalWorkflowIdsAsync`)
|
||||
|
||||
Nền tảng đã verify TRƯỚC khi code (chống bẫy "quên lọc IsDeleted" — risk C):
|
||||
- `ContractConfiguration.cs:44` `b.HasQueryFilter(x => !x.IsDeleted)` ⇒ `db.Contracts` mặc-định ĐÃ loại HĐ xóa mềm ⇒ inbox + list + `ResolveV2InboxIdsAsync` tự an-toàn, KHÔNG cần `.Where(!IsDeleted)` tay (khác HRM).
|
||||
- `Contract.cs:23/40/46` có đủ `ApprovalWorkflowId` / `CurrentWorkflowStepIndex` / `CurrentApprovalLevelOrder`; `:16` `DrafterUserId`.
|
||||
- `BaseEntity.CreatedBy` kiểu **`Guid?`** (không phải string) ⇒ so trực tiếp với `actorUserId`.
|
||||
- `grep tests/` cho `ContractV2Pipeline|GetMyInboxQuery|ListContractsQuery|GetContractQuery` = **0 hit** ⇒ 3 handler này hiện KHÔNG có test cũ nào bám ⇒ sửa không thể phá test cũ qua đường assert; rủi ro duy nhất là compile + suite tổng.
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user