# run — S159 arc-2 · Tổng quan pipeline 4 GĐ + điều chỉnh menu eOffice - **run-id:** `2026-07-29-S159-tong-quan-pipeline-menu` · phiên-LOGIC **L8**, window 1 (arc thứ 2 sau bookend) - **mode:** RUN-TRACE (≥3 task) · lead = **Fable 5** (anh `/model` — chủ dự án đổi, 0 caveat) - **Nguồn lệnh:** ảnh chụp eoffice + text anh 2026-07-29 (đánh dấu 3 vùng đỏ) + 4 câu AskUser đã chốt ## 🔴 OWNER CHỐT — NGUYÊN VĂN (2026-07-29, gõ vào sổ ngay để không bốc hơi — bài ring2 M-1 @S158) **Lệnh khung (text kèm ảnh):** > *"Hiện điều chỉnh cái giao diện này lại theo thế này. Đổi vai main sang Fable nhé. Hiện là tổng quy trình mình đã đi (…): GĐ1: Duyệt NCC (1→6) CEO chốt đã xong · GĐ2: Đề xuất Ký kết hợp đồng (7→12) — Có 1 bước email thì bỏ đi cũng đc, thay bằng bước bắt các phiếu từ Giai đoạn 1 → Để nối tiếp làm tiếp. Đây là 1 đầu phiếu mới hoàn toàn · GĐ3: 12→18 (Duyệt Hợp đồng — Cái này mình đã có làm trước rồi, tận dụng lại) · GĐ4 (Bước còn lại): Ký cứng hợp đồng các thứ → có thể nằm ngoài do vướng chữ ký cứng, ký nháy các thứ, có thể ko cần đủ các bước chỉ cần cho upload các file đã ký cứng lên là đc. Đọc lại nắm đủ nội dung. Xong báo lại tao trước khi làm."* **4 câu chốt (AskUser cùng ngày):** - **❶ Ranh GĐ:** *"Đúng như em map"* ⇒ GĐ2 = b.7→**12** (b.12 = chốt con số) · GĐ3 = b.**13**→18 · GĐ4 = b.19→21 + ký cứng upload · **tên phiếu/menu GĐ2 = "Đề xuất ký kết hợp đồng"** (spec đổi nhãn theo). - **❷ Tổng quan:** *"Pipeline 4 GĐ đầy đủ"* — GĐ1+GĐ3 data thật · GĐ2/GĐ4 khung "sắp triển khai". - **❸ Ẩn 3 nhóm (verbatim):** *"Chỉ nên hiển thị ở trang admin là đc → Để tao khỏi nhầm giữa cái đã public và cái đang làm"* ⇒ `IsVisible=0` cho 3 root `Hrm` `Off` `Personal` (fe-admin thấy đủ, eOffice ẩn — đúng comment entity `MenuItem.cs`). - **❹ Mở HĐ + DANH MỤC (verbatim):** *"Hiện đang phát triển → Nên cứ cho hiển thị hết để mọi người góp ý, còn duyệt NCC → thì cứ để như cũ nhé. Phần đó đã tốt rồi."* 🔴 **Ghi sổ rủi ro CÓ Ý THỨC:** lead đã nêu lỗ hổng authz HĐ (`ContractsController` `[Authorize]` trần 22 endpoint ghi + Reject-trước-guard, @S156) và rằng mở menu = phơi lỗ cho toàn bộ NV. **Anh tái khẳng định hiển thị hết, KHÔNG vá đợt này** (giữ "chỗ hợp đồng cứ từ từ"). Đây là quyết định chủ dự án, đã cảnh báo, chấp nhận trong giai đoạn phát triển. **PE (Duyệt NCC) KHÔNG chạm.** ## Ánh xạ 4 GĐ ↔ đĩa (đã báo, anh xác nhận) | GĐ | Bước | Đĩa | |---|---|---| | 1 Duyệt NCC | 1→6 | ✅ module PE (`DaDuyet=7`) | | 2 Đề xuất ký kết HĐ | 7→12 | 📋 spec KHKK 5-wave (nay đổi nhãn); b.7 email **BỎ** — thay bằng tạo-phiếu-từ-PE-`DaDuyet` = **spec W2 đã đúng sẵn** ⇒ Q8 (email external) **ĐÓNG: out-of-scope** | | 3 Duyệt HĐ | 13→18 | ✅ tận dụng Contract V2 (verdict `LAI` @S156) | | 4 Ký cứng | 19→21 | 🔸 ngoài hệ thống — upload file đã ký (Contract attachments sẵn nền); thiết kế sau | ## Stages - [x] **T1 — FE Tổng quan pipeline** ✅ — `frontend-designer` land `UserDashboardPage.tsx` **585+/143−** (1 file, 0 dep mới, khai `NO-SCREENSHOT` trung thực); return dính #53 nhưng **file chính + sub-file 15.803B đã trên đĩa TRƯỚC khi chết** — mất 0 B. ⭐ Designer **BÁC 2 dữ kiện lead đưa** (đọc BE thật): `pendingMe` KHÔNG phải query-param (là endpoint `/inbox` mảng phẳng) · `Paged` field là `total` không phải `totalCount`. - [x] **T4a — reviewer diff** ✅ `PASS_WITH_FLAGS — 7 FLAG (0H/2M/5L)` (`sub-reviewer-diff-tongquan.md` 16.761B; §A 12-claim verify độc lập + 7 giả-thuyết-tự-bác; chết #53 ×1 giữa chừng, resume sạch). **Disposition TỪNG DÒNG:** · FLAG-1 [M] aria trùng tên → **FIX**: prop `group` BẮT BUỘC + `aria-label` (TS tự bắt đủ 6 call-site) · FLAG-2 [M] 2 chuỗi Anh → **FIX**: "Toàn trình 4 giai đoạn" · "Tải lên bản hợp đồng đã ký cứng" · FLAG-3 [L] câu GĐ2 nói quá → **FIX**: bỏ mệnh đề "sẵn sàng nối tiếp" · FLAG-5 [L] queryKey đôi → **FIX SÂU HƠN đề nghị**: 🔴 đề nghị gốc (dùng chung key, giữ queryFn trả `.length`) sẽ **VỠ CACHE** InboxPage (cache mảng ⟂ number cùng key) — fix đúng = chung key + chung queryFn (mảng) + `select: d => d.length`; request +2→+1 · FLAG-4 [L] đích `/inbox` số lệch nguồn → **PARK** (lệch có sẵn pre-diff, fix cần param/endpoint mới — ngoài scope, ghi nợ) · FLAG-6 [L] 2 nút Thử-lại trùng → **PARK** (reviewer tự đính chính giữa chừng; cosmetic, chấp nhận) · FLAG-7 [L] nhãn GĐ4 → **NO_CHANGE** (đúng spec owner ❷/❹ — GĐ4 cố ý ngoài hệ thống) - [x] **T4b — build độc lập SAU mọi edit** ✅ PASS 454ms (`tsc -b && vite build`) · 6/6 `group` land · diagnostics IDE giữa chừng = snapshot dở (#68), bác bằng compiler thật - [x] **T4c — commit đợt-1 `b5799fc` push → cicd `PASS 9/9`** (bundle user `DptYR4wL`→`0GO8mgrG`, 3 marker dương + 2 control âm, smoke 4/4; return garble #53 lần 10 — đĩa `cicd-verify-b5799fc.md` 9.930B trọn) ## ĐỢT-2 (3 lệnh mid-turn của anh, 11:24-11:5x) **Owner verbatim:** ① *"sửa giao diện nhanh"* ② ảnh tab strip 4 giai đoạn trên phiếu + *"cho hiển thị các tab phía trên như này nhé"* ③ *"Phần menu cũng hiển thị đúng như vậy luôn. (Trình ký Hợp đồng đổi thành Duyệt hợp đồng, ký cứng -> Hợp đồng cứng)"* · UAT anh Kiệt (chat FDC): *"cho đánh số thứ tự phía trước giúp anh — 01 . HĐ thầu phụ"*. 🔴 **Bộ tên 4-GĐ CHỐT MỚI NHẤT (supersede nhãn ❶ sáng nay):** Duyệt NCC · **Kế hoạch ký kết HĐ** · **Duyệt hợp đồng** · **Hợp đồng cứng** — tin-mới-nhất-thắng; nhãn "Đề xuất ký kết hợp đồng" (❶) chỉ sống 1 buổi, spec sẽ ghi cả 2 đời. - [x] **Đ2-a — đánh số 01.-07. nhóm HĐ** ✅ prod LIVE tức thì (`renamed=7`, prepend-only **0 ký tự VN qua wire** — né E-010) + seeder `typeLabels` + labelBackfill 7 entry - [x] **Đ2-b — menu 4-GĐ prod** ✅ SQL qua **file UTF-16 + scp** (3 nhãn VN mới an toàn): `ren_pe=1 ren_ct=1 perm=26` (=13×2, khớp toán) · root order: Duyệt NCC(25) → Kế hoạch ký kết HĐ(26) → Duyệt hợp đồng(31) → Hợp đồng cứng(32) · bẫy shell VPS = PowerShell 5.1 không nhận `&&` - [x] **Đ2-c — `PePipelineStrip` mirror ×2 app** ✅ byte-identical (`ef7b78…`) + chèn `PeDetailTabs` ×2 giữ **md5 parity** (`5be2ca…`, edit qua python assert count==1) — GĐ1 active, GĐ2/GĐ4 badge "Sắp", stage không-active KHÔNG click (không giả link) - [x] **Đ2-d — staticMap +2 route** (`KeHoachKyKet`/`HopDongCung` → `/dashboard`; thiếu là sidebar **drop SILENT** — gotcha #50) + đồng bộ 3 nhãn + 3 aria-group dashboard - [x] **Đ2-e — build FE ×2 PASS + test 562 PASS** (seeder đụng ⇒ chạy đủ) → **commit `1a47a61` push** (8 file, 190+/18−) - [!] **Đ2-f — cicd verify `1a47a61`** đang chạy (kèm check seeder-re-run không double-insert: 12 root, 7 nhãn `01.` nguyên) 🔸 fe-admin sidebar: 2 root placeholder sẽ **drop silent** (không thêm staticMap admin — cố ý, admin không cần placeholder; ghi để khỏi đọc thành bug) - [x] **T2 — Prod menu data** ✅ **LIVE + VERIFY TRỌN** (`prod-backup-pre-apply.txt` → apply `hide=3 upd=99 ins=376` → `prod-verify-post-apply.txt`): · Inspect lộ thực-trạng ≠ giả định: Master subtree có matrix 13-row/key (canread 2/13) nhưng **`Ct_*` 28 key = 0 ROW** (chưa từng seed), `Contracts` root 1 row ⇒ INSERT 376 + UPDATE 99, số khớp toán từng đồng (9×11=99 · 28×13+12=376) · Verify: **38/38 key min=max=13 canread** · 3 root `IsVisible=0` · control âm **Pe_* 197/185 NGUYÊN** (❹ "để như cũ") · `Hrm_Config*` canread=7 nguyên (vùng đang-làm loại khỏi grant, đúng ý ❸) · Thuần cộng: chỉ thêm `CanRead=1, CanCreate/Update/Delete=0` — không rút quyền ai - [x] **T3 — Spec đổi nhãn** ✅ 2 site (`:26` owner-block + `:222` seed label) — "Đề xuất ký kết hợp đồng"; tên English `ContractSigningPlan*` giữ; ranh GĐ + Q8-ĐÓNG ghi vào spec - [ ] **T4 — build fe-user + reviewer diff → commit/push → cicd verify** 🔴 Luật run: CẤM điền kết quả trước khi đo. Prod = backup-trước-apply, verify-LIVE-sau (S88).