@ -47,10 +47,10 @@ Read-only CI/CD + post-deploy verifier SOLUTION_ERP. Polls Gitea Actions API, ve
- ** Gitea: ** `git.baocaogiaoduc.vn/vietreport-admin/solution-erp` · workflow `.gitea/workflows/deploy.yml` · paths-ignore `['docs/**','**/*.md','.claude/skills/**']`
- ** Gitea: ** `git.baocaogiaoduc.vn/vietreport-admin/solution-erp` · workflow `.gitea/workflows/deploy.yml` · paths-ignore `['docs/**','**/*.md','.claude/skills/**']`
- ** Prod: ** api / admin / eoffice `.solutions.com.vn` · SSH `ssh vietreport-vps` ( Administrator , id_ed25519 ) · IIS site phys paths ( S42 verified ) : API `C:\inetpub\solution-erp\api` · admin `\fe-admin` · user `\fe-user` ( 3 sites Started ). DB `.\SQLEXPRESS` / `SolutionErp` / `vrapp` SQL-auth . **Conn string key = `ConnectionStrings.Default` (NOT `DefaultConnection`!)** — read pw from prod appsettings . Production . json when `$env:PROD_DB_PASSWORD` empty .
- ** Prod: ** api / admin / eoffice `.solutions.com.vn` · SSH `ssh vietreport-vps` ( Administrator , id_ed25519 ) · IIS site phys paths ( S42 verified ) : API `C:\inetpub\solution-erp\api` · admin `\fe-admin` · user `\fe-user` ( 3 sites Started ). DB `.\SQLEXPRESS` / `SolutionErp` / `vrapp` SQL-auth . **Conn string key = `ConnectionStrings.Default` (NOT `DefaultConnection`!)** — read pw from prod appsettings . Production . json when `$env:PROD_DB_PASSWORD` empty .
- ** SSH → PS quoting ( S42 lesson ) : ** nested bash → ssh → powershell mangles `$var` / `\"` . Use `iconv UTF-16LE | base64` → `powershell -EncodedCommand $B64` . Single-quote literal paths .
- ** SSH → PS quoting ( S42 lesson ) : ** nested bash → ssh → powershell mangles `$var` / `\"` . Use `iconv UTF-16LE | base64` → `powershell -EncodedCommand $B64` . Single-quote literal paths .
- ** Tests baseline: ** **141 PASS** ( 58 Domain + 83 Infra ) S42 ( was 130 ). CI gate runs both test projects BEFORE build / deploy ( `deploy.yml` L62 + L71 ) → status = success ⟹ test gate passed . Local grep undercounts ( Theory / InlineData ) — trust CI conclusion . Phase 9 UAT mode skip per chunk OK .
- ** Tests baseline: ** **144 PASS** ( 58 Domain + 86 Infra ) S42 Run #365 (+ 3 SetWorkflow ; was 141 ). CI gate runs both test projects BEFORE build / deploy ( `deploy.yml` L62 + L71 ) → status = success ⟹ test gate passed . Local grep undercounts ( Theory / InlineData ) — trust CI conclusion . Phase 9 UAT mode skip per chunk OK .
- ** Mig latest repo: ** **Mig 41 `20260530021936_WireWorkflowAppsApprovalV2`** ( S42 P11-A ). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` . Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC TOP 5` .
- ** Mig latest repo: ** **Mig 41 `20260530021936_WireWorkflowAppsApprovalV2`** ( S42 P11-A ). Path `src/Backend/SolutionErp.Infrastructure/Persistence/Migrations/` . Prod check `sqlcmd __EFMigrationsHistory ORDER BY MigrationId DESC TOP 5` .
- ** Bearer: ** admin `admin@solutions.com.vn/Admin@123456` ( full ) · UAT `nv.test@solutions.com.vn/TestUser@123456` ( Drafter CCM , gotcha #44 check )
- ** Bearer: ** admin `admin@solutions.com.vn/Admin@123456` ( full ) · UAT `nv.test@solutions.com.vn/TestUser@123456` ( Drafter CCM , gotcha #44 check )
- ** Bundle hash live S42: ** admin `BLA09-qv ` · user `CXvejOE- ` ( Run #250 ). Prev S38 admin `cWAXid0q ` · user `CX79e2kZ` . Bundle size ~ 800KB / 750KB gz .
- ** Bundle hash live S42: ** admin `6D4k-aRi ` · user `DkME-974 ` ( Run #365 sha 75df04e ). Prev admin `BLA09-qv ` · user `CXvejOE-` ( #250/e7b66cd ) . Bundle size ~ 800KB / 750KB gz .
## 🔑 Critical config (flag commit nếu tái xuất)
## 🔑 Critical config (flag commit nếu tái xuất)
Node CI `20.x` ( `feedback_node_cicd` ) · MediatR `12.4.1` ( gotcha #1 , flag `Version="14` ) · Swashbuckle `6.9.0` ( gotcha #2 ) · act_runner manual checkout ( #39 ) · npm cache DISABLED ( #40 , flag `cache: npm` )
Node CI `20.x` ( `feedback_node_cicd` ) · MediatR `12.4.1` ( gotcha #1 , flag `Version="14` ) · Swashbuckle `6.9.0` ( gotcha #2 ) · act_runner manual checkout ( #39 ) · npm cache DISABLED ( #40 , flag `cache: npm` )
@ -67,7 +67,8 @@ BE (test+build) ~90s · FE × 2 ~60s/app · deploy ~30s · **total ~3min code /
## 📅 Recent runs (FIFO — older → archive/git)
## 📅 Recent runs (FIFO — older → archive/git)
- **2026-05-30 Run #250 sha=`e7b66cd ` PASS ~4m07 s (S42 P11-A wire ApproveV2+LevelOpinions 4 WorkflowApps ):** 1 commit BE+FE× 2+Mig41+Tests. Status=success iter3. Bundle rotate admin `cWAXid0q→BLA09-qv` + user `CX79e2kZ→CXvejOE-` . **Mig 41 auto-applied prod** (latest=`20260530021936_WireWorkflowAppsApprovalV2` ). Tables 84→**90** (+5: Leave/Ot/T ravel/V ehicleRequest LevelOpinions + WorkflowAppCodeSequences — ALL EXIST). 4 new endpoint smoke 200 auth ( leave/ ot/travel/vehicle-requests) + unauth 401 (route exists) + POST .../approve=411 (route reg ). health live/ ready 200. **Stage 4.6 seed gate PASS** (gotcha #51 ): 4 WF seeded prod despite DemoSeed:Disabled — QT-NP/OT/CT/XE-V2-001 AppType=5/6/7/9, verified call-site L142-145 OUTSIDE `if(!demoSeedDis abled)` gate. Test gate 141 (CI runs both proj pre-deploy). Note: table count 90 vs spec-expected 89 = baseline-count diff, NOT missing table (all 5 present). Stale doc drift deploy.yml comments "54/17 test" (cosmetic, flag em main) . Tag `[s42, run250 , pass, p11a-approvev2- workflowapps ]` .
- **2026-05-30 Run #365 sha=`75df04e ` PASS ~4m05 s (S42 P11-A fix workflow picker 2-bug + SetWorkflow endpoint, NO migration ):** Code commit 11 files (4 BE controllers + 2 App features `LeaveOtApprovalFeatures` /`TravelVehicleApprovalFeatures` +125 lines + 2 FE `WorkflowAppDetailPage` × 2 + 1 test +79 lines). Status=success iter5 (started 10:15:45). **Bundle rotate admin `BLA09-qv→6D4k-aRi` + user `CXvejOE-→DkME-974`** (both changed ✓ FE fix shipped, verified AFTER status=success). +4 endpoint `PUT /api/{leave,ot,t ravel,v ehicle-bookings}/{id}/workflow` (`Set{Module}WorkflowCommand` , route `[HttpPut("{id:guid}/workflow")]` body record `SetWorkflowBody(Guid ApprovalWorkflowId)` ). Unauth smoke leave+ ot/workflow → **401** (route exists, NOT 404 ✓ ). health live+ ready 200 Healthy. Test gate **144** (CI both proj pre-deploy; grep undercounts InlineData=14 Fact at WorkflowAppApproveV2Tests). **NO migration** → skipped Stage 4.6 seed (verified #250 ). **NAMING RECONCILE:** Gitea task IDs are real #364 (e7b66cd, mem-l abe led "#250 ") + #365 (this). Going forward use actual Gitea task id. **HEADS-UP em main:** follow-up commit `e47ef1d` (FE-User ProposalCreatePage workflow dropdown shape, latent S37 bug) pushed 10:19:17 DURING poll — NOT yet triggered CI run, will redeploy FE shortly (bundle may re-rotate). Out of scope this verdict . Tag `[s42, run365 , pass, p11a-set workflow]` .
- **2026-05-30 Run #364 (mem #250 ) sha=`e7b66cd` PASS ~4m07s (S42 P11-A wire ApproveV2+LevelOpinions 4 WorkflowApps):** 1 commit BE+FE× 2+Mig41+Tests. Status=success iter3. Bundle rotate admin `cWAXid0q→BLA09-qv` + user `CX79e2kZ→CXvejOE-` . **Mig 41 auto-applied prod** (latest=`20260530021936_WireWorkflowAppsApprovalV2` ). Tables 84→**90** (+5: Leave/Ot/Travel/VehicleRequest LevelOpinions + WorkflowAppCodeSequences — ALL EXIST). 4 new endpoint smoke 200 auth (leave/ot/travel/vehicle-requests) + unauth 401 (route exists) + POST .../approve=411 (route reg). health live/ready 200. **Stage 4.6 seed gate PASS** (gotcha #51 ): 4 WF seeded prod despite DemoSeed:Disabled — QT-NP/OT/CT/XE-V2-001 AppType=5/6/7/9, verified call-site L142-145 OUTSIDE `if(!demoSeedDisabled)` gate. Test gate 141 (CI runs both proj pre-deploy). Note: table count 90 vs spec-expected 89 = baseline-count diff, NOT missing table (all 5 present). Stale doc drift deploy.yml comments "54/17 test" (cosmetic, flag em main). Tag `[s42, run250, pass, p11a-approvev2-workflowapps]` .
- **2026-05-28 Run #247 sha=`e54a22d` PASS 3m25s (S38 SKELETON 5-plan combo Mig 39+40 dual):** Push 1 commit mega `Domain+App+Infra+Api+FE× 2` . ALL PASS. Bundle rotate admin `CGueDk22→cWAXid0q` + user `CEt0QRgX→CX79e2kZ` . Mig 39+40 dual auto-applied startup (90830→90839). 6 endpoint smoke 200 (leave/ot/travel/vehicle/it-tickets/hr-dashboard `totalEmployees=33 male=17 female=16` ). 6 new tables + 8 menu seeded. 0 regression. Fastest S38 deploy. Tag `[s38, run247, pass, skeleton-combo]` .
- **2026-05-28 Run #247 sha=`e54a22d` PASS 3m25s (S38 SKELETON 5-plan combo Mig 39+40 dual):** Push 1 commit mega `Domain+App+Infra+Api+FE× 2` . ALL PASS. Bundle rotate admin `CGueDk22→cWAXid0q` + user `CEt0QRgX→CX79e2kZ` . Mig 39+40 dual auto-applied startup (90830→90839). 6 endpoint smoke 200 (leave/ot/travel/vehicle/it-tickets/hr-dashboard `totalEmployees=33 male=17 female=16` ). 6 new tables + 8 menu seeded. 0 regression. Fastest S38 deploy. Tag `[s38, run247, pass, skeleton-combo]` .
- **2026-05-28 Run #246 sha=`de1c378` PASS 3m53s (S37 Proposal Mig 37+38):** Bundle admin `C9kzTTmq→CGueDk22` + user `CC4DQ-Tr→CEt0QRgX` . Mig 38 AddProposals + 37 ExtendApplicableType. `/api/proposals` 200 empty + workflow `QT-DX-V2-001` ApplicableType=4 seed + 4 Off_DeXuat menu. Stage 4.6 sample seed INFRASTRUCTURE-gated correct (gotcha #51 ). Tag `[s37, run246, pass, proposal-v2]` .
- **2026-05-28 Run #246 sha=`de1c378` PASS 3m53s (S37 Proposal Mig 37+38):** Bundle admin `C9kzTTmq→CGueDk22` + user `CC4DQ-Tr→CEt0QRgX` . Mig 38 AddProposals + 37 ExtendApplicableType. `/api/proposals` 200 empty + workflow `QT-DX-V2-001` ApplicableType=4 seed + 4 Off_DeXuat menu. Stage 4.6 sample seed INFRASTRUCTURE-gated correct (gotcha #51 ). Tag `[s37, run246, pass, proposal-v2]` .
- **Archived Run #359/#243/#242/#241/#240 + S35/S36 startup → `archive/2026-05-q4.md` + git d2f52ba (S40 curate):** Run #359 G-O2 Meeting Mig 36 · #243 HrmConfig BE 16 endpoint (BE-only bundle unchanged anti-pattern verify) · #242 FE inline forms 5 satellite · #241 Mig 35 HRM foundation · #240 satellite CRUD. Discovery #7 path-filter eval/** + #8 collection `proj_*` . KEY absorbed in essentials/Stage sections above.
- **Archived Run #359/#243/#242/#241/#240 + S35/S36 startup → `archive/2026-05-q4.md` + git d2f52ba (S40 curate):** Run #359 G-O2 Meeting Mig 36 · #243 HrmConfig BE 16 endpoint (BE-only bundle unchanged anti-pattern verify) · #242 FE inline forms 5 satellite · #241 Mig 35 HRM foundation · #240 satellite CRUD. Discovery #7 path-filter eval/** + #8 collection `proj_*` . KEY absorbed in essentials/Stage sections above.