3.8 KiB
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 -bfe-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..HEADchỉ chạm.claude/**(đogit diff --stat) ⇒ toàn bộ code K4a+K4b nằm ở working-tree. Mốc so sánh dùng7a903cflà ĐÚ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, ....PagedRequestlàabstract record(Common/Models/PagedResult.cs:15) với 4 propertyinit⇒ trộn positional-ctor + object-initializer HỢP LỆ (record kế thừa record; nếuPagedRequestlàclassthì đã 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ônList(: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ƯỚCSearch— đú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.ApprovalGrouplàintkhô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
groupcho cả 2 nhánh (KhkkListPage.tsx:124, nằm ngoài tam-nguyêndeletedViewnên áp cho cả/contract-signing-planslẫ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.