13 KiB
CICD-K3: PASS — 6/6 (§1-§5 vai đo · §6 lead đo on-behalf @S166 sau khi vai chết 2 lần)
cicd-monitor — verify deploy K3 SP-002 (15349e8)
Artifact chống #53: ghi TỪNG MỤC ngay khi có bằng chứng. Kết bằng
END ... VERDICT=. RepoD:\Dropbox\CONG_VIEC\SOLUTION\SOLUTION_ERP· push0779f2d..15349e8 main.
§0 — Tiền đề (đo LIVE trước khi deploy xong)
Commit HEAD:
15349e8ee054406797cc1d76c7bc3384c6768fc2 [CLAUDE] Contract: K3 SP-002 8 workflow nhom KHKK-N1-8 + port level-finalize + designer (0-mig) + 5 test
git log origin/main..HEAD -> (rỗng — đã push)
git diff --name-only 0779f2d 15349e8 = 26 file. Phân loại vs paths-ignore 7-glob:
- CODE (13, trigger CI): BE 6 (
ContractSigningPlansController.cs,ApprovalWorkflowV2AdminFeatures.cs,ContractSigningPlanFeatures.cs,IContractSigningPlanWorkflowService.cs,MenuKeys.cs,DbInitializer.cs,ContractSigningPlanWorkflowService.cs= 7 thực) · FE 4 (fe-admin/Layout.tsx,fe-admin/khkk/KhkkWorkflowPanel.tsx,fe-admin/system/ApprovalWorkflowsV2Page.tsx,fe-user/khkk/KhkkWorkflowPanel.tsx) · test 2 (ContractSigningPlanApprovalTests.cs,ContractSigningPlanGroupAndCatalogTests.cs) - IGNORED (13):
docs/**×2 +.claude/WAL.md+.claude/agent-memory/**×3 +.claude/workflows/runs/**×7 - 0 file
*Migrations*⇒ K3 = 0-mig (khẳng định này được đo lại ở §3).
Bundle PRE-deploy (đo LIVE 18:22:51 +07, lúc run #436 CÒN running):
admin /assets/index-DVQEwGwf.js + /assets/index-D050EVYG.css
eoffice /assets/index-CZAYiWWa.js + /assets/index-DX1FRk5n.css
Khớp ĐÚNG mốc post-K2 (#435) ghi ở sub-cicd-verify-k2.md:139-142 ⇒ mốc PRE hợp lệ, chưa bị K3 ghi đè.
PROD DB PRE-deploy (sqlcmd localhost\SQLEXPRESS, đo 18:23 +07 lúc run CÒN running):
MIGTOP=20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime
MIGCOUNT=71
WF_KHKK_N=0 <- CHƯA có workflow nhóm nào
MENU_AwV2_KhkkN=0 <- CHƯA có menu-row nào
MENU_TOTAL=143
PERM_TOTAL=1576
LEVELS_FINALIZE_ALL=2 <- cờ finalize toàn hệ TRƯỚC K3 (control nền)
⚠️ Cột PK của MenuItems là [Key] (KHÔNG phải MenuKey — MenuItemConfiguration.cs:11 b.HasKey(x => x.Key);
MENUCOLS=Key,Label,ParentKey,Order,Icon,DisplayLabel,IsVisible). Query đầu dùng MenuKey → Msg 207 Invalid column name ⇒ đã sửa, ghi lại cho lane sau.
w3wp PRE: appcmd list wp → WP "5364" (applicationPool:SolutionErp-Api), StartTime 7/31/2026 5:11:25 PM
= đúng mốc recycle của K2 (#435). ⇒ mốc-so-sánh recycle-proof cho K3.
§1 — Run Gitea Actions cho 15349e8 — ✅ PASS
API .../actions/tasks?limit=8 (anon, public repo). Match theo head_sha (KHÔNG theo run_number):
id=549 | run# 436 | 15349e8ee0 | status=success | conclusion=None | 2026-07-31T18:21:48+07 -> 18:27:59+07
- Duration 6m11s (in-band: #435 K2 = 6m12s, #434 K1 = 6m31s).
conclusion=Nonelà bình thường cho endpointtasks(memory: tinstatus). Gate test chạy TRƯỚC build/deploy ⇒success⟹ gate passed.- Control neo thứ tự: run kề dưới =
0779f2d(#435 K2) ⇒ #436 đúng là run của K3, không nhầm run. - URL: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/436
§2 — Gate CI test 614 — ✅ PASS (khớp TỪNG VẾ, không chỉ khớp tổng)
Log web-UI run #436 (.../actions/runs/436/jobs/0/logs, 18.680 B, HTTP 200). Đọc bằng bytes (memory: text-mode crash cp1252); regex Passed!.{0,120} — nới khoảng-trắng vì log dùng 2 space sau Passed!:
11:22:13Z Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45, Duration: 157 ms - SolutionErp.Domain.Tests.dll (net10.0)
11:24:47Z Passed! - Failed: 0, Passed: 569, Skipped: 0, Total: 569, Duration: 1 m 31 s - SolutionErp.Infrastructure.Tests.dll
- Domain 45 + Infra 569 = 614 — khớp kỳ vọng TÁCH-PHẦN (45/569), 0 fail / 0 skip.
- Delta vs #435 K2 (45 + 564 = 609): Domain GIỮ 45, Infra 564→569 = +5 — khớp ĐÚNG "+ 5 test" trong commit subject K3.
- Control ÂM:
grep -c 'Failed!'trên toàn log = 0 (nếu có project fail, dotnet inFailed! - Failed: N…) ⇒ 2 dòngPassed!là TOÀN BỘ project, không có project thứ 3 bị nuốt.
§3 — Top-migration prod GIỮ 20260731085624 — ✅ PASS
ssh vietreport-vps → sqlcmd -S localhost\SQLEXPRESS -d SolutionErp -U vrapp -W -h -1:
SELECT TOP 1 MigrationId FROM __EFMigrationsHistory ORDER BY MigrationId DESC
-> 20260731085624_AddKhkkApprovalGroupCatalogAndFinalizeRuntime
SELECT COUNT(*) FROM __EFMigrationsHistory
-> 71
- GIỮ NGUYÊN mốc K2 (Mig 71) — đúng kỳ vọng K3 = 0-mig. MIGCOUNT 71 = 71 ở §0 ⇒ không có mig lén nào chen vào.
- Chứng ĐỘC LẬP từ nguồn khác (không dựa vào lời khai của K3):
git diff --name-only 0779f2d 15349e8 -- '*Migrations*'= rỗng (§0) ⇒ repo cũng không có mig mới. Hai nguồn (repo ⟂ prod) khớp. - ⚠️ Đây là mục "GIỮ NGUYÊN" nên tự nó ít bit thông tin — răng đến từ control DƯƠNG cùng phiên: §4 chứng minh DbInitializer ĐÃ chạy (seed 8 workflow mới) ⇒ startup-hook sống, "mig không nhích" là vì KHÔNG CÓ mig chứ không phải vì app không khởi động lại.
§5 — Bundle ×2 — ✅ PASS (admin ROTATE · eoffice FROZEN ĐÃ DỰ ĐOÁN TRƯỚC KHI ĐO, không phải ship-fail)
| App | PRE (§0, = mốc post-K2 #435) | POST (đo LIVE 08:39 01/08) | Content-Type | Size | Last-Modified |
|---|---|---|---|---|---|
| admin js | index-DVQEwGwf.js |
index-mySTlx42.js ROTATE |
application/javascript | 1.755.009 | 31/07 11:26:24 GMT = 18:26:24 +07 |
| admin css | index-D050EVYG.css |
index-Cf3iCOOv.css ROTATE |
text/css | 86.364 | 18:26:24 +07 |
| eoffice js | index-CZAYiWWa.js |
index-CZAYiWWa.js FROZEN |
application/javascript | 1.671.584 | 31/07 11:27:23 GMT = 18:27:23 +07 |
| eoffice css | index-DX1FRk5n.css |
index-DX1FRk5n.css FROZEN |
text/css | 92.148 | 18:27:23 +07 |
Cả 4 LM nằm TRONG cửa-sổ deploy 18:21:48→18:27:59 ⇒ deploy CÓ chạm cả 4 file (gotcha #69: LM-in-window = ship-proof thật, hash-delta thì KHÔNG).
⚠️ Đính chính mốc PRE trong đề bài: spec giao việc ghi baseline admin B43R6Y17 · user NLI5umBg (@S164) —
KHÔNG khớp gì đo được. Mốc PRE dùng ở đây lấy từ §0 đo LIVE lúc #436 còn running (DVQEwGwf/CZAYiWWa),
và §0 đã đối chiếu khớp sub-cicd-verify-k2.md:139-142. Hai nguồn độc lập ⇒ dùng mốc §0, bỏ mốc trong spec.
🔑 FROZEN eoffice được GIẢI THÍCH TRỌN, dự đoán TỪ SOURCE trước khi curl (khuôn #425 comment-strip):
git diff 0779f2d 15349e8 -- fe-user= 14 dòng ± / 14 dòng đó là//comment (bộ lọcgrep -vE '^[+-]\s*//'ra 0 dòng) ⇒ 0 câu lệnh thực thi đổi.- Build strip comment — chứng trực tiếp, không suy đoán: chuỗi
đến lượt bạntrong source fe-user CHỈ nằm ở comment (:4//và:262{/* */}) ⇒ đếm trong bundle live = 0. - Không có code-splitting che mắt:
index.htmleoffice tham chiếu đúng 2 asset (index-*.js+index-*.css), và marker riêng của panelml-7 mt-1.5 space-y-1 border-l-2 border-violet-200 pl-2đếm =1 trongindex-CZAYiWWa.js⇒ file bị sửa NẰM TRONG bundle này, không lọt chunk khác. ⇒ Nguồn vào đổi 0 byte thực thi ⟹ Vite ra byte-identical ⟹ hash GIỮ. FROZEN ở đây là hệ quả bắt buộc, nếu hash ĐỔI mới đáng nghi.
🔑 Byte-marker trên bundle admin (ship-proof 2 chiều):
POS /^KhkkN[1-8]$/ admin=1 eoffice=0 (K3 Layout.tsx:183, repo-exclusive)
NEG "Chưa hỗ trợ cho quy trình Kế hoạch…" admin=0 eoffice=0 (K3 XOÁ; git show 0779f2d:…V2Page.tsx = 1 hit ⇒ PRE có, POST mất)
- POS có RĂNG: chuỗi này 0-hit toàn source repo ngoài
Layout.tsx:183(hit còn lại chỉ ở.mdrun-trace, không ship) + cross-app controleoffice=0. - NEG có RĂNG vì là string literal (minifier giữ nguyên) và đo được transition PRE→POST: bản
0779f2dchứa 1 hit, bản live 0 hit. - ❌ Marker BỊ LOẠI vì không có răng:
earlyFinalizeLocked(admin=0). Đây là tên biến local → minifier đổi tên trong MỌI trường hợp ⇒ 0-hit dù code còn hay mất ⇒ 0 bit thông tin. Ghi ra để lượt sau đừng tính nhầm nó là bằng chứng.
§4 — Seed 8 workflow KHKK-N1..N8 prod + cờ chuong.phan ×8 — ✅ PASS (dự-đoán-từ-source TRƯỚC khi đo, khớp từng đồng)
Bước 1 — ĐỌC SEEDER RỒI DỰ ĐOÁN (DbInitializer.cs:549-687 SeedKhkkGroupWorkflowsAsync), roster 3 trạm:
PRO(Level1 ×4 + Level2 tra.bui, finalize=false) · CCM(Level1 ×4 + Level2 chuong.phan, finalize=TRUE :579) · BGĐ(Level1 ×1 truong.nguyen, Level2 rỗng→bỏ :645).
⇒ Dự đoán: 8 wf × 3 step × 11 level (4+1+4+1+1) · chuong.phan 1/wf ⇒ 8 · finalize 1/wf ⇒ +8 trên nền §0 LEVELS_FINALIZE_ALL=2 ⇒ tổng phải = 10.
Bước 2 — ĐO (sqlcmd, file .sql qua scp + sqlcmd -i vì nested quoting bash→ssh→sqlcmd bị nuốt ''):
WF_KHKK_N = 8 (§0 PRE = 0 ⇒ delta 0→8) WF_ALL = 17
A|KHKK-N1..N8|type=10|act=1|sel=1|steps=3|levels=11|chuong=1|finalize=1 <- 8/8 dòng GIỐNG HỆT nhau
B_CHUONG_TOTAL_IN_KHKKN = 8 ✔ khớp dự đoán
B_LEVELS_FINALIZE_ALLSYSTEM = 10 ✔ = 2 (§0 PRE) + 8 — khớp CHÍNH XÁC, không dư không thiếu
B_LEVELS_FINALIZE_OUTSIDE_KHKKN = 2 ✔ 2 cờ cũ NGUYÊN VẸN
C_OUTOFSET_KHKKN9plus = 0
Bước 3 — SHAPE element-wise KHKK-N1 (11 dòng, khớp roster source từng email/từng Order):
step1 Phòng Cung Ứng lvOrder1 × {binh.lethanh, duy.nguyen, long.chau, phuong.nguyen} fin=0 (OR-of-N)
step1 lvOrder2 × {tra.bui} fin=0
step2 P. Kiểm soát Chi phí lvOrder1 × {binh.le, luu.tran, nguyen.ho, truong.letrandang} fin=0
step2 lvOrder2 × {chuong.phan} fin=1 <- ĐÚNG người, ĐÚNG cấp, ĐÚNG cờ
step3 Ban Giám đốc lvOrder1 × {truong.nguyen} fin=0
3 nguồn ĐỘC LẬP cùng ra 8 (khuôn tam-giác K1): (a) source-parse seeder for n=1..8 · (b) sqlcmd WF_KHKK_N=8 · (c) Serilog prod 18:27:48.888 [INF] Seeded 8 KHKK group workflows (K3 SP-002).
Control ÂM (chứng "đúng NGƯỜI, đúng TẬP", không phải quét bừa):
B_LEVELS_FINALIZE_OUTSIDE_KHKKN = 2— seeder KHÔNG đụng 2 cờ finalize có sẵn ngoài họ KHKK.C_OUTOFSET = 0— không đẻKHKK-N0/N9+ngoài miền 1..8.- 11 level/wf = ĐỦ roster ⇒ 0 email nào resolve hụt; đồng thời log KHÔNG có dòng
[WRN] … email người duyệt KHÔNG có user(:598-600) — hai đường cùng nói một điều.
Recycle-proof (BẮT BUỘC — mọi số trên đo SAU recycle):
appcmd list wp→WP "1900" (applicationPool:SolutionErp-Api);Get-Process w3wp→ PID 1900 StartTime 31/07/2026 18:27:28.- KHÁC mốc §0 (PID 5364 @ 17:11:25) ⇒ app pool ĐÃ recycle sau K2, đúng cửa-sổ deploy K3.
- Dòng ĐẦU TIÊN của
solution-erp-20260731.log=18:27:40.918 [INF] Applying migrations...(deploy xoálogs/) ⇒ chứng khởi-động-lại từ nguồn thứ hai. - PID 1900 vẫn sống lúc đo (08:39 01/08) ⇒ không có restart xen giữa; số đo phản ánh đúng bản K3.
§6 — Smoke prod — ✅ PASS `[LEAD ĐO ON-BEHALF @S166 09:0x 01/08 — vai chết lượt 2 SAU khi đo xong §1-§5;
return cuối của vai chỉ nói "Smoke is clean + route thật là kebab-case /api/contract-signing-plans" mà CHƯA ghi bằng chứng ⇒ lead đo lại 4 phép từ đầu, KHÔNG tin lời khai suông (khuôn path-4 lead-on-behalf-sau-verify)]`
GET https://api.solutions.com.vn/api/contract-signing-plans (no token) -> 401 (authz đóng đúng)
GET https://api.solutions.com.vn/api/route-khong-ton-tai-xyz -> 404 (route rác không nuốt)
GET https://eoffice.solutions.com.vn/ -> 200
GET https://admin.solutions.com.vn/ -> 200
- Ghi chú của vai (giữ lại vì ĐÚNG): route KHKK là kebab-case
/api/contract-signing-plans— đề bài lượt này ghi nhầm/api/contractsigningplans; 401 ở trên đo trên route THẬT. - Ý định dang dở của vai ("materialize 8 wf qua EF via live API") KHÔNG cần cho verdict: §4 đã chứng 3-nguồn độc lập (source-parse ⟂ sqlcmd ⟂ Serilog) + shape element-wise — thêm đường thứ 4 là dư, không phải lỗ.
END sub-cicd-verify-k3 — VERDICT=PASS 6/6 (run #436 success 6m11s · gate 614 tách-phần 45+569 +5-khớp-subject · mig GIỮ 20260731085624/71 · seed 8-wf shape-đúng-từng-email + finalize 2+8=10 + recycle-proof 5364→1900 · bundle admin ROTATE mySTlx42/Cf3iCOOv + eoffice FROZEN-dự-đoán-trước · smoke 401/404/200/200)