Files
solution-erp/.claude/workflows/runs/2026-07-31-S164-4gd-khkk-fanout/sub-reviewer-gate-k4b.md
2026-08-01 09:59:59 +07:00

38 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

GATE-K4B: IN-PROGRESS
# Gate K4b — adversarial review wave K4b (nối `?group=` end-to-end), S166
**Mốc đo (neo lúc mở gate):** HEAD = `14ea2ea` (wal: flush 20260801T0945); commit code cuối = `7a903cf`.
Spec nói HEAD `7a903cf` — thực tế trên đĩa có thêm 6 commit `wal:` phía trên (chưa xác minh chỉ-WAL, sẽ đo).
`git status --porcelain` lúc mở gate: 18 M + 1 ?? (`tests/.../KhkkGroupMenuSeedTests.cs`).
`git diff --stat`: 541 insertions / 82 deletions / 18 files.
Scope chấm = K4b only: KhkkListPage ×2 · KhkkCreatePage ×2 · fe-user/Layout.tsx (staticMap-G1) · BE ContractSigningPlansController.cs (/deleted +group) · ContractSigningPlanFeatures.cs (ListDeleted).
K4a (MenuKeys/DbInitializer/Layout-regex/types/STATUS/test) ĐÃ qua gate K4a — không chấm lại.
---
## Ghi TỪNG MỤC (append khi đo xong, không soạn-gộp)
### M1 — Đo nền (tự chạy, không tin claim)
- `dotnet build SolutionErp.slnx`**Build succeeded, 0 Warning, 0 Error** (56.4s, tôi tự chạy).
- `npx tsc -b` fe-admin — **EXIT=0**; fe-user — **EXIT=0** (tôi tự chạy, không đọc log nền của lane).
- WAL 6 commit `7a903cf..HEAD` chỉ chạm `.claude/**` (đo `git diff --stat`) ⇒ toàn bộ code K4a+K4b nằm ở working-tree. Mốc so sánh dùng `7a903cf` là ĐÚNG về nội dung code dù HEAD ghi khác.
### M2 — Mirror 2 app (sha256, 16 ký tự đầu)
| file | fe-admin | fe-user | |
|---|---|---|---|
| `pages/khkk/KhkkListPage.tsx` | `fa4c7aa268f35eeb` | `fa4c7aa268f35eeb` | MATCH (khớp con số `fa4c7aa2` spec nêu) |
| `pages/khkk/KhkkCreatePage.tsx` | `545b4c2fe0ebae88` | `545b4c2fe0ebae88` | MATCH |
| `types/khkk.ts` | `7a99b86518948093` | `7a99b86518948093` | MATCH |
`Layout.tsx` lệch by-design (đã khai trong cả 2 file: admin `Khkk_WfView` → Designer, không mang `group`; admin không nới regex `Khkk_G*`).
### M3 — FLAG-1 (code LEAD tự viết) — BE `/deleted` + group
- Ký-pháp: `public record ListDeletedContractSigningPlansQuery(int? ApprovalGroup = null) : PagedRequest, ...`. `PagedRequest``abstract record` (`Common/Models/PagedResult.cs:15`) với 4 property `init` ⇒ trộn positional-ctor + object-initializer HỢP LỆ (record kế thừa record; nếu `PagedRequest``class` thì đã không biên dịch được). Build 0E xác nhận.
- Controller mirror List **ĐÚNG TỪNG NÉT**: `[FromQuery(Name = "group")] int? group = null` đặt ở vị trí tham số đầu, `new Query(group) { Page = …, PageSize = …, Search = …, SortDesc = … }` — cùng khuôn `List` (`:42`, anchor này ĐÚNG, tôi đếm lại).
- Handler: vế lọc `if (request.ApprovalGroup is not null) q = q.Where(p => p.ApprovalGroup == request.ApprovalGroup)` nằm **SAU** khối IDOR non-admin và **TRƯỚC** `Search` — đúng thứ tự list sống (`:755-758`). `IgnoreQueryFilters().Where(x => x.IsDeleted)` giữ nguyên phía trên ⇒ lọc nhóm không đụng vế soft-delete.
- `ContractSigningPlan.ApprovalGroup``int` **không nullable**, default `= 1` (`ContractSigningPlan.cs:41`) ⇒ so sánh `== request.ApprovalGroup` (int? vs int) dịch SQL thành so sánh giá trị, không sinh ca NULL-semantics.
- **Không có validator biên 1..8** cho `/deleted` — nhưng list SỐNG cũng không có ⇒ **consistent**, ghi nhận chứ không tính lỗi. `?group=999` = lọc rỗng (200 + `items: []`, `total: 0`), không 500. `?group=abc` = model-binding fail ⇒ 400 do `[ApiController]`. Cả hai hành vi giống hệt list sống.
- FE gửi `group` cho **cả 2 nhánh** (`KhkkListPage.tsx:124`, nằm ngoài tam-nguyên `deletedView` nên áp cho cả `/contract-signing-plans` lẫn `/deleted`) ⇒ khớp BE mới. Title/subtitle màn "Đã xóa" in tên nhóm — hết là lời nói dối vì server đã lọc thật.