[CLAUDE] Office: IT staff tự reassign ticket — authz Admin-OR-IT + capability endpoint (S54)
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 4m17s
- BE: GetAssignableItStaffQuery {canReassign,staff} capability endpoint + AssignItTicketHandler authz Admin-OR-dept-IT (Forbidden) + assignee-must-IT (Conflict); controller /assign hạ [Authorize(Roles=Admin)]→[Authorize] (handler enforce fine-grained data-driven)
- FE: fe-admin + fe-user ItTicketsPage SHA256-identical (reverse S53 divergence), nút gate by canReassign, dropdown từ /assignable-staff (không /users)
- Test: +13 authz guard (203→216 PASS), reviewer PASS (role-string Admin chain-verified real)
- No migration (DepartmentId reuse), no menu change
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -53,6 +53,7 @@ Test theo CODE (single source truth), document mismatch header comment + report.
|
||||
|
||||
## 📅 Recent activity (last 10 FIFO)
|
||||
|
||||
- **2026-06-08 (S54 ItTicket reassign authz — test-before-merge SECURITY) [harvested by em main — agent MEMORY write mis-landed, B2/B3]:** +13 test `tests/.../Application/ItTicketReassignAuthzTests.cs` → **203→216 PASS** (58 Domain + Infra 145→158, 0 fail). **GetAssignableItStaff (6):** Admin→CanReassign=true + 2 IT-active ordered FullName (Cao<Truong) no KT/inactive leak · IT-staff→true · non-IT non-admin (KT)→false + **empty staff (0-leak assert)** · dept-null→false+empty · inactive-IT-excluded · UserId null→Unauthorized. **AssignItTicket (7):** non-IT non-admin→**ForbiddenException** + side-effect `AssignedToUserId.Should().BeNull()` (no-mutation) · Admin+assignee∈IT→success · IT-staff+assignee∈IT→success · assignee∉IT(KT)→**ConflictException** "Người được giao phải thuộc tổ IT." · assignee inactive→NotFound · ticket not found→NotFound · null→Unauthorized. **Pattern mới: authz-capability test = seed 2-dept (IT+KT) + fake `ICurrentUser` role/dept matrix; assert canReassign flag + Forbidden/Conflict guard; empty-staff = 0-leak.** Forbidden red-able **by-contrast** (case5 non-IT vs case7 IT-staff identical-setup → chỉ khác caller-identity; rule cấm sửa prod để chứng minh RED). **No prod bug** — handler-level data-dependent authz (caller-dept vs IT-dept) = CORRECT pattern, KHÔNG phải gotcha #44 silent-403 gap (Pattern 10 reflection-regression chỉ cho static `[Authorize(Policy)]`; data-driven authz PHẢI ở handler = enforcement point, test cover tại đó). Tag [s54, it-ticket-reassign, authz-capability, forbidden-conflict-guard, test-before-merge, 0-leak].
|
||||
- **2026-06-08 (S52 P11-D Master gotcha #57 EXT) [test-before · 3 RED LIVE]:** +3 test `tests/.../Application/MasterCatalogFilteredUniqueTests.cs` (run `--filter MasterCatalogFilteredUnique` → Failed 3/Passed 0). Department+Project+Supplier `.IsUnique()` BARE (Dept cfg:18 / Proj:19 / Supp:24) chưa `[IsDeleted]=0` — cùng class gotcha #57. Mirror EXACT GROUP B HrmConfigFilteredUniqueTests: seed row `IsDeleted=true` slot Code="DUP1" → `Create{Dept|Project|Supplier}CommandHandler(db)` cùng Code → assert `NotThrowAsync` + active==1 + `IgnoreQueryFilters` all==2. **3 RED** = `DbUpdateException → SQLite Error 19 UNIQUE constraint failed: {Departments|Projects|Suppliers}.Code` (app-check `AnyAsync(Code==X)` chạy QUA HasQueryFilter → loại soft-deleted → PASS → Add+SaveChanges → DB UNIQUE bare đếm cả row xoá → throw). NOT test lỗi — REPORTED em main fix migration `.HasFilter` 3 config → flip GREEN. **⚠️ all-count PHẢI `IgnoreQueryFilters()`** (khác HRM ref dùng raw `Count(Code==X)` trên DbSet đã có HasQueryFilter → trả 1 not 2 = sai; tôi sửa = active-count plain DbSet, all-count IgnoreQueryFilters). 3 handler clean `(IApplicationDbContext db)` 1-dep. KHÔNG đụng Configuration/Domain/migration. Tag [s52, p11-d, gotcha-57, master-catalog, filtered-unique, test-before, RED].
|
||||
- **2026-06-08 (S52 P11-D Wave2 round-robin + SLA-due) [proxy by em main: agent killed session-limit trước MEMORY step]:** +9 test `ItTicketAssignSlaTests.cs` → **200 PASS** (Infra 133→142). **Round-robin:** seed Department Code="IT" + 2 user A/B `IsActive` trong IT + A có 1 ticket Open → Create → assign **B** (load 0<1); tie A=B → `ThenBy(Id)`; edge no-dept-IT / no-user-IT → unassigned; user ngoài IT hoặc `IsActive=false` KHÔNG assign. **SLA-due:** Priority Urgent→+4h / High→+8h / Medium→+24h / Low→+72h (assert `e.SlaDueAt==CreatedAt+SlaWindow[priority]`). **Regression P11-F:** create vẫn gen `^IT/\d{4}/\d{3}$`. `ItTicketSlaJob` BackgroundService SKIP unit-test (breach-query inline, khó test trực tiếp — REPORTED). Baseline 191→**200** (58 Domain + 142 Infra). Tag [s52, p11-d, round-robin, sla-due, regression].
|
||||
|
||||
|
||||
Reference in New Issue
Block a user