K8-DRYRUN: ĐANG CHẠY — B0 PASS (backup 26,6MB + roster LIVE + login admin OK); B1.. đổ ruột liên tục bên dưới # sub-k8-dryrun — K8 dry-run E2E toàn trình (S168, 2026-08-01) > Mandate owner @S168 (verbatim): *"Chạy dry-run hết luôn đi rồi tao giao tiếp plan khác"*. > Kịch bản = spec-cụm3 §③ K8 + bảng B0-B16 (`sub-invest-fable-b2-cum3.md` K8.1) + **vá-9..15 spec-final THẮNG nền**. > 🔴 Vá-12 owner-ratified @S164 *"tạo PE Test SOLUTION-PE-1,2,3… không test trên phiếu thật"* ⇒ **bộ test RIÊNG** (Project+NCC+gói ZZTEST/SOLUTION-PE-{n}), **KHÔNG đụng `PE/2026/A/049`** — câu giờ-G K8.2 của bản nền coi như ĐÃ trả. > Người bấm mọi bước hôm nay = **admin (duyệt thay — SignedByUserId track, banner "Admin duyệt thay" by-design)**; cột "Ai (thật)" trong form = roster LIVE để buổi chạy với người thật dùng lại. ## B0 — PRE-FLIGHT (fail-closed) — ✅ PASS 16:2x-16:3x +07 - (i) **Backup prod:** `C:\Backups\SolutionErp\SolutionErp_preK8_S168.bak` — 27.877.888 B @ 2026-08-01 16:28 (BACKUP DATABASE 3393 pages OK). *(Script `scripts/backup-sql.ps1` default `D:\` — VPS KHÔNG có ổ D ⇒ dùng `C:\Backups`; default ĐÃ VÁ `C:\` @S168 cùng lượt.)* - (ii) **Workflow LIVE (sqlcmd -E; ⚠️ `$env:PROD_DB_PASSWORD` KHÔNG tồn tại cả 3 scope trên VPS — persona-note stale cùng lớp F-9):** - type-1 PE: `QT-DN-V2-001` active+selectable · 3 trạm (P1: 4NV L1 + tra.bui L2[SkipToFinal,Delete] · P2: 4NV L1 + **chuong.phan L2 [Finalize=1,SkipToFinal,Delete]** · P3: truong.nguyen [SkipToFinal]). - type-10 KHKK: **đủ 8 nhóm N1-N8 active**; `KHKK-N4` 3 trạm 11 người (Cung ứng: 4NV+tra.bui · Kiểm soát CP: 4NV+**chuong.phan [Finalize=1]** · BGĐ: truong.nguyen) — khớp anchor OG-3/OG-9. - type-3 HĐ: `QT-HD-V2-001` active — **1 trạm 1 người: binh.le (Bước 1 - Phòng CCM)**. - (ii-b) Catalog: `ContractCatalogEntries` = **86** dòng; nhóm-4 mẫu B1-01 Đá · B1-02 Cát · B1-03 Cọc tràm · B1-04 Bê tông · **B1-05 Xi măng (chọn cho line test)** · B1-06 Thép. - (iii) Dữ liệu test sẵn có: Projects ZZTEST = **0** · Suppliers TEST = **0** ⇒ TẠO MỚI qua API (GĐ0 dưới). Contracts prod = **0** (HĐ dry-run sẽ là HĐ ĐẦU TIÊN trên prod — seq cháy thuộc cặp prefix TEST, vô hại data thật). - (iv) **Dặn team:** em KHÔNG có kênh Zalo/email — thay bằng ZZTEST-prefix mọi bản ghi + mục này để anh nhắn team *"notification phiếu ZZTEST trong hôm nay — bỏ qua"*. KHAI trade-off, không im. - (v) Login API prod: `POST /api/auth/login` admin OK (accessToken 468c — field `accessToken` đúng bài S160). ## B0-FORM 14 dòng {bước · người THẬT (roster LIVE) · tài khoản · ai bấm hôm nay} — vá-9 fail-closed | B | Ai (thật, theo roster LIVE) | Tài khoản | Hôm nay | |---|---|---|---| | B1-B3 | BCH drafter (đại diện Cung ứng: Nguyễn Văn Duy) | duy.nguyen@solutions.com.vn | admin (tạo thay) | | B4 | Trạm-1 PE/KHKK — 1 trong {duy.nguyen · binh.lethanh · long.chau · phuong.nguyen} + L2 tra.bui | (4+1 tài khoản trên) | admin duyệt thay | | B5 | Trạm-2 — 1 trong {luu.tran · nguyen.ho · binh.le · truong.letrandang} | (4 tài khoản) | admin duyệt thay | | B6 | **TP.CCM Phan Văn Chương (Finalize)** | chuong.phan@solutions.com.vn | admin duyệt thay (tick finalize) | | B7 | CEO Nguyễn Văn Trường (nhánh B) | truong.nguyen@solutions.com.vn | admin duyệt thay | | B8 | BCH/Admin kiểm khóa | — | admin | | B9 | Người có `Contracts.Create` (câu III default: Drafter/Procurement/Admin — seeder K7 CanCreate=3) | — | admin | | B10 | Người bấm B9 | — | admin | | B11 | Approver HĐ: **Lê Văn Bình** (QT-HD-V2-001 trạm duy nhất) | binh.le@solutions.com.vn | admin duyệt thay | | B12 | HRA/CCM (HardCopyActorRoles) | — | admin | | B13 | Bất kỳ + Admin (mở cây) | — | admin | | B14 | Lead chốt sổ | — | lead | ⇒ 14/14 dòng CÓ CHỦ — fail-closed ĐẠT (không dòng nào trống). ## Nhật ký bước (đổ ruột liên tục — ID ghi TẠI CHỖ cho rollback vá-11/13) ### 🔴 PHÁT HIỆN TRƯỚC GIỜ CHẠY — BLOCKER toàn trình: Lines-editor KHÔNG TỒN TẠI (vá tại chỗ @S168) Truy vết trước khi bấm B1 (đúng tinh thần "K8 lộ wave thiếu"): - `ContractSigningPlanFeatures.cs` auto-gen line mồi `CatalogEntryId = null` + comment HẸN *"Người soạn gán sau qua `UpdateContractSigningPlanLineCommand`"* — **command đó chỉ tồn tại TRONG COMMENT** (grep toàn src + FE = 0 impl, 0 route, 0 call). - `ContractSigningPlanWorkflowService.SubmitAsync` (vá-5) **CHẶN THẬT** line null: `"Còn dòng chưa gán hạng mục…"` + đếm-so-khớp nhóm. - FE `KhkkDetailPage` cột Hạng mục tự khai *"Đường GÁN (Lines-editor) = K4b"* — nhưng K4b THẬT ship việc khác (`88e7ecf` = nối `?group=` sidebar, đo `git show --name-only`). ⇒ mảnh rơi giữa build-order. - Hệ quả nếu không vá: **MỌI phiếu KHKK tạo sau K2 kẹt Nháp vĩnh viễn** — dry-run chết ở B3. Đây chính là chỗ cicd-K2 khai *"mục-4 chân-lý-rỗng — đo lại khi K8 đẻ phiếu thật"*. **Vá @S168 (BE + FE ×2 app + 3 test):** `UpdateContractSigningPlanLineCommand(PlanId, LineId, CatalogEntryId)` handler (EnsureDraftEditable + fail-fast entry sống/đúng-nhóm 409 + denorm `TenHangMuc` + changelog Line) · route `PUT /contract-signing-plans/{id}/lines/{lineId}` policy `KeHoachKyKet.Update` · FE select gán tại bảng (Nháp/TraLai, khoá dòng đã bắc cầu HĐ, options lọc `?approvalGroup=`) mirror SHA-pair `21e0ca0507d4` ×2 app · 3 Fact (dương gán→submit-QUA · âm khác-nhóm 409 · âm phase). Gate + commit riêng trước khi chạy chuỗi. ### GĐ0 — dựng bộ test (Project + Supplier + WorkItem + PE `SOLUTION-PE-{n}`) (đang chạy — điền dưới)