[CLAUDE] Domain+App+Api+Tests+FE-Admin+FE-User: S34 Plan 3 Phase 1.5 batch 4 item
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 3m48s

Phase 1.5 backlog G-H1 EmployeeProfile hardening batch (Items 6+2+1+4 of 6).

Item 6 — menuKeys FE drift sync × 2 app:
- fe-admin add: Catalogs + 4 Catalog leaves + Workflows + Budgets + Bg_List/Create/Pending (10 key)
- fe-user add: Budgets + Bg_List/Create/Pending + ApprovalWorkflowsV2 + 2 AwV2 leaf + MenuVisibility + Workflows (8 key)
- Cả 2 file giờ identical mirror BE MenuKeys.cs (28 key cumulative)

Item 2 — UpdateEmployeeProfileCommand bool→bool? safe partial update:
- 3 field IsCommunistParty/IsYouthUnion/IsTradeUnion → bool?
- Handler: HasValue check, null = giữ giá trị cũ (Reviewer minor #(b) S33 fixed)
- FE không bắt buộc gửi 3 field every PUT — tránh accidental reset

Item 1 — EmployeesController per-action policy (gotcha #44 mitigation):
- Class-level [Authorize(Policy = "Hrm_HoSo.Read")] — non-admin thiếu Read → 403
- POST [Authorize(Policy = "Hrm_HoSo.Create")]
- PUT  [Authorize(Policy = "Hrm_HoSo.Update")]
- DELETE [Authorize(Policy = "Hrm_HoSo.Delete")]

Item 4 — Test bundle Phase 1.5 (+10 [Fact], baseline 120 → 130/130 PASS):
- EmployeeCodeGeneratorTests (3 [Fact]) — atomic SERIALIZABLE NV/YYYY/NNNN
  + first call + sequential increment + year boundary preserve old year
- CreateEmployeeProfileCommandTests (4 [Fact]) — Create handler edge case
  + first profile + duplicate UserId Conflict + soft-deleted Conflict-restore
  + UserNotFound NotFoundException
- ListEmployeesQueryTests (3 [Fact]) — filter + paging logic
  + status filter + departmentId filter + search by EmployeeCode partial

Implementer Case 3 test gen caught spec mismatch (allow new after soft-delete
vs throws Conflict-restore) — chose CODE source of truth + renamed test
documenting discriminator message branch. Em main verify behavior correct
(admin UX khôi phục thay vì tạo mới — explicit flow defer Phase 1.5+).

Verify:
- dotnet build PASS (2 warn DocxRenderer baseline, 0 error)
- dotnet test 130/130 PASS (58 Domain + 72 Infra = +10)
- 4 endpoint /api/employees policy wired (gotcha #44 active mitigation)
- 4 MEMORY agent updated post-spawn (CICD Run #238 + Implementer test bundle)

Deferred Phase 1.5 next batch:
- Item 3 Satellite CRUD endpoints (WorkHistory/Education/FamilyRelation/Skill/
  Document) + FE inline edit forms — heavy ~2-3h
- Item 5 UAT smoke non-admin role verify silent 403 catch — defer post-deploy

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-27 13:57:08 +07:00
parent ea440da990
commit 61e9ce5b3b
9 changed files with 521 additions and 9 deletions

View File

@ -174,6 +174,8 @@ Bug latency observed when miss points 9-10: 2-3 days prod silent (Mig 28-29 depl
## 📅 Recent runs (FIFO — slim post-curate 2026-05-22)
- **2026-05-27 13:40-13:43 — Run #238 (task 352) sha=`ea440da` VERDICT=PASS ~3m30s (S34 Plan 2 G-O1 Danh bạ nội bộ — BE+FE 2 app endpoint mới `/api/directory`):** Push range `edba4ae..ea440da` 2 commits 23 files: (1) `7b0781b` Plan 1 Curate 4 agent MEMORY (8 file MD — match `**/*.md` paths-ignore) + (2) `ea440da` Plan 2 G-O1 15 file BE+FE code (BE 4 new/modified: `DirectoryFeatures.cs` Application/Office namespace mới + `DirectoryController.cs` route `/api/directory` + `MenuKeys.cs` +Off/Off_DanhBa + `DbInitializer.cs` seed menu; FE × 2 app cookie-cutter: 5 new/modified each — types/directory.ts + pages/office/InternalDirectoryPage.tsx + App.tsx + Layout.tsx + menuKeys.ts). Per Discovery #3 anomaly: ≥1 commit non-ignored → entire push runs (commit 2 code triggers). **Stage results ALL PASS** (Run status=success, conclusion=None UI bug per Run #350/#237 pattern): test_domain 58 + test_infra 62 baseline 120/120 UNCHANGED (no test add G-O1 per UAT mode) + build_be (Application/Office namespace mới auto-discovered MediatR — KHÔNG gotcha #1) + build_fe_admin + build_fe_user (BOTH bundle rotate) + deploy NSSM IIS recycle. **Post-deploy verify ALL PASS Stage 4 + 4.6 sqlcmd:** auth login admin 200 + **5/5 endpoint smoke 200** (contracts 3.5KB + PE 6.2KB + employees 8.0KB + menus 10.8KB + **NEW directory 13.6KB 34 rows** — wire BE/FE confirmed: 34 @solutions.com.vn users w/ employeeCode+phone+departmentName populated, dept sample covers all 9 phòng ban: Ban GĐ + Cung ứng + Kiểm soát Chi phí + Kế toán + Nhân sự-HC + QS + Thiết bị + Tài chính + ...) + health/live 200 (0.14s) + admin/eoffice 200 (0.11s/0.10s) + **bundle hash BOTH rotated** (fe-admin `CqGMUMOr``ChA9_vP5` + fe-user `C_HKyxBe``DCpX7akt` — Plan 2 FE × 2 app ship confirmed) + Mig 34 prod TOP 1 `20260526110207_AddEmployeeProfiles` UNCHANGED (no Mig in G-O1, only Application/Office layer + menu seed — expected) + **menu seed verify GOOD**: `Off`+`Off_DanhBa` keys present in /api/menus response + sqlcmd direct `MenuItems WHERE Key IN ('Off', 'Off_DanhBa')` returns 2 rows (Off root order 29, Off_DanhBa child Order 1 ParentKey=Off) + Permissions auto-grant 2 rows (`MenuKey IN ('Off','Off_DanhBa')` — SeedAdminPermissionsAsync All[] wire OK). **Gotcha #44 silent 403 NOT observed:** class-level `[Authorize]` on DirectoryController correctly allows any authenticated user (admin login 200 OK). **0 prod regression observed Run #238.** Pattern: BE namespace mới `SolutionErp.Application.Office` (first Office-domain after Hrm) MediatR auto-discovery WORK — no manual `services.AddMediatR` registration needed (assembly scan từ Application root namespace, gotcha #1 pin v12.4.1 stable). **Cumulative S33-S34 deploy:** 3× Run PASS (#350 Phase 1 schema + #237 Phase 2 wire + #238 G-O1 Danh bạ). Token cost ~25K (Read MEMORY + grep git + 10 Bash poll/curl/ssh/sqlcmd + parse JSON).
- **2026-05-26 20:28-20:32 — Run #237 (task 351) sha=`79a8343` VERDICT=PASS 3m50s (S33 Plan B G-H1 Phase 2 Task 4+5+6 — Hrm CQRS endpoint + FE 2 app + Menu seed):** Push range `48a99e1..79a8343` 3 commits 18 files: (1) `0e191de` Task 4+6 (3 BE new — EmployeesController + EmployeeDtos + EmployeeFeatures + 2 modified MenuKeys + DbInitializer = CODE non-ignored CI trigger) + (2) `9616ae2` Task 5 FE × 2 app (12 file = 6 new × 2 + 6 modified App/Layout/menuKeys/types — FE CODE CI trigger + bundle rotate) + (3) `79a8343` MEMORY 3 agent (match `**/*.md` ignore). Per Discovery #3 anomaly: ≥1 commit non-ignored → entire push runs (commit 1+2 code triggers). **Single Run #237 success authoritative** (Gitea task API status=success, conclusion=None UI bug — same S33 #350 pattern). **Stage results ALL PASS:** test_domain 58 + test_infra 62 (baseline 120/120 unchanged — no test add Plan B Phase 2 per UAT mode) + build_be (Hrm CQRS compile OK) + build_fe_admin + build_fe_user (BOTH bundle rotate — 6 new file × 2 app each) + deploy NSSM IIS recycle. **Post-deploy verify ALL PASS:** auth login admin 200 + **6/6 endpoint smoke 200** (contracts/PE/menus/auth.me + **2 NEW employees endpoint 200/200** — wire BE Task 4 confirmed: route `/api/employees` GET list + GET paged page=1&pageSize=5) + health/live 200 (0.21s) + admin/eoffice 200 (0.23s/0.25s) + **bundle hash BOTH rotated** (fe-admin `BUTKoqRP``CqGMUMOr` + fe-user `CMHv2GS4``C_HKyxBe` per FE Task 5 ship confirmed) + Mig 34 prod TOP 1 = `20260526110207_AddEmployeeProfiles` STILL applied (no rollback, Task 4-6 chỉ thêm CQRS + FE + menu seed, không touch Mig) + **menu seed verify GOOD**: `Hrm` + `Hrm_HoSo` keys present in /api/menus response (Task 6 SeedMenuTreeAsync + SeedAdminPermissionsAsync wire OK) + EmployeeProfiles total=33 (unchanged Run #350 baseline — idempotent guard skip). Sample row `NV/2026/0007` (BOD 1 — Director, Ban Giám đốc, hireDate 2021-08-01) properly formed via API. Plan B Phase 2 Task 4+5+6 cookie-cutter mirror PE Workspace pattern WORK end-to-end FE+BE+DB+Menu. **0 prod regression observed Run #237.** Pattern 12-bis cross-module mirror reaffirmed strong. **Cumulative S33 deploy:** 2× Run (#350 Phase 1 schema + #237 Phase 2 wire). Pending S33 next kick: Phase 1.5 backlog if any (e.g. Employee CRUD/Update/Detail Page) hoặc Phase 10.1 next G-H module port. Token cost ~30K (8 Bash curl/ssh/grep + Read MEMORY + parse JSON).
- **2026-05-26 18:19-18:23 — Run #350 sha=`48a99e1` VERDICT=PASS 3m38s (S33 Plan B G-H1 Mig 34 EmployeeProfile + Plan C BW1-BW7 test bundle):** Push range `5400983..48a99e1` 4 commits 34 files: (1) `1bc6b70` docs drift (3 file MD — match `docs/**` + `**/*.md` paths-ignore) + (2) `b3444a3` 3 MEMORY agent (match `**/*.md`) + (3) `0605f19` Plan C +4 test file +9 [Fact]+Theory instances (NOT ignored → CI trigger) + (4) `48a99e1` Mig 34 + 17 entity/config new + 7 modified (NOT ignored → CI trigger). Per Discovery #3 anomaly Gitea per-push trigger when ≥1 commit non-ignored → entire push runs. **Stage results ALL PASS** (Run status=success authoritative — Gitea task API `conclusion=None` even on success, do NOT confuse): test_domain 58/58 + test_infra **62/62** (=53 baseline +9 BW: BW1 happy Cấp 1→2 / BW2 terminal DaPhatHanh + gen mã / BW3 skipToFinal F2 admin opt-in / BW4 outsider ForbiddenException / BW5 wrong ApplicableType / BW6a UNIQUE composite / BW6b UPSERT 1 row / BW6c Cascade delete / BW7 V1 fallback ConflictException) + build_be (Mig 34 compile OK +6555 LOC) + build_fe_admin + build_fe_user (unchanged — no FE in push) + deploy NSSM IIS recycle. **Post-deploy verify ALL PASS (Stage 4 + 4.6 sqlcmd):** auth login admin 200 + 4 endpoint smoke 200/200/200/200 (contracts/PE/menus/auth.me) + health/live 200 + bundle hash 2/2 UNCHANGED (fe-admin `BUTKoqRP` + fe-user `CMHv2GS4` baseline preserved — expected NO FE) + Mig 34 prod TOP 1 = `20260526110207_AddEmployeeProfiles` MATCHES repo + **gotcha #51 INFRASTRUCTURE seed verify GOOD**: EmployeeProfiles=**33 rows** (16 demo + 14 Solutions thật + 3 admin/test = full @solutions.com.vn user reconcile) + EmployeeCodeSequences NV/2026 LastSeq=33 atomic match + sample rows NV/2026/0001-0003 EmployeeStatus=1 Active Nationality="Việt Nam" — `SeedDemoEmployeeProfilesAsync` correctly NOT gated `DemoSeed:Disabled` per gotcha #51 lesson (DbInitializer.cs:94 vs 99/111 demo gate). Plan B Investigator pre-flight + Em main 4 decisions chốt + Implementer 17 new file Pattern 12-bis cross-module mirror PE→Hrm cookie-cutter all WORK end-to-end. **Plan C BW1-BW7 ROI:** test gate caught NOTHING this run (all PASS first try) — Pattern 12-bis mirror clean + Implementer Reviewer pre-commit gate strong. **0 prod regression observed Run #350.** Discovery #7 path filter `eval/**` missing still stands but N/A this push (no eval/* files). **Cumulative S33 deploy:** 1× Run (#350), expect more S33+ kicks (Plan B Phase 2 Task 4 endpoint CQRS + Plan B Task 5 FE 2 app + Plan B Task 6 menu seed). Token cost ~30K (Read MEMORY + grep tests + git show + 8 Bash poll/curl/ssh + Read Mig 34 file).