Files
solution-erp/.claude/workflows/runs/2026-07-29-S161-khkk-w3-duyet/cicd-verify-df52fa0.md
2026-07-29 22:46:27 +07:00

174 lines
9.7 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.

# CI/CD verify — `df52fa0` (W3 KHKK — duyệt 3 trạm, 0 migration)
> Ghi TỪNG MỤC ngay khi có bằng chứng (đối-sách #53: file = sản phẩm chính, return chỉ là tóm tắt).
> Agent: cicd-monitor · Session S161 W3 · Ngày 2026-07-29
---
## §0. Grounding — commit + push
| Mục | Giá trị |
|---|---|
| SHA | `df52fa0cd09e13a533724c35f4e6bed44afeb42d` |
| Subject | `[CLAUDE] App+Infra+Api+FE-User+FE-Admin+Tests: W3 KHKK — duyet 3 tram OR-of-N + finalize chot gia (test-before 6 RED->GREEN)` |
| Author / Date | pqhuy1987 · Wed Jul 29 22:33:11 2026 +0700 |
| `git log origin/main..HEAD` | **RỖNG** ⇒ đã push |
| Files changed | **11** (+2370 / 6) |
| Breakdown | BE 4 (Controller · IContractSigningPlanWorkflowService · DependencyInjection · ContractSigningPlanWorkflowService) · FE 6 (2 app × {KhkkDetailPage, KhkkWorkflowPanel, types/khkk}) · Tests 1 (`ContractSigningPlanApprovalTests.cs`) |
| paths-ignore (gotcha #41) | KHÔNG khớp glob nào trong 7-entry ⇒ **CI PHẢI chạy** ✅ |
| Migrations trong diff | **0 file** `*Migrations*` ⇒ khai báo 0-mig (verify ở §2) |
**File MỚI trong commit này (quan trọng cho §3):**
`fe-{admin,user}/src/pages/khkk/KhkkWorkflowPanel.tsx`**NEW-FILE-IN-THIS-COMMIT**
(`git cat-file -e df52fa0~1:…``exists on disk, but not in df52fa0~1`), 423 dòng/app,
SHA256 mirror KHỚP 2 app: `2b64144ef6e8567d6997c0e19b9686c083080216510a4cd8da6157a80f584817`.
⟹ Mọi chuỗi ĐỘC-QUYỀN của file này **phải VẮNG trong bundle CŨ** (build từ `6cbc6ad9` W2) và
**có mặt trong bundle MỚI** → control ÂM theo trục THỜI GIAN, mạnh hơn control âm hash.
---
## §1. CI run — PASS ✅
| Mục | Giá trị |
|---|---|
| Run | **#429** (task id **542**) |
| head_sha | `df52fa0c` ✅ khớp (key theo SHA, KHÔNG theo run_number) |
| status | **success** (`conclusion:None` — Gitea `tasks` không populate, tin `status` per baseline) |
| created → updated | 22:33:19 → 22:39:13 = **5m54s** (nằm trong dải ~5m40s6m của arc S159/S161) |
| URL | https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/429 |
**Test gate (đọc web-UI log `…/runs/429/jobs/0/logs`, 17.900 B) — đối chiếu TÁCH-PHẦN:**
```
:29 Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45, Duration: 147 ms - SolutionErp.Domain.Tests.dll
:47 Passed! - Failed: 0, Passed: 535, Skipped: 0, Total: 535, Duration: 1 m 36 s - SolutionErp.Infrastructure.Tests.dll
```
| | Kỳ vọng | Đo | KL |
|---|---|---|---|
| Domain | 45 | **45** | ✅ |
| Infrastructure | 535 | **535** | ✅ |
| **TỔNG** | **580** | **580** | ✅ |
| Failed / Skipped | 0 / 0 | **0 / 0** | ✅ |
Delta so run #427 (566 = 45D+521I): **+14 Infra** — commit khai "test-before 6 RED→GREEN";
file test đổi = 1 (`ContractSigningPlanApprovalTests.cs`). 6 là số **kịch bản** lead khai, 14 là số **test-case**
thực thi (Theory/InlineData nở) ⇒ không mâu thuẫn, và gate-580 đúng con số đề bài yêu cầu.
---
## §2. 0-migration invariant
_(đang cập nhật)_
---
## §3. Bundle marker
### §3.a Chọn marker theo LUẬT ĐỘC-QUYỀN (#426)
Trước khi nhận 1 chuỗi làm chứng-cứ, grep repo-wide xác nhận nó ĐỘC QUYỀN cho thứ cần chứng.
Đo bằng `grep -roF <s> fe-admin/src fe-user/src src | wc -l` (occurrence) + `grep -rlF` (file list):
| Ứng viên | occurrence | file chứa | Kết luận |
|---|---|---|---|
| `Không phải lượt bạn` | 5 | +`{2 app}/components/pe/PeWorkflowPanel.tsx` +`PurchaseEvaluationWorkflowService.cs` | ❌ **NHIỄM PE** — loại |
| `Đến lượt bạn duyệt` | 4 | +`{2 app}/components/pe/PeWorkflowPanel.tsx` | ❌ **NHIỄM PE** — loại |
| `chỉ người trên mới thao tác cấp này` | 2 | CHỈ `{2 app}/pages/khkk/KhkkWorkflowPanel.tsx` | ✅ ĐỘC QUYỀN, **1 lần/app** |
| `Cấp hiện tại chỉ người được phân công` | 6 | CHỈ `{2 app}/pages/khkk/KhkkWorkflowPanel.tsx` | ✅ ĐỘC QUYỀN, **3 lần/app** |
| `Trả lại người soạn sửa` | 4 | CHỈ `{2 app}/pages/khkk/KhkkWorkflowPanel.tsx` | ✅ ĐỘC QUYỀN, **2 lần/app** |
> 🔑 Đúng bài học #426 lặp lại LIVE: 2/5 ứng viên "nghe rất KHKK" thực ra dùng chung với PE panel.
> Nếu áp máy móc `Đến lượt bạn duyệt` thì bundle CŨ đã có sẵn ⇒ PASS GIẢ.
**Trap #425 (comment bị esbuild strip) — đã loại trừ:** cả 3 marker giữ lại đều nằm ở **mã CHẠY**,
không phải comment: `chỉ người trên…` = JSX text (`<div className="mt-0.5">⚠ Không phải lượt bạn — …</div>`) ·
`Cấp hiện tại chỉ người được phân công…` = 3 × `title={…}` string literal ·
`Trả lại người soạn sửa` = `dialogTitle` + 1 × `title=` (2 string literal).
### §3.b Hiệu-chuẩn máy đo TRƯỚC khi dự đoán bội-số (chống bẫy minifier-dedupe)
Bội-số chỉ dùng được nếu minifier KHÔNG gộp literal trùng. Đo bằng chuỗi **đã ship** `bg-slate-200 text-slate-500`:
| App | source (HEAD) | trừ 1 lần trong file MỚI ⇒ kỳ vọng bundle CŨ | đo bundle CŨ | Khớp |
|---|---|---|---|---|
| fe-admin | 4 (`PeWorkflowPanel`×2 · `EmployeesListPage`×1 · `KhkkWorkflowPanel`×1 MỚI) | **3** | **3** | ✅ |
| fe-user | 4 (cùng phân bố) | **3** | **3** | ✅ |
**KHÔNG dedupe** — literal trùng được giữ nguyên bội-số ⇒ dự đoán SỐ CHÍNH XÁC là hợp lệ (không phải chỉ "≥1").
### §3.c Control ÂM theo TRỤC THỜI GIAN (đo TRƯỚC deploy, bundle W2 `6cbc6ad9`)
Bundle cũ: admin `index-D4uy3yxF.js` (1.709.294 B) · user `index-C1ASe0K1.js` (1.625.473 B), cả 2 `ct=application/javascript`.
| Chuỗi | admin CŨ | user CŨ | Ý nghĩa |
|---|---|---|---|
| `chỉ người trên mới thao tác cấp này` | **0** | **0** | ✅ vắng đúng (file chưa tồn tại ở W2) |
| `Cấp hiện tại chỉ người được phân công` | **0** | **0** | ✅ vắng đúng |
| `Trả lại người soạn sửa` | **0** | **0** | ✅ vắng đúng |
| `Không phải lượt bạn` (PE panel, chứng MÁY ĐO SỐNG) | **1** | **1** | ✅ grep bắt được tiếng Việt trong bundle ⇒ 0 ở trên là "vắng THẬT", không phải "máy đo hỏng" |
> 🔑 Đây là control ÂM mạnh hơn hash-bịa: nó chứng minh **trước deploy chuỗi KHÔNG có**, nên nếu sau deploy
> chuỗi XUẤT HIỆN đúng bội-số ⇒ chính commit này đã lên đĩa, không thể do bundle cũ hay cache.
### §3.d DỰ ĐOÁN (chốt TRƯỚC khi đo bundle mới)
| Chuỗi | admin MỚI | user MỚI |
|---|---|---|
| `chỉ người trên mới thao tác cấp này` | **1** | **1** |
| `Cấp hiện tại chỉ người được phân công` | **3** | **3** |
| `Trả lại người soạn sửa` | **2** | **2** |
| `bg-slate-200 text-slate-500` (hiệu-chuẩn) | **4** (3→4) | **4** (3→4) |
### §3.e SỐ ĐO bundle MỚI — **4/4 dự đoán KHỚP TỪNG ĐỒNG** ✅
Bundle mới (rotate **4/4**): admin js `D4uy3yxF`→**`BPWQQe4q`** · css `9okZenCM`→**`KS0kL7bG`** ·
user js `C1ASe0K1`→**`DV3fEpOw`** · css `BfN7IuxJ`→**`Cpp9Qc7C`**.
Size: admin 1.709.294 → **1.720.297** (+11.003 B) · user 1.625.473 → **1.636.476** (+11.003 B) —
**delta BẰNG NHAU 2 app**, khớp việc file panel là MIRROR SHA256 identical. Cả 2 `ct=application/javascript`.
| Chuỗi | Dự đoán | admin đo | user đo | KL |
|---|---|---|---|---|
| `chỉ người trên mới thao tác cấp này` | 1 / 1 | **1** | **1** | ✅ |
| `Cấp hiện tại chỉ người được phân công` | 3 / 3 | **3** | **3** | ✅ |
| `Trả lại người soạn sửa` | 2 / 2 | **2** | **2** | ✅ |
| `bg-slate-200 text-slate-500` (hiệu-chuẩn) | 4 / 4 | **4** | **4** | ✅ |
| `Không phải lượt bạn` (PE 1 + KHKK 1) | 2 / 2 | **2** | **2** | ✅ bonus nhất-quán |
> Cả 3 marker đi từ **0 (bundle W2) → đúng bội-số nguồn (bundle W3)**, và chuỗi hiệu-chuẩn đi **3→4**
> đúng bằng +1 lần xuất hiện trong file mới ⇒ không chỉ "có ship", mà ship **ĐÚNG BẤY NHIÊU**, không thừa không thiếu.
### §3.f Control ÂM 2 tầng (bundle cũ phải BIẾN MẤT khỏi đĩa)
| Phép | code | content-type | size | KL |
|---|---|---|---|---|
| admin hash **CŨ** `index-D4uy3yxF.js` | 200 | `text/html` | 900 | ✅ đã bị ghi đè |
| user hash **CŨ** `index-C1ASe0K1.js` | 200 | `text/html` | 876 | ✅ đã bị ghi đè |
| admin hash **BỊA** `index-ZZZZ9999.js` | 200 | `text/html` | **900** | ✅ trùng khít hash cũ |
| user hash **BỊA** `index-ZZZZ9999.js` | 200 | `text/html` | **876** | ✅ trùng khít hash cũ |
⟹ hash CŨ trả về **byte-size y hệt hash BỊA** ⇒ 200 đó là SPA-fallback `index.html`, không phải file thật
(bẫy #69/SPA-fallback). Bundle W2 đã bị xoá khỏi đĩa ⇒ deploy ghi đè THẬT.
**PHÉP 3 = PASS.**
---
## §4. Smoke + transitions THẬT — PASS ✅ [LEAD đo on-behalf]
- login admin token-468 · `POST .../00000000-…-01/transitions` body `{"action":"nonsense"}`**409** ProblemDetails "Hành động không hợp lệ" (validate-action TRƯỚC load-plan — đúng thiết kế skeleton đợt-1).
- body `{"action":"approve"}` GUID ma → **404** ProblemDetails "Không tìm thấy ContractSigningPlan" (GlobalExceptionMiddleware map đúng; endpoint transitions SỐNG prod).
---
## §5. Cờ `KeHoachKyKet` 13/13/2 — PASS ✅ [LEAD đo on-behalf]
sqlcmd prod: `KHKK_CU=13/13/2` GIỮ · MIGTOP `20260729122015_AddContractSigningPlans` GIỮ · MIGCOUNT 69 · TABLES 96 · MENU **142 GIỮ** (§2 0-mig PASS luôn tại đây).
---
END cicd-verify df52fa0 — **VERDICT=PASS 5/5** (§1+§3 cicd-monitor · §2+§4+§5 lead 2-nguồn)
---