wal: flush 20260727T1250

This commit is contained in:
pqhuy1987
2026-07-27 12:50:05 +07:00
parent dfbaeb1e76
commit 3ec2f116a2
4 changed files with 180 additions and 6 deletions

View File

@ -51,7 +51,9 @@ chain:
[x] A-wave5 + lead-vá cuối: F1 transaction ✓ · F2 thu-hẹp-purge ✓ · F3 dây FE `api.put`=1 hit ✓. **Lead tự vá 3 chỗ agent để lại**: (1) `FAULT_INJECT_OFF=false` — cờ tiêm-lỗi bỏ quên khiến `if (FAULT_INJECT_OFF && …)` LUÔN sai ⇒ guard tầng-2 KHÔNG BAO GIỜ chạy (2 test F2 đỏ vì đúng cái này) · (2) TS2345 `LevelOrder` vs `number` `ApprovalWorkflowsV2Page:709` · (3) F11 test xanh-giả → thêm chứng-nhân seed 1 PE ChoDuyet
[!] 🔴 BÀI HỌC ĐO: lead đo `tsc -p tsconfig.json` → exit 0 → suýt báo "FE sạch". SAI — `tsconfig.json` chỉ là file **references**, không check file nào; config THẬT = `tsconfig.app.json` (chạy đúng nó ra 1 lỗi thật). **Phép đo rỗng-nghĩa đọc y hệt PASS.** Diagnostics của hệ thống đúng, lead sai
[x] 🚀 **A-DEPLOY XONG** — commit `b1bae77`, push `871ac0a..b1bae77 → main` exit 0. **F8 gate 2 lớp ĐỀU QUA**: staging không còn `??` ở Migrations/+tests/ · `git show --stat HEAD` có ĐỦ 2 file migration (`.cs` 29 dòng + `.Designer.cs` 6410 dòng). Test lúc đẩy: **551 PASS / 0 FAIL**
[!] wf: A-cicd-verify — cicd-monitor đang xác minh prod: Gitea run `b1bae77` · **`__EFMigrationsHistory``20260727033522` chưa** · **cột `AllowApproverDelete` có thật chưa** · smoke 7 module chống `Invalid column name` · `PUT /approval-workflows-v2/{id}` phải 401/403 KHÔNG 404 · bundle hash ×2 app
[x] **A-CICD PASS 6/6**`cicd-verify-dot1.md`: Gitea run **#416 success 5m31s**, test gate **551 PASS (45+506) 0 fail** KHỚP CHÍNH XÁC số local · **mig `20260727033522` ở TOP `__EFMigrationsHistory` prod** · cột `AllowApproverDelete` bit NOT NULL default 0 — **history ⟷ cột KHỚP, không lệch ⇒ kịch bản F8 LOẠI TRỪ** · smoke 8/8 HTTP 200, 0 `Invalid column name` · **phép mạnh nhất: `GET /approval-workflows-v2` materialize cột mới 54 lần từ DB thật** = chứng khép kín model⟷DB · PUT mới → **401** (control route bịa → 404 ⇒ discriminator sạch) · bundle JS rotate ×2 app, Last-Modified TRONG cửa-sổ deploy, chuỗi `allowApproverDelete` CÓ trong cả 2 bundle đã ship (#77 byte-verify) · health live+ready 200. `sys.tables` giữ **89**
[ ] A-baseline cần cập-nhật @close: test **532 → 551** · mig mới nhất **Mig 67 → Mig 68** (`docs/STATUS.md` + skill `ef-core-migration` row cuối)
[~] wf: A-cicd-verify — cicd-monitor đã xong: Gitea run `b1bae77` · **`__EFMigrationsHistory``20260727033522` chưa** · **cột `AllowApproverDelete` có thật chưa** · smoke 7 module chống `Invalid column name` · `PUT /approval-workflows-v2/{id}` phải 401/403 KHÔNG 404 · bundle hash ×2 app
[ ] ⚠️ Deploy này mang **migration mới** `20260727033522_AddPeAllowApproverDelete` lên PROD — AddColumn bit default false, additive an-toàn, nhưng LÀ đổi schema prod thật
[~] wf: A-S4-đợt1 hmw — run-id engine `wf_f1bfea65-ed9` · run-folder `.claude/workflows/runs/2026-07-27-S155-pe-delete-approver/` · 2 task: implementer-backend (F6 schema+mig+UpdateCommand+validator T1/T2+authz+F-5a+F-6+F-10) · implementer-frontend (F-11 5 dây, bẫy :605). Chết giữa chừng ⇒ /tiep §4 relaunch ĐÃ-CẮT-GỌT, đọc sub-*.md trên đĩa trước
[ ] A-S4-đợt1 wave 2 (sau khi wave 1 xanh): test-specialist F-12..F-16 + reviewer soi diff

View File

@ -1,7 +1,8 @@
# CI/CD Monitor Agent — Persistent Memory
- **07-23 verify 4510cea (App: chuẩn-hóa mã dự-án normalize + PE attach-gate FE both-apps) [em-main spawn, return CLEAN]:** VERDICT **PASS 5/5** — Run **#407** (id=521) success ~5m36s (17:11:54→17:17:30+07); gate **532 EXACT từ log** (45 Domain + 487 Infra, 0 fail/skip) — **+4 vs prev run #406/8b6df0a (483I)** = 4 `ProjectCodeNormalizationTests` (delta-proof: dotnet summary KHÔNG in tên-test riêng → dùng delta prev-run + build-success + all-pass). NO-Mig: `git diff 8b6df0a..4510cea -- *Migrations*` EMPTY + prod history-top `AddPeApprovedBudgetSnapshot` (Mig 67, từ S133 KHÔNG phải push này) = repo-HEAD unchanged + sys.tables **89** — code-only no-drift by-construction. **Bundle JS rotate cả 2 app / CSS FROZEN cả 2** (đúng dự-đoán — PeDetailTabs.tsx ×2 = pure button-gating logic, no new Tailwind utility): admin js `DGPE6Nkb`→**`B2j1LQ-v`** css `CBzUlgOA` frozen · eoffice js `DlTwAgJj`→**`C3wbJegk`** css `BHsBUA8e` frozen; real-size 1.660.902/1.567.232B, LM 17:16:01/17:16:54+07 in-window; SPA-trap control fake-hash `index-ZZfakehash0.js`=900B **ct=text/html** (discriminator OK). smoke 4×200 (health/live+ready, admin, eoffice). Baseline shift: **Infra 464(S118)→483(run406)→487**, Mig-latest = **Mig 67** ("Mig 66" essentials-line STALE — updated). Pre-deploy snapshot captured WHILE running (đúng bài #242 verify-post-success). Tag `[run-407, pass-5-5, js-rotate-css-frozen, delta-proof-+4, code-only-no-mig]`
- **07-27 verify b1bae77 (Workflow: quy-trình duyệt TẠI CHỖ + cờ F6 `AllowApproverDelete` đợt-1) [S155, MIG-BEARING deploy, CLEAN-return]:** VERDICT **PASS 6/6** — Run **#416** (id=529) success **5m31s** (12:37:18→12:42:49+07); gate **551 EXACT từ log** (45 Domain + **506** Infra, 0 fail/skip) — **+19 vs run #407 (532)**, **KHỚP CHÍNH XÁC số lead đo local (551)** = cross-check 2-nguồn. **Mig 68 `20260727033522_AddPeAllowApproverDelete` VERIFIED-APPLIED-PROD** (AddColumn `AllowApproverDelete` bit NOT NULL default `(CONVERT([bit],(0)))` trên `ApprovalWorkflowLevels`; history-TOP + `INFORMATION_SCHEMA.COLUMNS` **cả 2 cùng có ⟹ không lệch**; sys.tables **89** giữ nguyên đúng AddColumn-no-new-table). 🔑 **Reviewer FLAG F8 (mig-file rớt khỏi commit ⟹ `Invalid column name` hạ 7 module V2) LOẠI TRỪ bằng 3 lớp:** (i) pre-deploy baseline 12:38 history-top còn `AddPeApprovedBudgetSnapshot` ⟹ mig áp TRONG cửa-sổ này không phải sẵn có; (ii) smoke 8/8 HTTP 200 `Invalid column name`=0 (PE·HĐ·Đề-xuất·Nghỉ-phép·Tăng-ca·Công-tác·Đặt-xe + AwV2); (iii) **phép mạnh nhất = `GET /api/approval-workflows-v2` trả `allowApproverDelete` ×54 materialize qua EF từ DB thật** — DB thiếu cột thì chính query này đã ném. Endpoint mới `PUT /api/approval-workflows-v2/{id}` no-token → **401** + **control route bịa → 404** (discriminator sạch, 401 có nghĩa). Bundle **JS rotate CẢ 2** (admin `hHISK1Ig`→**`CiUBEEJr`** css `CBzUlgOA`→**`DX5ew0wg`** rotate; eoffice `CJeXZso2`→**`DFh7GK0t`** css `BHsBUA8e` **FROZEN** = #69-REFINE lành tính, 2 file fe-user là logic/type no-new-utility) real-size 1.670.035/1.570.257B, LM 12:41:28/12:42:22+07 **in-window**; byte-verify #77 marker `allowApproverDelete` admin ×7 / eoffice ×1 ⟹ đúng mã F6 đã ship. SPA-trap control `ct=text/html` 900/876B. health live+ready 200. Tag `[run-416, pass-6-6, mig-bearing, F8-averted-3-layer, col-materialize-x54, js-rotate-both, gate-551-khớp-local]`
- _(**S135 #407 `4510cea` mã-dự-án normalize + PE attach-gate GO 5/5** — gate 532 [45+487, +4 delta-proof]; NO-Mig `git diff -- *Migrations*` EMPTY + history-top unchanged; js-rotate/css-frozen ×2 · verbatim → `archive/2026-07.md` @S155-curate)_
- _(**S134 #399 `6664a61` PE lũy-kế tạm-tính (0-mig) GO 5/5** — gate 528 [45+483, +8 PePendingAccumulation]; js+css rotate ×2 admin `BVCukFP5`/`CBzUlgOA` eoffice `DoxyEOxh`/`BHsBUA8e`; byte-verify #77 urllib-BYTES; 🔑 **ct=text/html discriminator SẠCH HƠN size-919B** [shell size drift per-build]; `body.count(marker.encode())` bulletproof cp1252 · verbatim → `archive/2026-07.md` via `_INDEX`)_
- _(**S133 #398 `d4fbced` PE budget-freeze + Mig 67 `AddPeApprovedBudgetSnapshot` APPLIED-PROD GO 5/5** — gate 520 [45+475]; 11-col ApprovedBudget\* + backfill 18/18 DaDuyet + 89-table; js+CSS rotate ×2 [badge utility-class → CSS content-hash đổi, benign #69]; python text=True crash cp1252 → text=False bytes+json.loads · verbatim → `archive/2026-07.md` via `_INDEX`)_
@ -61,9 +62,9 @@ cicd-spawn đôi khi trả memory-curation slice ("Compressing S112/S111") thay
- **Gitea:** `git.baocaogiaoduc.vn/vietreport-admin/solution-erp` · workflow `.gitea/workflows/deploy.yml` · paths-ignore 7-entry (D10 S111 #495): `['docs/**','**/*.md','.claude/skills/**','.claude/agent-memory/**','.claude/workflows/runs/**','.gitignore','scripts/**.md']`. Anon API works (public repo) when GITEA_TOKEN absent.
- **Prod:** api/admin/eoffice `.solutions.com.vn` · SSH `ssh vietreport-vps` (Administrator, id_ed25519) · IIS phys paths: API `C:\inetpub\solution-erp\api` · admin `\fe-admin` · user `\fe-user`. DB `.\SQLEXPRESS`/`SolutionErp`/`vrapp` SQL-auth. **Conn key = `ConnectionStrings.Default` (NOT `DefaultConnection`)**. DB pw = `buKL3TGBkD0wDDbYVw65QeX9` (User Id=`vrapp`; Password field has NO `vrapp/` prefix S89 login-failed when prefix included; read verbatim from prod `appsettings.Production.json` ConnectionStrings.Default when `$env:PROD_DB_PASSWORD` empty). skill-doc path `C:\inetpub\apps\SolutionErp\Api` STALE.
- **SSHPS quoting (S42):** nested bashsshpowershell mangles `$var`/`\"` use `iconv UTF-16LE | base64` `powershell -EncodedCommand $B64`; OR write ps1-file + `powershell -File $(cygpath -w)`. sqlcmd over SSH direct `-W -h -1` pw-inline. sys-catalog string-concat `COLLATE DATABASE_DEFAULT` (collation conflict).
- **Tests baseline:** **532 PASS** (45 Domain + 487 Infra · 0 fail/skip; run #407 `4510cea` 07-23; prior climb 528/520/509/505/501/495/486/458/440/421). Phase 9 UAT skip OK. 🔑 **Concrete count via web-UI log `https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/{run_number}/jobs/0/logs` (~18KB, NO `/api/v1/` prefix — api/v1 runs+tasks logs BOTH 404) → per-project `Passed! - Failed: 0, Passed: N, Skipped: 0`. Delta-proof new-tests = compare prev-run count (dotnet summary hides names). status=success alone ⟹ gate-passed (tests pre-deploy).**
- **Mig latest repo: Mig 67 `AddPeApprovedBudgetSnapshot`** (`20260717032812`, S133 `d4fbced` PE freeze-budget 11-col AddColumn + backfill 18/18, no-new-table; VERIFIED-APPLIED-PROD history-top + sys.tables **89**). Prev Mig 66 `AddPeApprovedPriceRange` / 65 backfill-invariant / 62 `ExpandSupplierFields` (full table docs/CLAUDE.md). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` (67 `.cs` excl Designer/Snapshot). Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC`. **`sys.tables`(is_ms_shipped=0)=89** AddColumn/data-only/enum-additive don't change count; no-new-table commit 89 correct, don't FAIL. **NO-Mig proof = history NOT-advance + empty `git diff <base>..<head> -- '*Migrations*'`.**
- **Bundle hash live:** ship-baseline = run #407 (07-23) admin js `B2j1LQ-v`/css `CBzUlgOA` · eoffice js `C3wbJegk`/css `BHsBUA8e` (real-size 1,660,902/1,567,232b; LM 17:16:01/17:16:54+07). PER #69 TWO-MODE = SNAPSHOT-per-run NOT stable-baseline (rotate on real-src, freeze byte-id on 0-src) ALWAYS re-snapshot LIVE post-success; **ship-proof = LM-in-window + real-size (vs 900b `ct=text/html` SPA-trap) + marker-grep, NOT hash-delta**. js-rotate/css-frozen = FE-logic-no-style fingerprint (S134-refine: `ct=text/html` cleaner discriminator than 919b, shell size drifts per-build). idrun_number (head_sha-keyed).
- **Tests baseline:** **551 PASS** (45 Domain + 506 Infra · 0 fail/skip; run #416 `b1bae77` 07-27; prior climb 532/528/520/509/505/501/495/486/458/440/421). Phase 9 UAT skip OK. 🔑 **Concrete count via web-UI log `https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/{run_number}/jobs/0/logs` (~18KB, NO `/api/v1/` prefix — api/v1 runs+tasks logs BOTH 404) → per-project `Passed! - Failed: 0, Passed: N, Skipped: 0`. Delta-proof new-tests = compare prev-run count (dotnet summary hides names). status=success alone ⟹ gate-passed (tests pre-deploy).**
- **Mig latest repo: Mig 68 `AddPeAllowApproverDelete`** (`20260727033522`, S155 `b1bae77` AddColumn `AllowApproverDelete` bit NOT NULL def-0 trên **`ApprovalWorkflowLevels`**, no-new-table; VERIFIED-APPLIED-PROD history-top + col-present + sys.tables **89**). Prev Mig 67 `AddPeApprovedBudgetSnapshot` / 66 `AddPeApprovedPriceRange` / 65 backfill-invariant / 62 `ExpandSupplierFields` (full table docs/CLAUDE.md). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` (68 `.cs` excl Designer/Snapshot). Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC`. **`sys.tables`(is_ms_shipped=0)=89** AddColumn/data-only/enum-additive don't change count; no-new-table commit 89 correct, don't FAIL. **NO-Mig proof = history NOT-advance + empty `git diff <base>..<head> -- '*Migrations*'`.**
- **Bundle hash live:** ship-baseline = run #416 (07-27) admin js `CiUBEEJr`/css `DX5ew0wg` · eoffice js `DFh7GK0t`/css `BHsBUA8e` (real-size 1,670,035/1,570,257b; LM 12:41:28/12:42:22+07). PER #69 TWO-MODE = SNAPSHOT-per-run NOT stable-baseline (rotate on real-src, freeze byte-id on 0-src) ALWAYS re-snapshot LIVE post-success; **ship-proof = LM-in-window + real-size (vs 900b `ct=text/html` SPA-trap) + marker-grep, NOT hash-delta**. js-rotate/css-frozen = FE-logic-no-style fingerprint (S134-refine: `ct=text/html` cleaner discriminator than 919b, shell size drifts per-build). idrun_number (head_sha-keyed).
- **Bearer:** admin `admin@solutions.com.vn/Admin@123456` (full) · UAT `nv.test@solutions.com.vn/TestUser@123456` (Drafter CCM, gotcha #44 check).
- **API Serilog log (S118 correction):** real sink = `C:\inetpub\solution-erp\api\logs\solution-erp-YYYYMMDD.log` (lowercase `logs`, rolling daily). skill-runbook path `…\Logs\log-YYYYMMDD.txt` STALE empty grep. MinimumLevel Default=Information (DbInitializer `LogInformation` seed/revoke lines DO persist) Microsoft/System overridden Warning (no "Now listening" INFO). **Startup seed-race audit pattern (durability deploys):** grep this log for revoke-line THEN seeder-line same-second "N added + M upgraded" proves seeder actively flipped rows revoke knocked down (0-upgraded = seeder no-op = FAIL flag).

View File

@ -38,3 +38,8 @@
- **S133 (07-17) verify d4fbced PE budget-freeze [wf_4eadbcf6-c25, return sạch — verdict landed SAU khi lead /pause; harvest-liền lúc notification, lead CHƯA re-verify độc lập]:** VERDICT **GO 5/5** — Run **#398** success ~5.5m (gate **520** = 45D+475I, 0 fail/skip); Mig 67 prod: history-top + **11 cột ApprovedBudget\* exact** + backfill **18/18 phiếu DaDuyet chua=0** + sys.tables **89** no-new-table; bundle rotate ×2: admin js `yCkX-2Bp`→**`3NCdyODe`** css `CXD7q9xH`→**`B--dUHcm`** · eoffice js `DKSD4p9k`→**`CKsoiNCI`** css `CjwZwYJo`→**`BuntB63r`**, real-size 1.657.025/1.563.373B, LM 11:18:42/11:19:36+07 in-window; byte-verify #77: `budgetFrozen`=1 + `Ngân sách chốt tại thời điểm duyệt`=1 cả 2 js mới, old-hash control = 900B SPA-trap 0-hit; smoke 4×200 + PE 401-secured. **Surprise: CSS CŨNG rotate cả 2 app** (spec đoán "CSS có thể frozen") — PeDetailTabs badge sinh utility-class mới → content-hash đổi theo content, benign #69; phá streak bundle-FROZEN S129-S132. Lesson tool: python `capture_output text=True` crash cp1252 trên title CI tiếng Việt → dùng `text=False` bytes + `json.loads(bytes)`; foreground sleep bị chặn → `python time.sleep` poll-loop OK. Tag `[s133, run-398, go-5-5, css-rotate-benign, mig67-backfill-18]`
- **S134 (07-17) verify 6664a61 PE lũy-kế tạm-tính [wf_f366f38d-498 · return CLEAN no-garble] `[engine: opus-worker]`:** VERDICT **GO 5/5** — Run **#399** (id=513) success 5m27s (14:27:29→14:32:56+07); gate **528 EXACT từ log** (45D+483I, +8 PePendingAccumulationTests); Mig 67 top FROZEN + sys.tables 89 (0-mig by-construction, `git diff -- *Migrations*` empty); bundle rotate ×2 admin js `3NCdyODe`→**`BVCukFP5`** css `B--dUHcm`→**`CBzUlgOA`** · eoffice js `CKsoiNCI`→**`DoxyEOxh`** css `BuntB63r`→**`BHsBUA8e`** (FE-src đổi 6 file ⇒ rotate expected; CSS = amber utilities benign #69), real-size 1.659.037/1.565.367B + LM in-window; **byte-verify #77 qua python urllib BYTES**: `pendingPriorPes`=2 + `Tạm tính`=3 + `phiếu trước cùng gói thầu CHƯA duyệt`=2 cả 2 js, control old-hash 900B **ct=text/html** 0-hit; smoke 4×200 + PE 401. Learned: (1) **urllib bytes + `body.count(marker.encode())` = bulletproof cp1252** cho marker tiếng Việt (khác subprocess text=True crash S133); (2) **ct=text/html là SPA-trap discriminator SẠCH HƠN size-919B** (shell size drift per build — 900B lượt này); (3) tasks-API có thể blip empty-200 transient → poll-loop absorb. Poll held-off verify khi running (iter 0-2) đúng bài #242. Tag `[s134, run-399, go-5-5, ct-html-discriminator, urllib-bytes-marker]`
## Run #407 `4510cea` (2026-07-23) — moved from L1 @S155 curate, byte-exact
- **07-23 verify 4510cea (App: chuẩn-hóa mã dự-án normalize + PE attach-gate FE both-apps) [em-main spawn, return CLEAN]:** VERDICT **PASS 5/5** — Run **#407** (id=521) success ~5m36s (17:11:54→17:17:30+07); gate **532 EXACT từ log** (45 Domain + 487 Infra, 0 fail/skip) — **+4 vs prev run #406/8b6df0a (483I)** = 4 `ProjectCodeNormalizationTests` (delta-proof: dotnet summary KHÔNG in tên-test riêng → dùng delta prev-run + build-success + all-pass). NO-Mig: `git diff 8b6df0a..4510cea -- *Migrations*` EMPTY + prod history-top `AddPeApprovedBudgetSnapshot` (Mig 67, từ S133 KHÔNG phải push này) = repo-HEAD unchanged + sys.tables **89** — code-only no-drift by-construction. **Bundle JS rotate cả 2 app / CSS FROZEN cả 2** (đúng dự-đoán — PeDetailTabs.tsx ×2 = pure button-gating logic, no new Tailwind utility): admin js `DGPE6Nkb`→**`B2j1LQ-v`** css `CBzUlgOA` frozen · eoffice js `DlTwAgJj`→**`C3wbJegk`** css `BHsBUA8e` frozen; real-size 1.660.902/1.567.232B, LM 17:16:01/17:16:54+07 in-window; SPA-trap control fake-hash `index-ZZfakehash0.js`=900B **ct=text/html** (discriminator OK). smoke 4×200 (health/live+ready, admin, eoffice). Baseline shift: **Infra 464(S118)→483(run406)→487**, Mig-latest = **Mig 67** ("Mig 66" essentials-line STALE — updated). Pre-deploy snapshot captured WHILE running (đúng bài #242 verify-post-success). Tag `[run-407, pass-5-5, js-rotate-css-frozen, delta-proof-+4, code-only-no-mig]`

View File

@ -18,6 +18,172 @@
---
## Migration nội dung (đọc từ đĩa, file có trong commit)
`20260727033522_AddPeAllowApproverDelete.cs` Up():
```csharp
migrationBuilder.AddColumn<bool>(
name: "AllowApproverDelete", table: "ApprovalWorkflowLevels",
type: "bit", nullable: false, defaultValue: false);
```
→ AddColumn-only, **no new table** (kỳ vọng `sys.tables` giữ 89). Down = DropColumn (reversible).
## Pre-deploy bundle snapshot (chụp LÚC run đang chạy, 12:38)
| App | JS | CSS |
|---|---|---|
| admin | `index-hHISK1Ig.js` | `index-CBzUlgOA.css` |
| eoffice | `index-CJeXZso2.js` | `index-BHsBUA8e.css` |
## Stage 2 — Gitea Actions run (IN PROGRESS)
_(pending)_
- Run **id=529 · run_number=#416 · head_sha `b1bae77c`** — MATCH commit ✅
- created_at `2026-07-27T12:37:18+07:00` · status lúc đo đầu = `running`
- Run URL: https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions/runs/416
- **TERMINAL: `status=success`** · updated `2026-07-27T12:42:49+07:00` · **duration 5m31s** (12:37:18→12:42:49) — trong dải bình thường (~5m30 các run gần đây)
- ⚠️ `conclusion=None` là bình-thường ở Gitea `tasks` API (đã tái-xác-nhận nhiều lần) → tin `status`.
### Test gate — CÓ CHẠY và PASS
Log web-UI `runs/416/jobs/0/logs` (17.856 B tải về), trích nguyên văn:
```
Passed! - Failed: 0, Passed: 45, Skipped: 0
Passed! - Failed: 0, Passed: 506, Skipped: 0
```
**45 Domain + 506 Infra = 551 PASS / 0 FAIL / 0 SKIP**. **KHỚP CHÍNH XÁC số local lead đo (551 = 45+506)**
Baseline dịch: 532 (run #407) → **551** (+19 Infra).
Test gate chạy TRƯỚC build/deploy ⟹ `status=success` ⟹ gate đã qua.
---
## 🔴 Stage 3 — MIGRATION TRÊN DB PROD (kiểm quan trọng nhất) — **PASS**
`sqlcmd` qua `ssh vietreport-vps`, DB `SolutionErp`, user `vrapp`. Output NGUYÊN VĂN:
```
=== TOP3 HISTORY ===
20260727033522_AddPeAllowApproverDelete
20260717032812_AddPeApprovedBudgetSnapshot
20260714035636_AddPeApprovedPriceRange
=== TARGET MIG ROW ===
20260727033522_AddPeAllowApproverDelete
=== COLUMN ===
ApprovalWorkflowLevels|AllowApproverDelete|bit|nullable=NO
=== SYSTABLES ===
89
=== DEFAULT ===
(CONVERT([bit],(0)))
```
**Đối chiếu (đây là điểm F8):**
| Kiểm | Kỳ vọng | Thực tế | KQ |
|---|---|---|---|
| Row `20260727033522_...` trong `__EFMigrationsHistory` | có + ở TOP | **có, ở TOP** | ✅ |
| Cột `AllowApproverDelete` trên `ApprovalWorkflowLevels` | tồn tại, `bit`, NOT NULL | **tồn tại, `bit`, nullable=NO** | ✅ |
| Default constraint | `0` | `(CONVERT([bit],(0)))` | ✅ |
| `sys.tables` (is_ms_shipped=0) | 89 (AddColumn no-new-table) | **89** | ✅ |
| **Nhất quán history ⟷ cột** | cả 2 cùng có | **cả 2 cùng có** | ✅ **KHÔNG lệch** |
🟢 **Kịch bản F8 (model có cột / DB không có ⟹ `Invalid column name` hạ 7 module) KHÔNG xảy ra.**
Baseline TRƯỚC deploy (đo lúc 12:38, run còn chạy): history top = `20260717032812_AddPeApprovedBudgetSnapshot`, chưa có mig mới
→ chứng minh mig được áp **trong** cửa-sổ deploy này, không phải sẵn có từ trước.
Mig repo mới nhất giờ = **Mig 68 `AddPeAllowApproverDelete`** (trước là Mig 67).
---
## Stage 4 — Smoke 7 module V2 — **PASS 8/8**
Bearer admin (`POST /api/auth/login` → HTTP 200, token 468 ký tự). Output thật:
```
PE /api/purchase-evaluations?page=1&pageSize=5 HTTP 200 bytes=5103 InvalidCol=False
HopDong /api/contracts?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
DeXuat /api/proposals?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
NghiPhep /api/leave-requests?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
TangCa /api/ot-requests?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
CongTac /api/travel-requests?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
DatXe /api/vehicle-bookings?page=1&pageSize=5 HTTP 200 bytes=91 InvalidCol=False
AwV2-list /api/approval-workflows-v2 HTTP 200 bytes=41234 InvalidCol=False
```
**0/8 có chuỗi `Invalid column name`**, 8/8 HTTP 200. Kịch bản F8 không tái hiện được.
⚠️ Trung thực về độ mạnh: 6 module Văn-phòng-số trả 91 B (envelope rỗng, chưa có dữ-liệu) nên chỉ chứng minh **query chạy không ném**, chưa chứng minh join sâu vào Levels. Hai phép mạnh thật nằm ở PE (5.103 B có dữ-liệu) và AwV2 (41.234 B) dưới đây.
### 🔑 Phép thử TRỰC TIẾP nhất cho F8 — cột round-trip qua EF
`GET /api/approval-workflows-v2` (endpoint đọc THẲNG bảng `ApprovalWorkflowLevels`):
```
bytes 41234
count allowApproverDelete = 54
count allowApproverFinalize = 54
LEVEL sample: allowApproverDelete= False | order= 1 | keys# 17
```
→ Cột MỚI được EF materialize **54 lần** từ DB thật ra JSON, giá-trị `False` đúng default `0`.
Nếu DB thiếu cột thì chính truy-vấn này đã ném `Invalid column name`**đây là bằng-chứng khép kín model ⟷ DB đồng bộ.**
## Stage 5 — Endpoint MỚI `PUT /api/approval-workflows-v2/{id}` — **PASS (401, không phải 404)**
```
PUT /api/approval-workflows-v2/1111...1111 (KHÔNG token, có body) -> 401
GET /api/approval-workflows-v2/1111...1111 (KHÔNG token, có body) -> 405
--- control: route chắc chắn KHÔNG tồn tại ---
PUT /api/approval-workflows-v2-nonexistent/{id} -> 404
```
→ Route **401** = đã lên + `[Authorize]` chặn đúng. Control route bịa trả **404** ⟹ 404 đúng là tín-hiệu "route chưa lên", nên 401 ở route thật là có nghĩa (discriminator sạch, không phải may).
(405 ở GET chỉ nói `GET {id}` không được map — không liên quan.)
## Stage 6 — Bundle FE — **PASS (deploy thay file thật, không phải cache)**
```
== admin ==
JS pre=index-hHISK1Ig.js post=index-CiUBEEJr.js ROTATED
CSS pre=index-CBzUlgOA.css post=index-DX5ew0wg.css ROTATED
real-js index-CiUBEEJr.js HTTP 200 size=1670035 ct=application/javascript LM=Mon, 27 Jul 2026 05:41:28 GMT
FAKE-ctl index-ZZfakehash0.js HTTP 200 size=900 ct=text/html
== eoffice ==
JS pre=index-CJeXZso2.js post=index-DFh7GK0t.js ROTATED
CSS pre=index-BHsBUA8e.css post=index-BHsBUA8e.css FROZEN
real-js index-DFh7GK0t.js HTTP 200 size=1570257 ct=application/javascript LM=Mon, 27 Jul 2026 05:42:22 GMT
FAKE-ctl index-ZZfakehash0.js HTTP 200 size=876 ct=text/html
```
- **JS ROTATE cả 2 app** ✅ — khớp commit có sửa src cả `fe-admin` (1 file) lẫn `fe-user` (2 file).
- `Last-Modified` **05:41:28 / 05:42:22 GMT = 12:41:28 / 12:42:22 +07****NẰM TRONG cửa-sổ deploy** 12:37:1812:42:49 ✅ (đây mới là ship-proof chính, không phải hash-delta).
- real-size 1.670.035 / 1.570.257 B; bẫy SPA-fallback: hash bịa cũng trả 200 nhưng **`ct=text/html` + 900/876 B** ⟹ discriminator sạch, file thật là JS thật.
- eoffice **CSS FROZEN** = lành tính (#69-REFINE): 2 file fe-user sửa là logic/type, không thêm utility-class Tailwind mới ⟹ CSS byte-identical ⟹ cùng content-hash. Admin CSS rotate vì thêm ô chọn F6 (class mới).
### Byte-verify #77 — mã tính-năng CÓ THẬT trong bundle prod
```
admin size=1670035 allowApproverDelete=7 allowApproverFinalize=11
eoffice size=1570257 allowApproverDelete=1 allowApproverFinalize=5
```
→ chuỗi `allowApproverDelete` hiện diện trong CẢ HAI bundle đã ship ⟹ không chỉ "file mới" mà **đúng mã F6 đã lên**.
## Health
```
/health/live -> 200 b'Healthy'
/health/ready -> 200 b'Healthy'
```
---
## KẾT LUẬN
**CICD: PASS** — 6/6 hạng mục bắt buộc đạt, rủi ro F8 đã loại trừ bằng bằng-chứng trực tiếp trên DB prod.
| # | Hạng mục | KQ |
|---|---|---|
| 1 | Gitea run `b1bae77` + test gate | ✅ #416 success 5m31s · 551 PASS (45+506) 0 fail |
| 2 | 🔴 Mig áp trên DB prod | ✅ `20260727033522_AddPeAllowApproverDelete` ở TOP history |
| 3 | 🔴 Cột có thật | ✅ `bit` NOT NULL default 0 — **khớp history, không lệch** |
| 4 | Smoke 7 module | ✅ 8/8 HTTP 200, 0 `Invalid column name` |
| 5 | Endpoint mới PUT | ✅ 401 (control route bịa = 404) |
| 6 | Bundle FE 2 app | ✅ JS rotate ×2, LM trong cửa-sổ, marker F6 có trong bundle |
Không có mục nào "không truy được". Không có cảnh-báo cần leo thang.
Baseline cập nhật: test **532 → 551**; mig mới nhất **Mig 67 → Mig 68**; `sys.tables` giữ **89**.
<!-- END cicd-verify-dot1 -->