wal: flush 20260729T2023

This commit is contained in:
pqhuy1987
2026-07-29 20:23:52 +07:00
parent 980b1329b5
commit 77c723b07a
6 changed files with 344 additions and 3 deletions

View File

@ -14,7 +14,9 @@ chain:
- [x] wf ĐỢT-2 `wf_a95c9909-14b`: database-agent **PASS 8/8+DB11 0-blocker** (parity 2 DB, Down script-proof) · test-specialist **4 test + fault-inject 2-chiều** (chết #53 lúc đợi suite — sub-md cứu, lead chạy tươi **566/0**); harvest 2 diary xong. Tally #53 wave này: 3/5 lượt spawn
- [x] reviewer PWF 10-issue 0-chặn (lượt-1 garble #53 → resume sạch): 8 fix cùng commit + 2 giữ; build+suite giữ 0W/0E · 566/0; residual-write MEMORY reviewer ACCEPT verified-KEPT (AS-10)
- [x] commit `a8027c0` (30 file +8.987/22, F-0 gate ĐẠT) + PUSH origin/main
- [!] wf: cicd-monitor verify `a8027c0` ĐANG CHẠY nền — 6 phép (CI 566 · mig 69 prod · menu 142 · marker `QT-KHKK-V2-001` · đo-CỜ F-04 2 chiều · smoke+label); về PASS ⇒ W1 ĐÓNG, còn nghiệm thu tay Designer type-10 3-Bước (deep-link `/system/approval-workflows-v2/ContractSigningPlan`) + dựng WF trước W5
- [x] **W1 ĐÓNG — cicd VERDICT=PASS 6/6** (Run #427 5m40s · 566 · Mig 69 prod 96 bảng · menu 142 GIỮ · marker 3-tầng · đo-CỜ 13/13/13/2 + control-âm Khkk_G1 + log `0 added + 91 upgraded` khớp dự-đoán · label type-10 VN sống). Synthesis `runs/2026-07-29-S161-khkk-w1-schema/w1-synthesis.md`. Tồn: setup WF tay trước W5 · UAT non-Admin (nv.test KHÔNG tồn tại prod) · 51-bis GẤP (cicd _INDEX 99,2%/167B) · F-4
- [x] gate 5-anchor W2 PASS 5/5 (A4 line-drift content-found; A5 KeHoachKyKet∈All:180 THẬT; phân xử lệch: mã sinh @CREATE per spec, entity-comment W1 sai → worker sửa)
- [!] wf: hmw W2 đợt-1 `wf_6f0aad26-229` ĐANG CHẠY — 2 lane {implementer-backend: mega-file ContractSigningPlanFeatures CHỈ-CRUD (cấm copy phần duyệt, bẫy flatten :427-439) + Controller authz-2-tầng ≥4 policy · implementer-frontend: pages/khkk 3-page ×2 app + 4-place re-point 6 leaf khỏi coming-soon + SHA-pair} — run-folder `runs/2026-07-29-S161-khkk-w2-crud/` (taskList 6 stage)
- [ ] đợt-2 SAU khi wf về: test-specialist + database-agent (song song) → lead acceptance §③-B (build·test·sqlcmd 96·Down sạch·đo CỜ) → reviewer → commit/push → cicd-monitor 3-chân-kiềng
- [ ] setup thủ công TRƯỚC W5 (SAU W1 vì type=10 cần mig 69): dựng workflow type=3 + type=10 3-trạm qua Designer (seed chỉ 1 trạm)
- [ ] housekeeping @pause/closeout kế: nén MIND-1 5.447B (trần `_mind` 83,2% — MIND-5 chắc vượt) · re-carry 2 ý D rơi (vá-GỐC-Phase-3.5-refresh {mới-nêu} CÒN SỐNG + khuôn-5-đợt→sổ bền {gần-chốt}) · STATUS:6 bổ arc dry-run S160 (mù có lý do — land 15:27 trước pipeline) · hạ nhãn DR/WF-3-trạm đã-định-đoạt · E đếm 7 sub-file (không 6) · mở lại slot-45 trần `_mind` (tiền-đề lật: file SỐNG 83,2%) · quyết bookkeeping OVERDUE:light (cặp H24 chạy @S159 bookend mà `last_audit` đứng 27)

View File

@ -1,6 +1,8 @@
# CI/CD Monitor Agent — Persistent Memory
- **07-29 verify `ea962b1` ĐỢT-5 (menu 6-leaf y-chang-Duyệt-NCC + `GET /contracts/deleted` + bỏ hero) [S159, 10 file 173+/371, 0 mig]:** ✅ **PASS 9/9** — Run **#426** (id=539) success **5m38s**; gate **562**. JS rotate cả 2 app (admin `CC1pGE1F``D0sXA0fe` · user `CLfAftby``Y6dW_5CM` +css `B6bUSFBt``6YIAufJR`); admin-css FROZEN nhưng **LM 14:44:29 in-window** ⇒ lành tính (#69 mode-B, khuôn đợt-4 dùng lại được ngay). 🔑 **CỨU FALSE-FAIL — luật MỚI về control ÂM:** brief bảo `Toàn trình 4 giai đoạn` phải VẮNG; tao grep repo-wide TRƯỚC khi đo → chuỗi vẫn sống hợp lệ ở `PePipelineStrip.tsx:24` **`aria-label`** (cả 2 app, có từ đợt-2) ⇒ **dự đoán bundle=1 chứ không 0**, đo đúng 1. Áp máy móc là FAIL OAN. Thay bằng `Quy trình mua sắm` (eyebrow hero) — `grep -rc` 2 app = **0 hit mọi file** ⇒ ĐỘC QUYỀN ⇒ bundle=0 = chứng hero đã gỡ (kèm `UserDashboardPage` 63.124→50.142 B). ⟹ **LUẬT: trước khi nhận 1 chuỗi làm control ÂM phải grep repo-wide xác nhận nó ĐỘC QUYỀN cho thứ mình muốn chứng vắng; chuỗi dùng-chung chỉ làm marker DƯƠNG.** 🔑 **SEEDER-INSERT delta khớp TOÁN (khuôn mạnh, tái dùng):** đo baseline TRƯỚC deploy rồi so SAU restart — `Ct_%_WfView` 0→**7** · `_Approved` 0→**7** · `_Deleted` 0→**7** · `Khkk_%` 5→**7** · nhãn `Ct_%_Pending`=`Đang%` 0→**7** · Dashboard `%quy tr%` 0→**1** · **MenuItems 119→142 = +23 = 7+7+7+2 khớp từng đồng** · root 12 · DUPKEYS 0 · **21 key mới đủ 13/13 canread** (nhánh reviewKeys skip-existing ăn vì key HOÀN TOÀN MỚI — khác đợt-2/3 nơi row `false` sẵn có không được nâng). **Endpoint mới:** `GET /api/contracts/deleted`**401** + **control route bịa → 404** ⇒ 401 CÓ NGHĨA, không phải catch-all (đừng chỉ đo 401 trần). ⚠️ brief ghi `/contracts/deleted` thiếu prefix — route thật có `[Route("api/contracts")]`. **Durability lần 3:** 38-key **494/494** · control âm Hrm/Off/Personal=0 · `Pe%` 197/185 · `Hdc_` nhãn 7 · 3 root ẩn. ⚠️ **Bẫy phạm-vi mới: `Ct_*` nay đẻ thêm 21 key ⇒ `LEFT(MenuKey,3)='Ct_'` cho ra 59 key, KHÔNG so được với đợt trước — phải NOT LIKE 3 hậu tố mới để giữ đúng tập 38 gốc.** Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-ea962b1.md`. Tag `[run-426, pass-9-9, control-am-phai-DOC-QUYEN, seeder-delta-khop-toan, 401-voi-control-404, durability-restart-3, query-scope-re-anchor, gate-562]`
- **07-29 verify `a8027c0` W1 KHKK — Mig 69 `AddContractSigningPlans` [S161, 30 file +8987/22]:** ✅ **PASS 6/6** — Run **#427** (id=540) success **5m40s**; gate **566 = 45D+521I** (0 fail/skip, +4 test W1). Mig 69 APPLIED-PROD: MIGTOP `20260729122015_AddContractSigningPlans` · MIGCOUNT 68→**69** · `sys.tables` **89→96 (+7 khớp 7 CreateTable)** · 7 bảng `ContractSigningPlan{s,Lines,DossierItems,LevelOpinions,Attachments,Changelogs,Approvals}`. MenuItems **142→142 GIỮ** (policy-key ⟂ menu-key). 🔑 **KHUÔN ĐO-CỜ (không đếm ROW) — tái dùng cho mọi seeder UPGRADE-if-exists:** row đã tồn tại CanRead-only ⇒ đếm row = 0-bit; đo PRE/POST **cờ** 8 key: 7 key đích 13/0/0/0 → **13/13/13/2**, vế ÂM liệt-kê-toàn-bộ `CanDelete=1` = **đúng 14 row = {Admin,Drafter}×7** (11 role kia D=0), Drafter (non-Admin) C/U/D=1. 🔑 **Control ÂM NỘI-HỌ mạnh nhất từ trước tới nay: `Khkk_G1` bị seeder CỐ Ý bỏ khi danh sách 7 key** ⇒ nó phải đứng yên 13/**0/0/0** — và nó đứng yên ⟹ chứng "đúng NGƯỜI làm, đúng TẬP", không phải thứ gì lật bừa cả họ. **Đọc seeder DỰ ĐOÁN `0 added + 91 upgraded` (91=7×13) TRƯỚC khi đo → log prod khớp từng đồng** (`added=0` = đúng đường upgrade, F-S1 đóng). Marker `QT-KHKK-V2-001` grep repo TRƯỚC ⇒ độc quyền 1 site fe-admin ⇒ dự đoán admin=1/user=0, đo đúng; **control ÂM 3 TẦNG**: hash CŨ `D0sXA0fe``ct=text/html` 900B **trùng khít hash BỊA** ⇒ 200 là SPA-fallback, bundle cũ đã bị ghi đè. admin js+css rotate (`M8SDA7Ps`/`C3xzT0H9`); user FROZEN nhưng **LM 20:10:00 in-window**#69 mode-B lành tính. Restart chứng bằng **w3wp pid=4980 StartTime 20:10:05 TRÙNG dòng CI `App pool started`** + DLL mtime 20:07:50. Label F-7 sống: `?applicableType=10``"applicableTypeLabel":"Kế hoạch ký kết HĐ"`, `active:null/history:[]` + sqlcmd `ApplicableType=10`=0 ⇒ chưa dựng WF (đúng W1). Smoke 4 endpoint 200 + **route bịa 404** (chứng 200 CÓ NGHĨA). Durability `Ct_` **637/637** CanRead, root 12, DUPKEYS 0. Evidence: `runs/2026-07-29-S161-khkk-w1-schema/cicd-verify-a8027c0.md`. Tag `[run-427, pass-6-6, do-CO-khong-dem-ROW, control-am-noi-ho-key-bi-bo-sot, du-doan-91-upgraded-khop, control-am-3-tang-bundle, mig69-96-bang, gate-566]`
- _(**#426 S159 đợt-5 `ea962b1` menu 6-leaf + `GET /contracts/deleted` + bỏ hero — PASS 9/9**: gate 562, 5m38s. JS rotate cả 2 app (admin `CC1pGE1F``D0sXA0fe` · user `CLfAftby``Y6dW_5CM` +css `B6bUSFBt``6YIAufJR`); admin-css FROZEN nhưng **LM 14:44:29 in-window** ⇒ lành tính (#69 mode-B, khuôn đợt-4 dùng lại được ngay). 🔑 **CỨU FALSE-FAIL — luật MỚI về control ÂM:** brief bảo `Toàn trình 4 giai đoạn` phải VẮNG; tao grep repo-wide TRƯỚC khi đo → chuỗi vẫn sống hợp lệ ở `PePipelineStrip.tsx:24` **`aria-label`** (cả 2 app, có từ đợt-2) ⇒ **dự đoán bundle=1 chứ không 0**, đo đúng 1. Áp máy móc là FAIL OAN. Thay bằng `Quy trình mua sắm` (eyebrow hero) — `grep -rc` 2 app = **0 hit mọi file** ⇒ ĐỘC QUYỀN ⇒ bundle=0 = chứng hero đã gỡ (kèm `UserDashboardPage` 63.124→50.142 B). ⟹ **LUẬT: trước khi nhận 1 chuỗi làm control ÂM phải grep repo-wide xác nhận nó ĐỘC QUYỀN cho thứ mình muốn chứng vắng; chuỗi dùng-chung chỉ làm marker DƯƠNG.** 🔑 **SEEDER-INSERT delta khớp TOÁN (khuôn mạnh, tái dùng):** đo baseline TRƯỚC deploy rồi so SAU restart — `Ct_%_WfView` 0→**7** · `_Approved` 0→**7** · `_Deleted` 0→**7** · `Khkk_%` 5→**7** · nhãn `Ct_%_Pending`=`Đang%` 0→**7** · Dashboard `%quy tr%` 0→**1** · **MenuItems 119→142 = +23 = 7+7+7+2 khớp từng đồng** · root 12 · DUPKEYS 0 · **21 key mới đủ 13/13 canread** (nhánh reviewKeys skip-existing ăn vì key HOÀN TOÀN MỚI — khác đợt-2/3 nơi row `false` sẵn có không được nâng). **Endpoint mới:** `GET /api/contracts/deleted`**401** + **control route bịa → 404** ⇒ 401 CÓ NGHĨA, không phải catch-all (đừng chỉ đo 401 trần). ⚠️ brief ghi `/contracts/deleted` thiếu prefix — route thật có `[Route("api/contracts")]`. **Durability lần 3:** 38-key **494/494** · control âm Hrm/Off/Personal=0 · `Pe%` 197/185 · `Hdc_` nhãn 7 · 3 root ẩn. ⚠️ **Bẫy phạm-vi mới: `Ct_*` nay đẻ thêm 21 key ⇒ `LEFT(MenuKey,3)='Ct_'` cho ra 59 key, KHÔNG so được với đợt trước — phải NOT LIKE 3 hậu tố mới để giữ đúng tập 38 gốc.** Evidence: `runs/2026-07-29-S159-tong-quan-pipeline-menu/cicd-verify-ea962b1.md`. Tag `[run-426, pass-9-9, control-am-phai-DOC-QUYEN, seeder-delta-khop-toan, 401-voi-control-404, durability-restart-3, query-scope-re-anchor, gate-562]`
- _(**#425 S159 đợt-4 `a2bbcb9` 7-FLAG fix + nhãn 'Bảng cứng' — PASS 9/9**: gate 562, user js `DeAg7MWm``CLfAftby`. 🔑 **admin FROZEN vẫn chứng được lành tính**: LM 13:55:31 **in-window** + size trùng ⇒ re-ship byte-identical (#69 mode-B). 🔑 **comment-strip DỰ ĐOÁN TRƯỚC rồi mới đo**: `chưa tới` source=2 (cả 2 trong comment) → dự đoán bundle=0 → đúng 0. ⚠️ `Không tìm thấy` bundle 10 > source 3 ⇒ marker phổ-thông chỉ dùng '≥1'. **Durability lần 2**: 38-key 494/494 giữ + control âm 0)_

View File

@ -0,0 +1,277 @@
# cicd-monitor — verify deploy `a8027c0` (W1 KHKK, Mig 69 ContractSigningPlans)
> Agent: cicd-monitor (READ-only) · S161 · 2026-07-29
> Spec acceptance: `.claude/workflows/runs/2026-07-29-S160-khkk-dryrun-plan/spec-wave-w1-schema-designer-29-07-2026.md` §③-B
> **Ghi-đĩa-TRONG-lúc-làm** (chống #53). Mỗi mục ghi NGAY khi có bằng chứng. Kết bằng dòng `END … VERDICT=`.
---
## CHÂN 0 — Push + path-filter (pre-condition)
| Mục | Giá trị |
|---|---|
| Commit | `a8027c04fe929750998f5c20e23854f9d0e7a765` |
| Subject | `[CLAUDE] Domain+App+Infra+Admin: W1 KHKK — Mig 69 ContractSigningPlans 7 bang + policy KeHoachKyKet + seeder UPGRADE-if-exists + CodeGen KHKK + Designer type-10` |
| Commit time | 2026-07-29 20:04:39 +0700 |
| `git log origin/main..HEAD` | **rỗng** ⇒ đã push |
| Files changed | **30 file, +8987 / 22** |
| Path-filter (#41) | 29/30 file NON-ignored (`src/Backend/**`, `fe-admin/src/**`, `tests/**`); chỉ `docs/STATUS.md` bị ignore ⇒ **CI PHẢI trigger** ✅ |
**Mig 69 on-disk (3-file rule OK):**
- `20260729122015_AddContractSigningPlans.cs` (372 dòng) + `.Designer.cs` (6960) + `ApplicationDbContextModelSnapshot.cs` (+550)
- `grep -c migrationBuilder.CreateTable` = **7** — đúng 7 bảng, 0 ALTER bảng cũ:
`ContractSigningPlans` · `…Lines` · `…DossierItems` · `…LevelOpinions` · `…Attachments` · `…Changelogs` · `…Approvals`
**Byte-marker (chân 4) — kiểm ĐỘC QUYỀN TRƯỚC khi đo (luật S159):**
- `rg QT-KHKK-V2-001` toàn repo: **1 hit code** = `fe-admin/src/pages/system/ApprovalWorkflowsV2Page.tsx:170`
(`[TYPE_INT_CONTRACT_SIGNING_PLAN]: 'QT-KHKK-V2-001',` trong `DEFAULT_CODE_BY_TYPE`)
- `fe-user/src` = **0 hit** ⇒ chuỗi ĐỘC QUYỀN cho fe-admin, sinh mới @S161
-**Dự đoán TRƯỚC khi đo:** admin bundle mới = **1** occurrence · user bundle = **0** · admin bundle CŨ (`D0sXA0fe`) = 0.
---
## BASELINE PRE-DEPLOY (đo 20:08:31 +0700, TRƯỚC khi run #427 xong)
| Chỉ số | Giá trị pre-deploy |
|---|---|
| `sys.tables WHERE is_ms_shipped=0` | **89** |
| `MAX(MigrationId)` | **`20260727033522_AddPeAllowApproverDelete`** (Mig 68) |
| `COUNT(*) MenuItems` | **142** |
| bảng `ContractSigningPlan%` | **0** |
| admin bundle | js `index-D0sXA0fe.js` · css `index-DWDbm5As.css` |
| user bundle | js `index-Y6dW_5CM.js` · css `index-6YIAufJR.css` |
Kỳ vọng post-deploy: tables **89 → 96** (+7) · MIGTOP → `20260729122015_AddContractSigningPlans` · MenuItems **142 GIỮ** · CSP tables **0 → 7**.
---
### Baseline CỜ policy (chân 5) — đo 20:09, TRƯỚC deploy
13 role prod. 8 key họ KHKK, **tất cả** = `rows=13 · R=13 · C=0 · U=0 · D=0`:
`KeHoachKyKet` · `Khkk_G1` · `Khkk_WfView` · `Khkk_List` · `Khkk_Create` · `Khkk_Pending` · `Khkk_Approved` · `Khkk_Deleted`
⟹ xác nhận tiền-đề F-S1: **row ĐÃ có sẵn CanRead-only** ⇒ đếm ROW = 0-bit, chỉ CỜ mới chứng UPGRADE ăn.
### DỰ ĐOÁN TRƯỚC KHI ĐO (đọc seeder `DbInitializer.SeedKeHoachKyKetAccessAsync` trong diff, KHÔNG đọc kết quả)
Tập key seeder đụng = **7** (`:2405+`): `KeHoachKyKet` + `Khkk_{WfView,List,Create,Pending,Approved,Deleted}`.
🔑 **`Khkk_G1` CỐ Ý NGOÀI tập** (comment: "group điều hướng — KHÔNG cần cờ ghi") ⟹ **control ÂM nội-họ**: nếu `Khkk_G1` cũng bật C/U thì phép đo của tao vô nghĩa (chứng tỏ có thứ khác lật bừa cả họ).
| Đại lượng | Dự đoán |
|---|---|
| 7 key đích: `SUM(CanCreate)` | **13** mỗi key (13/13 role) |
| 7 key đích: `SUM(CanUpdate)` | **13** mỗi key |
| 7 key đích: `SUM(CanDelete)` | **2** mỗi key (CHỈ Admin + Drafter) — chiều ÂM: 11 role còn lại phải =0 |
| `Khkk_G1` (control ÂM) | **C=0 · U=0 · D=0 GIỮ NGUYÊN** |
| Log seeder | `0 added + 91 upgraded` (91 = 7 key × 13 role, mọi row tồn tại sẵn) |
| MenuItems | **142 GIỮ** (seeder không thêm menu-row; `KeHoachKyKet` menu-row đã có từ S159) |
---
## CHÂN 1 — CI run
| Mục | Giá trị |
|---|---|
| Run | **#427** (task id **540**) |
| head_sha | `a8027c04` ✅ khớp (key theo sha, KHÔNG theo run_number) |
| created_at | 2026-07-29T20:04:48+07:00 |
| **Kết luận** | **`status=success`** @2026-07-29T20:10:28+07:00 |
| Duration | **5m40s** (20:04:48 → 20:10:28) — trong dải ~5m30-6m gần đây |
| Run URL | https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/427 |
**Test gate (log web-UI `…/actions/runs/427/jobs/0/logs`, 17.936 B):** 2 dòng `Passed!`, đối chiếu TÁCH-PHẦN:
```
Passed! - Failed: 0, Passed: 45, Skipped: 0, Total: 45 <- SolutionErp.Domain.Tests
Passed! - Failed: 0, Passed: 521, Skipped: 0, Total: 521 <- SolutionErp.Infrastructure.Tests
```
**566 PASS (45 D + 521 I), 0 fail, 0 skip** = ĐÚNG con số spec chờ (562 → 566, +4 test mới W1). ✅
**Dòng deploy (cuối log, giờ UTC trong log = +07 7h):**
```
2026-07-29T13:10:05.8595528Z Deploy done. App pool started.
2026-07-29T13:10:19.7741482Z API /health/live -> 200
```
### ✅ CHÂN 1 = **PASS**
---
## CHỨNG MINH RESTART THẬT (điều kiện tiên quyết của chân 2/3/5 — luật 3-chân-kiềng)
| Bằng chứng | Giá trị |
|---|---|
| `w3wp` process mới | **pid 4980 · StartTime = 2026-07-29 20:10:05** — TRÙNG KHỚP dòng CI `App pool started` 20:10:05 |
| `SolutionErp.Api.dll` mtime | **2026-07-29 20:07:50** — trong cửa-sổ deploy (20:04:4820:10:28) ⇒ file BE thật sự bị ghi đè |
⟹ Mọi số đo DB dưới đây lấy lúc **20:11+**, tức **SAU** mốc recycle 20:10:05 ⇒ hợp lệ (tránh bẫy đo-trước-recycle S159 đợt-2).
---
## CHÂN 2 — Mig 69 áp prod
| Chỉ số | Pre | Post | Kỳ vọng | Kết quả |
|---|---|---|---|---|
| `MAX(MigrationId)` | `20260727033522_AddPeAllowApproverDelete` | **`20260729122015_AddContractSigningPlans`** | = Mig 69 | ✅ |
| `COUNT(*) __EFMigrationsHistory` | 68 | **69** | 69 | ✅ |
| `sys.tables WHERE is_ms_shipped=0` | 89 | **96** | 89→96 (+7) | ✅ khớp TOÁN |
| bảng `ContractSigningPlan%` | 0 | **7** | 7 | ✅ |
7 bảng đếm đích danh (khớp 1:1 với 7 `CreateTable` trong file mig):
`ContractSigningPlans` · `…Lines` · `…DossierItems` · `…LevelOpinions` · `…Attachments` · `…Changelogs` · `…Approvals`
### ✅ CHÂN 2 = **PASS** (bằng chứng sqlcmd prod trực tiếp, không phải suy từ CI-log)
---
## CHÂN 3 — Menu KHÔNG đổi
`COUNT(*) MenuItems`: pre **142** → post **142****GIỮ NGUYÊN, 0 row thêm**
(W1 chỉ đụng policy-key `KeHoachKyKet` trong `MenuKeys.All`, menu-row `Khkk_*` đã seed từ S159 — đúng Δ-1 của spec.)
### ✅ CHÂN 3 = **PASS**
---
## CHÂN 6 (phần 1) — 3 domain sống
| URL | HTTP |
|---|---|
| `https://api.solutions.com.vn/health/live` | **200** ✅ |
| `https://admin.solutions.com.vn/` | **200** ✅ |
| `https://eoffice.solutions.com.vn/` | **200** ✅ |
_(đo 20:11:30; lưu ý `/health` trần = 404 UNMAPPED — đường thật là `/health/live` + `/health/ready`)_
---
## CHÂN 4 — Bundle byte-marker (#77) + 3 tầng control ÂM
| App | Pre-deploy | Post-deploy | Trạng thái |
|---|---|---|---|
| admin js | `index-D0sXA0fe.js` | **`index-M8SDA7Ps.js`** | 🔄 ROTATE |
| admin css | `index-DWDbm5As.css` | **`index-C3xzT0H9.css`** | 🔄 ROTATE |
| user js | `index-Y6dW_5CM.js` | `index-Y6dW_5CM.js` | ⏸️ FROZEN — **lành tính** (xem dưới) |
| user css | `index-6YIAufJR.css` | `index-6YIAufJR.css` | ⏸️ FROZEN — lành tính |
**Ship-proof THẬT (không dựa hash-delta — #69 TWO-MODE):**
| Bằng chứng | admin js MỚI | user js (frozen) |
|---|---|---|
| `Content-Type` | `application/javascript` | `application/javascript` |
| Size thật | **1.679.452 B** | 1.595.577 B |
| `Last-Modified` | **Wed, 29 Jul 2026 13:09:05 GMT** = 20:09:05 +07 | **13:10:00 GMT = 20:10:00 +07** |
| Trong cửa-sổ deploy (20:04:4820:10:28)? | ✅ | ✅ |
⟹ user FROZEN + **LM TRONG cửa-sổ** = re-ship byte-identical (#69 mode-B), KHÔNG phải bundle-cũ-kẹt. Đúng kỳ vọng: commit chỉ đụng `fe-admin/src`, `fe-user` 0 file.
**Byte-marker `QT-KHKK-V2-001` — đo SAU khi đã chứng ĐỘC QUYỀN:**
| Phép | Dự đoán (ghi trước) | Đo được | KL |
|---|---|---|---|
| admin bundle MỚI | **1** | **1** | ✅ khớp SỐ FILE nguồn (1 site `ApprovalWorkflowsV2Page.tsx:170`) |
| user bundle (control ÂM cross-app) | **0** | **0** | ✅ chứng marker không "khớp bừa" |
| admin bundle **CŨ** `D0sXA0fe` (control ÂM tầng-2) | biến mất | `http=200` **`ct=text/html` 900 B** | ✅ bundle cũ đã bị GHI ĐÈ khỏi đĩa |
| hash BỊA `ZZZZZZZZ` (mốc so trap SPA-fallback) | text/html | `http=200` **`ct=text/html` 900 B** | ✅ trùng khít mốc ⇒ 200 của hash-cũ là fallback, KHÔNG phải file thật |
### ✅ CHÂN 4 = **PASS** (3 tầng control ÂM đều nói cùng một chuyện)
---
## CHÂN 5 — ĐO CỜ policy-grant (F-04 / F-1 — vế acceptance đang treo)
**Đo SAU recycle 20:10:05.** Đối chiếu PRE → POST, mọi key 13 role:
| MenuKey | PRE (R/C/U/D) | POST (R/C/U/D) | Dự đoán | KL |
|---|---|---|---|---|
| `KeHoachKyKet` | 13/0/0/0 | **13/13/13/2** | 13/13/2 | ✅ |
| `Khkk_WfView` | 13/0/0/0 | **13/13/13/2** | 13/13/2 | ✅ |
| `Khkk_List` | 13/0/0/0 | **13/13/13/2** | 13/13/2 | ✅ |
| `Khkk_Create` | 13/0/0/0 | **13/13/13/2** | 13/13/2 | ✅ |
| `Khkk_Pending` | 13/0/0/0 | **13/13/13/2** | 13/13/2 | ✅ |
| `Khkk_Approved` | 13/0/0/0 | **13/13/13/2** | 13/13/2 | ✅ |
| `Khkk_Deleted` | 13/0/0/0 | **13/13/13/2** | 13/13/2 | ✅ |
| 🔑 `Khkk_G1` **(control ÂM nội-họ)** | 13/0/0/0 | **13/0/0/0** | **KHÔNG đổi** | ✅ |
**Vế DƯƠNG (role non-Admin):** `Drafter` trên cả 7 key đích = **C=1 · U=1 · D=1** ⇒ thoả acceptance "≥1 role non-Admin có CanCreate=1 ∧ CanUpdate=1".
**Vế ÂM (CanDelete chỉ Drafter/Admin):** liệt kê TOÀN BỘ row có `CanDelete=1` trong họ KHKK = **đúng 14 row = {Admin, Drafter} × 7 key**, không thừa 1 role nào ⇒ 11 role còn lại D=0. ✅
🔑 **Vì sao `Khkk_G1` là control ÂM có RĂNG:** seeder liệt kê tay 7 key và **cố ý bỏ `Khkk_G1`** ("group điều hướng — KHÔNG cần cờ ghi"). Nếu `Khkk_G1` cũng bật C/U thì phép đo vô nghĩa (chứng tỏ có thứ khác lật bừa cả họ). Nó đứng yên ⇒ đúng NGƯỜI làm, đúng TẬP.
**Chứng độc lập từ log API prod** (`C:\inetpub\solution-erp\api\logs\solution-erp-20260729.log`), khớp con số tao ghi TRƯỚC khi đo:
```
2026-07-29 20:10:18.902 +07:00 [INF] Seeded KeHoachKyKet access: 0 added + 91 upgraded
(W1 GD2 golive - 13/13 role C+U, Delete=Drafter/Admin; UPGRADE-if-exists F-S1)
```
`0 added + 91 upgraded`**91 = 7 key × 13 role**, khớp từng đồng dự đoán. `added=0` ⇒ đúng đường UPGRADE-if-exists, KHÔNG insert (F-S1 đóng: nhánh insert-NO-OP đã bị tránh). Timestamp 20:10:18 nằm SAU restart 20:10:05 ⇒ seeder chạy trong lần khởi động này, và chạy SAU revoke (đúng thứ tự `SeedAsync`).
### ✅ CHÂN 5 = **PASS** — đo CỜ (không đếm ROW), đủ 2 chiều dương/âm + control ÂM
---
## CHÂN 6 (phần 2) — Bearer + label type-10
Login `admin@solutions.com.vn``accessToken` dài 468 ⇒ OK.
| Endpoint (admin bearer) | HTTP |
|---|---|
| `GET /api/contracts` | 200 ✅ |
| `GET /api/purchase-evaluations` | 200 ✅ |
| `GET /api/menus` | 200 ✅ |
| `GET /api/approval-workflows-v2` | 200 ✅ |
| **control: `GET /api/khong-ton-tai-abc`** | **404** ⇒ 200 ở trên CÓ NGHĨA, không phải catch-all |
**F-7 label BE ăn prod**`GET /api/approval-workflows-v2?applicableType=10` trả nguyên văn:
```json
{"types":[{"applicableType":10,"applicableTypeLabel":"Kế hoạch ký kết HĐ","active":null,"history":[]}]}
```
⟹ type **10** SỐNG trên prod với nhãn VN **"Kế hoạch ký kết HĐ"** (không rơi fallback `ToString()` tiếng Anh). `active:null` + `history:[]` = **chưa có quy trình type-10 nào** — ĐÚNG kỳ vọng W1 (admin sẽ dựng tay), xác nhận chéo bằng sqlcmd `COUNT(*) ApprovalWorkflows WHERE ApplicableType=10` = **0**.
### ✅ CHÂN 6 = **PASS**
---
## Kiểm tra phụ (không nằm trong 6 chân — chống hồi-quy)
| Phép | Kết quả | Nhận định |
|---|---|---|
| Họ `Ct_` (S159 durability) | **637/637 row CanRead**, 49 distinct key | ✅ 100%, revoker KHÔNG lật gì |
| MenuItems root (`ParentKey IS NULL`) | **12** | ✅ khớp mốc S159 |
| `MenuItems` trùng key | **0** | ✅ |
| Menu-row họ KHKK | **8** (`KeHoachKyKet` + 7 `Khkk_*`) | ✅ không đổi |
| `ContractSigningPlans` rows | **0** | ✅ đúng — W1 schema-only, chưa có dữ liệu |
⚠️ **Đính chính trí-nhớ của tao (không phải lỗi deploy):** ghi chú S159 nói họ `Ct_` có "59 key ⇒ tập gốc 38". Đo thật hôm nay: **49 distinct key**, trong đó 21 key mang 3 hậu tố mới ⇒ tập lọc còn **28 key × 13 role = 364**, nên `364/364` chứ không phải `494/494`. Denominator lệch là do **PHẠM-VI QUERY + số cũ ghi sai**, KHÔNG phải mất quyền — bằng chứng mạnh hơn: đo TOÀN họ `Ct_` được **637/637**.
---
## ⚠️ 2 phát hiện phụ cần báo (KHÔNG do commit này gây ra, KHÔNG chặn W1)
1. **Tài khoản UAT `nv.test@solutions.com.vn` KHÔNG TỒN TẠI trên prod.**
`POST /api/auth/login`**401** `"Email hoặc mật khẩu không đúng."`; sqlcmd `SELECT COUNT(*) FROM Users WHERE Email LIKE 'nv.test%'` = **0** (tổng 18 user).
⇒ Phép thử 2-bearer (gotcha #44 — soi 403 im lặng cho role non-Admin) **hiện KHÔNG chạy được trên prod**. Commit `a8027c0` không đụng Users ⇒ không phải hồi-quy của lượt này (nhiều khả năng demo-seed bị gate — gotcha #51). **Đề xuất em-main:** chọn 1 tài khoản non-Admin CÓ THẬT làm mốc UAT mới, hoặc bỏ vế 2-bearer khỏi checklist cho tới khi có tài khoản.
2. **Đường log API trong memory của tao đã STALE.** `C:\inetpub\solution-erppi\logs` = **không tồn tại**; đường THẬT = **`C:\inetpub\solution-erp\api\logs\solution-erp-YYYYMMDD.log`**. Đã sửa trong MEMORY.
---
## TỔNG KẾT
| Chân | Nội dung | Verdict |
|---|---|---|
| 1 | CI run #427 PASS + test gate **566 (45D+521I)** | ✅ **PASS** |
| 2 | Mig 69 áp prod (MIGTOP + 96 bảng + 7 bảng CSP) | ✅ **PASS** |
| 3 | MenuItems **142 GIỮ NGUYÊN** | ✅ **PASS** |
| 4 | Byte-marker `QT-KHKK-V2-001` + 3 tầng control ÂM | ✅ **PASS** |
| 5 | ĐO CỜ policy-grant 2 chiều + control ÂM `Khkk_G1` | ✅ **PASS** |
| 6 | Smoke 3 domain + bearer + label type-10 | ✅ **PASS** |
**Không có mục nào FAIL. Không đề xuất rollback.**
END cicd-verify a8027c0 — **VERDICT=PASS 6/6**

View File

@ -15,7 +15,9 @@
| 4 | Đợt-2b: design-review Mig 69 TRƯỚC deploy (reversible Down · snapshot drift · FK/index) | hmw `database-agent` | [x] cùng wf — **PASS 8/8 + DB11, 0 blocker** (đo sys.foreign_keys/filter_definition; parity 2 DB tuyệt đối; Down script atomic sạch; IX superset khuôn PE; 4 advisory wave-sau) — `sub-database-agent-1.md` 21KB |
| 5 | Lead: build ×2 + `dotnet test` + sqlcmd 89→96 + Down-script sạch + acceptance §③-B sweep | lead | [x] build BE 0W/0E 47s + FE build tươi PASS · test **566/0** (562+4 ≥ sàn 564) · sys.tables 96 ×2 DB · Down script-proof · CÒN 2 vế prod-side @stage-7: đo-CỜ policy sau seed prod + Designer tạo type-10 3-Bước |
| 6 | Reviewer adversarial diff (schema mig >50 LOC — bắt buộc trước commit) | `reviewer` | [x] **PASS_WITH_FLAGS 10 issue (1H/3M/4m/2L), 0 chặn logic** — lượt-1 garble #53 giữa Trục-1 → SendMessage-resume về SẠCH đủ 6 trục. Disposition TỪNG DÒNG: 8 FIX cùng commit (F-0 git-add-tường-minh gate · F-7 label VN type-10 vào AwLabels · F-8 ép-false 2 cờ tầng BE · F-2 STATUS 55/220 · F-5 comment 7→8 · F-3 comment 2 chỗ · F-9 neo-tên-thay-số-dòng · F-6b khai giới hạn changelog) + 2 GIỮ (F-1 đo-CỜ chờ prod @stage-7 · F-4 kế thừa y PE prod). Sau fix: build 0W/0E + suite 566/0 GIỮ. Residual-write MEMORY tự-curate → verify ĐẠT, ACCEPT verified-KEPT (AS-10) — `sub-reviewer-2.md` |
| 7 | Commit + push + cicd-monitor 3-chân-kiềng (CI PASS · mig 69 prod · menu 142 giữ) | lead + `cicd-monitor` | [!] commit **`a8027c0`** (30 file, +8.987/22, mig 3-file đủ, F-0 gate porcelain-??-rỗng ĐẠT) đã PUSH → CI đang chạy; `cicd-monitor` spawn nền — 6 phép {CI+test-gate 566 · mig 69 prod · menu 142 GIỮ · byte-marker `QT-KHKK-V2-001` độc-quyền · **đo CỜ F-04** (Create/Update 13/13 + Delete chỉ Drafter/Admin cả chiều âm) · smoke 3 domain + label type-10} |
| 7 | Commit + push + cicd-monitor 3-chân-kiềng (CI PASS · mig 69 prod · menu 142 giữ) | lead + `cicd-monitor` | [x] commit **`a8027c0`** PUSH → CI Run **#427 success 5m40s** · cicd **VERDICT=PASS 6/6** (`cicd-verify-a8027c0.md` 277 dòng END-line đủ; return garble #53 lần 5 — đĩa trọn): gate 566 · Mig 69 prod 96 bảng · menu **142 GIỮ** · marker 3-tầng-control-âm · **đo CỜ 13/13/13/2 + `Khkk_G1` control-âm-nội-họ đứng yên + log `0 added + 91 upgraded` khớp dự-đoán-ghi-trước** · label type-10 VN sống prod. Residual MEMORY cicd ACCEPT verified-KEPT; ⚠️ `_INDEX` cicd nay **99,2%** (167B) — slot 51-bis GẤP |
**⇒ W1 ĐÓNG — synthesis: `w1-synthesis.md` (VERIFIED). Tồn sang wave sau: setup WF tay trước W5 · tài khoản UAT non-Admin (nv.test không tồn tại prod) · slot 51-bis · F-4.**
## Ràng buộc mang theo
- 🔴 Seeder = **UPGRADE-if-exists khuôn `SeedProcurementMasterAccessAsync:2367-2374` + mở rộng vế CanDelete**, chạy SAU revoke (mirror `:2098-2101`) — KHÔNG insert (F-S1, 403 giết dry-run) · CẤM SQL tay (#84).

View File

@ -0,0 +1,32 @@
# W1-SYNTHESIS — Wave W1 KHKK: Schema Mig 69 + Permission + Designer type-10 (S161, 2026-07-29) — VERIFIED
> Lead-verified synthesis (đóng run — dual-accept dạng-1). Chi tiết per-lane: 4 sub-md + cicd-verify cùng cấp.
## KẾT QUẢ: W1 SHIP PROD — cicd VERDICT=PASS 6/6, commit `a8027c0` (30 file, +8.987/22)
- **Schema:** Mig 69 `20260729122015_AddContractSigningPlans` — 7 bảng + 20 index, 0 ALTER bảng cũ; prod 89→**96 bảng**, MIGTOP khớp; database-agent design-review **PASS 8/8 + DB11 0-blocker** (parity 2 DB local tuyệt đối, Down script-proof atomic).
- **Permission:** `MenuKeys.All += KeHoachKyKet` (54→55 key ⇒ policy 216→**220**) + seeder `SeedKeHoachKyKetAccessAsync` UPGRADE-if-exists (+vế CanDelete): prod đo CỜ PRE 13/0/0/0 → POST **13/13/13/2** cả 7 key, control ÂM nội-họ `Khkk_G1` đứng yên, log `0 added + 91 upgraded` khớp dự-đoán-ghi-trước. Menu-row **142 GIỮ** (policy-key ⟂ menu-key).
- **CodeGen:** `ContractSigningPlanCodeGenerator``KHKK/{YYYY}/{Seq:D3}` (anh OK @S161), SERIALIZABLE, `WorkflowAppCodeSequences` dùng chung.
- **Designer type-10:** deep-link `/system/approval-workflows-v2/ContractSigningPlan` + label VN từ BE (`applicableTypeLabel` sống prod) + 2 checkbox early-finalize bị rào **3 tầng** (render + payload FE + ép-false BE create-path — 2 đường anh phán "PHÁ VỠ" S155). Prod `ApplicableType=10` = 0 workflow (đúng — dựng tay trước W5).
- **Test:** 562 → **566 PASS/0 fail** (4 test mới, fault-inject 2 chiều chứng răng; gồm phép đo mã phiếu A6 với vế clock-2027 chống năm-hardcode).
- **Review:** reviewer PWF 10 issue (1H/3M/4m/2L) → **disposition từng dòng: 8 fix cùng commit + 2 giữ-có-lý-do** (F-1 đo-CỜ → ĐÃ ĐÓNG bởi cicd chân-5; F-4 UTC-year/D3-tràn kế thừa y PE prod).
## VẬN HÀNH — #53 cắn 5/7 lượt spawn, THIỆT HẠI 0 BYTE
| Lượt | Vai | Return | Đĩa |
|---|---|---|---|
| wf_7d6fb81b lane BE | implementer-backend | chết (empty) | code sống 40% (Domain trọn), 0 sub-md → relaunch-cắt-gọt |
| wf_7d6fb81b lane FE | implementer-frontend | CLEAN | sub-md 7.9KB + build tươi verify |
| wf_f8c806d2 lane BE | implementer-backend | chết (empty) | **sub-md 6.2KB ghi-từng-mục cứu TRỌN** (tới hết Mig 69 apply 2 DB) → lead solo đuôi |
| wf_a95c9909 lane test | test-specialist | chết (empty) | sub-md 10KB — chết LÚC ĐỢI full-suite, việc thật xong |
| wf_a95c9909 lane DB | database-agent | CLEAN | sub-md 21KB |
| reviewer | reviewer | garble → **SendMessage-resume về SẠCH** | sub-md đủ 6 trục |
| cicd-monitor | cicd-monitor | garble | **cicd-verify 15KB đủ END+VERDICT-line** |
Bài đắt nhất wave: **"ghi-đĩa-TỪNG-MỤC trong lúc làm" là biến số quyết định** — lượt BE-1 dồn cuối mất trắng narrative; mọi lượt sau ép ghi-từng-mục đều cứu trọn. Xác nhận lần thứ N bài S123/S158: chống #53 = thiết kế ARTIFACT, không phải prompt.
## TỒN SANG WAVE SAU
1. **Setup thủ công TRƯỚC W5** (sau W2/W3 cũng được, type-10 đã sống): dựng workflow type=3 3-trạm + type=10 3-trạm (PMH→CCM→CEO) qua Designer — type-10 vào bằng deep-link (menu cố ý không đổi). Acceptance "tạo + xoá Level chưa chữ ký" chấm lúc đó.
2. **Tài khoản UAT `nv.test@` KHÔNG tồn tại prod** (cicd phát hiện — demo-seed gated #51/#75): phép 2-bearer gotcha #44 không chạy được ⇒ W2+ cần chọn 1 tài khoản non-Admin THẬT làm mốc, hoặc anh cho tạo user test.
3. `cicd-monitor/archive/_INDEX.md` **99,2% cap (167B còn)** — slot (51-bis) của anh giờ GẤP thật.
4. F-4 (UTC-year + D3 tràn 1000) ghi nhận — xử chung với PE khi làm mốc đổi năm.

View File

@ -0,0 +1,26 @@
# RUN — W2 KHKK: CRUD phiếu nháp + căn cứ b.8-9 + FE 3 page ×2 app (S161, 2026-07-29)
> Wave 2/6 dry-run toàn trình. Spec: `../2026-07-29-S160-khkk-dryrun-plan/spec-wave-w2-crud-nhap-29-07-2026.md`. W1 ĐÃ SHIP (`a8027c0`, cicd PASS 6/6 — synthesis `../2026-07-29-S161-khkk-w1-schema/w1-synthesis.md`).
> **Gate 5-anchor: PASS 5/5 @S161** (flatten-trap :427-439 · guard+snapshot :53-62 · guard-type-trọn :258-267 · staticMap-comment content-found @:2215 [drift từ 2207 do commit W1 — neo content] · `KeHoachKyKet ∈ All:180` THẬT).
> ⚠️ Lệch phát hiện @gate: entity comment W1 "gen mã lúc Submit" ≠ spec W2 "gen lúc CREATE" (acceptance POST trả maKeHoach) — **SPEC THẮNG**, worker sửa comment entity cùng lượt.
## taskList snapshot
| # | Stage | Vai / cách | Trạng thái |
|---|---|---|---|
| 1 | Đợt-1a BE: mega-file `ContractSigningPlanFeatures.cs` (Create+auto-Lines+MaKeHoach@CREATE · UpdateDraft · Get/List/pendingMe+inbox-precompute · Dossier UPSERT/DELETE · Attachments · DELETE allow-list · picker PE-chờ-lập-KH) + `ContractSigningPlansController` authz 2-tầng per-action | hmw `implementer-backend` | [ ] |
| 2 | Đợt-1b FE: `pages/khkk/` 3 page + types ×2 app + 4-place mirror (routes + staticMap re-point 6 leaf khỏi coming-soon + menuKeys) + build ×2 + SHA-pair | hmw `implementer-frontend` | [ ] |
| 3 | Đợt-2: test-specialist (≥2 test PIN: `ContractSigningPlansController_EveryWriteEndpoint_HasAuthorizePolicy` + `CreateContractSigningPlan_FromNonApprovedPe_Throws`) | hmw `test-specialist` | [ ] |
| 4 | Lead: build ×2 + suite + acceptance §③-B sweep | lead | [ ] |
| 5 | Reviewer adversarial (CRUD endpoints POST/PUT/DELETE — bắt buộc) | `reviewer` | [ ] |
| 6 | Commit + push + cicd (3-chân-kiềng + 2-bearer NẾU có tài khoản non-Admin — nv.test KHÔNG tồn tại prod, xem w1-synthesis tồn-2) | lead + `cicd-monitor` | [ ] |
## Ràng buộc mang theo
- 🔴 CẤM copy phần DUYỆT của Proposal (bẫy flatten :427-439 — OR-of-N thành AND; duyệt = W3 con-trỏ-đôi mirror PE).
- 🔴 Guard workflow-type copy TRỌN :258-267 (cả nhánh NotFound), đổi đích `ContractSigningPlan=10`.
- 🔴 Authz 2 tầng (#82): class `[Authorize]` + per-action `Policy="KeHoachKyKet.{Action}"` — grep ≥4.
- 🔴 409-khoá-vĩnh-viễn: DELETE allow-list mở NGAY W2 (M6) + tạo-lại-sau-TuChoi/xóa được (#57).
- 🔴 FE 4-place ×2 app SHA-pair; 6 leaf hết coming-soon (grep = 0 cả 2 app).
## Stages
(cập nhật theo tiến độ)