Files
solution-erp/.claude/agent-memory/investigator-codebase/archive/2026-06.gist.md
pqhuy1987 c2d01f0dce
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 5m30s
[CLAUDE] Docs: S152 closeout — bookend hình B trọn 2 đầu + owner (30)(31)(32) + queue memory-ops TRỌN (squash 20 wal:)
- Owner 3-quyết: (30) JUMP để-nguyên-theo-nhịp · (31) 4 persona +NEVER-block (restart ĐÃ THOẢ) · (32) vòng 1→5 AUTO — lô consent gỡ 9 site (5 H1 + ring1-tự-bắt + 3 trio; E-013 EXT)
- Memory-ops TRỌN: A1-A4/D1/D2/R1/B-series — A7 392/392 · mfe 20/20-100% lần đầu · lead-gap drain 24.728→16.485B · strike-ledger + WARN-latch (-Ack = owner-action)
- V4 sleep AUTO đầu: 1 shard thật/16 KÊU · ring4 đầu-đời TRƯỢT-4/5 → 4 fix gist (scribe sub-ring4-close vì return-only)
- Thư model re-stamp: 59ce1d0f → 9c909007 published (G-024a) — adap-report Đính-chính @S152 + sweep 13 bề-mặt LIVE
- Bookend @close: stale 6 FLAG + gap 2 FLAG → vá 8/8; ring2 8/8 ĐẠT (4-A pin-bản-cắt → slot 33) · ring1 48Đ/5T/59-claim
- M9 13 đơn-vị diary (3 S151-deep hồi-tố) · #53 ×10-chắc → tally 60-cận-dưới + errata subject-1b85713
- Session-log 2 run= + completeness-gate 5-vòng ĐẠT · HANDOFF segment S152 (carry 3-đóng/3-mới/23-giữ; slot 33/34)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 01:58:30 +07:00

36 KiB
Raw Blame History

Gist 2026-06 — investigator-codebase (2026-06.md distilled)

distill-gen: 2 (already-distilled — do NOT re-compress). 4-field per record: VIỆC · KẾT-LUẬN (+file:line) · BÀI-HỌC · BẤT-NGỜ. Same-topic merged. Confidence cao/vừa/thấp. Each line ends with a back-resolve substring:"…" (unique Ctrl-F) into 2026-06.md. Covers all 18 records (3 S57bis-era + 12 moved by Harness-9 curate 2026-06-17 + 3 S65-series moved by S71 curate 2026-06-18). 22-marker coverage gate satisfied across this + 2026-05.gist.md.


gotcha #57 family — soft-delete + bare unique index (reachable 500)

  • [cao] gotcha #57 EXTENSION reachability audit · VIỆC: 6 candidates for soft-delete + bare .IsUnique() on Code → recreate-after-delete throws DbUpdateException 500. KẾT-LUẬN: FIX 3 Master = Department/Supplier/Project (Department/Supplier/ProjectConfiguration.cs:18/24/19 bare unique), all CONFIRMED-reachable (DepartmentFeatures.cs:76+125, ProjectFeatures.cs:87+147, CreateSupplierCommand.cs:45+DeleteSupplierCommand.cs:20). SKIP 3 = ContractClause (no Create/Update/Delete handler anywhere — not CRUD-reachable), MeetingRoom (Delete sets IsActive=false NOT IsDeleted, MeetingFeatures.cs:178; Create also && !IsDeleted), EmployeeProfile (Create BLOCKS reuse by design — UserId check sees soft-deleted → throws "Cần khôi phục" :160-163; EmployeeCode auto-gen atomic). Mig 46 = exactly 3 indexes. BÀI-HỌC: every OTHER bare-unique is safe (composite junction, nullable-code already filtered, or no-soft-delete). BẤT-NGỜ: Master's GLOBAL HasQueryFilter(!IsDeleted) MAKES the bug — auto-hides soft-deleted from the Create dup-check so it passes, then the unfiltered index throws 500 — opposite of HRM where the bug needs a manual !IsDeleted; either way the unfiltered index is the fault. · 2026-06.md · substring:"S51 gotcha #57 EXTENSION reachability audit"
  • [cao] add-kind 11-spot stack + bare-unique confirm · VIỆC: add a HrmConfigs kind (Vehicle/Driver). KẾT-LUẬN: HrmConfigs has NO kind-enum/registry backend — 4 separate entities (LeaveType/Holiday/ShiftPattern/OtPolicy), "kind" is FE-only union+route param; adding 1 kind = mirror full entity stack across 11 spots (Domain/Configuration/DbContext×2/Features-region/Controller-4-routes/DbInitializer/MenuKeys+All/Page-KIND_CONFIG/App-route/menuKeys+staticMap). gotcha #57 CONFIRMED still bare: LeaveTypeConfiguration.cs:19 + ShiftPatternConfiguration.cs:19 + OtPolicyConfiguration.cs:22 .IsUnique() lack .HasFilter("[IsDeleted]=0") — only HolidayConfiguration.cs:18 fixed (Mig43) → Vehicle/Driver Code UNIQUE must add the filter from day one. BÀI-HỌC: each kind = its own table (NOT discriminated) → Mig 44 must CREATE TABLE. · 2026-06.md · substring:"S50 P11-C Vehicle+Driver — HrmConfigs add-kind pattern VERIFIED"
  • [vừa] P11-C Vehicle/Driver catalog pre-flight · VIỆC: where to home the catalog. KẾT-LUẬN: extend HrmConfigs (NOT new module) — add Region 5/6 (kind vehicles/drivers); FE = +2 KIND_CONFIG entries; VehicleBooking stays free-text (Office/VehicleBooking.cs:13-19, no VehicleId/DriverId FK). BÀI-HỌC: HRM entities have NO global HasQueryFilter → manual .Where(!IsDeleted) + UNIQUE soft-delete needs .HasFilter("[IsDeleted]=0") (Holiday Mig43 lesson). · 2026-06.md · substring:"P11-C Vehicle+Driver catalog pre-flight"

Permission / authz / seed model

  • [cao] BE authz split — Master write-open · VIỆC: assess making modules visible to all roles (blocks A/B/E/F). KẾT-LUẬN: config controllers gate WRITE behind [Authorize(Roles="Admin")], READ open (HrmConfigs/Catalogs/MeetingRooms) → FE-grant is pure UI-visibility there. BUT Master 3 controllers = class [Authorize] ONLY, no per-action role: SuppliersController.cs:17, ProjectsController.cs:11, DepartmentsController.cs:11 — ANY authed user can POST/PUT/DELETE via API (FE menu is the only gate). S55 prod data lives in SeedRealMasterDataAsync :2267-2460 → Projects(62 :2270), WorkItems(71 :2430-2438), Suppliers(3 :2440-2456), all ungated idempotent. BÀI-HỌC: making Suppliers/Projects/Departments visible-to-all needs [Authorize(Roles="Admin,CatalogManager")] or the staff can overwrite S55 master data. 10 departments now (9 + IT); 31 demo users, none zero-role. · 2026-06.md · substring:"S57 perm-broaden blocks A/B/E/F"
  • [cao] seed model — no per-employee default Read · VIỆC: blocks C/D recon. KẾT-LUẬN: SeedAdminPermissionsAsync DbInitializer.cs:1939-1977 loops MenuKeys.All CRUD=true (skip-existing); 2 sub-seeders give 7 roles Read+Update on PE keys and CatalogManager full-CRUD 9 master keys. NO generic per-employee Read seed → a plain Drafter sees ONLY PE keys; most non-admin staff see ~nothing but PE. 4 inherit-roots (Contracts/Workflows/PurchaseEvaluations/PeWorkflows) cascade root→child; Hrm/Off/Master NOT inherit (each leaf needs own row). BÀI-HỌC: grant-all pattern = mirror CatalogManager seeder but loop ALL 13 roles × key-set, CanRead-only, inserted AFTER the catalog seeder. · 2026-06.md · substring:"S57 perm-broaden RECON blocks C/D"
  • [cao] menu seed = UPSERT that re-sets Order · VIỆC: menu reorder cross-repo SE↔NAMGROUP. KẾT-LUẬN: SE menu = SeedMenusAsync DbInitializer.cs tuple-list; seed UPSERT re-sets Order (:1845-1871) → reordering in code propagates to Dev/prod next deploy, NO migration; but Label/ParentKey/Icon are NOT touched on existing rows → rename needs a separate labelBackfill dict. Order = BE-only (GetMyMenuTreeQuery.cs:35 OrderBy); both FE render menu as-is → no FE edit for pure reorder. BÀI-HỌC: HR is SCATTERED across 2 rootsHrm (Hồ sơ+Config+Dashboard) and transactional HR under Off (DonTu/DatXe/ChamCong/AttendanceReport). BẤT-NGỜ: NAMGROUP "Puro" = hardcoded FE array (NOT DB seed), index=order, flat single links vs SE deep-nested. · 2026-06.md · substring:"menu-order cross-repo recon SE↔NAMGROUP"
  • [cao] public-HRM for all-role — seed-only · VIỆC: open HRM module (Hồ sơ/Dashboard) to every role. KẾT-LUẬN: EmployeesController.cs:23-25 is [Authorize(Policy="Hrm_HoSo.Read")] (NOT Roles="Admin") — policy resolves THROUGH the permission matrix (MenuPermissionHandler.cs:40-52), so seeding a CanRead row also unlocks the API, NO 403 → seed BE permission is enough, no controller edit; FE auto-renders (menu-tree API-driven, Hrm NOT in USER_HIDDEN_KEYS, root auto-shows if a child has access). Hrm_HoSo+Hrm_Dashboard ARE in MenuKeys.All (unlike Pe_ leaves); 13 roles in AppRoles.All.* BÀI-HỌC: Pe-style grant-all = SeedAllRolesReviewReadPermissionsAsync :2055 loops all roles × keys, upsert CanRead, idempotent. BẤT-NGỜ: RevokeTemporarilyHiddenModulesAsync is called LAST :2040 in SeedAsync (after the grant :2033) and wipes CRUD on every StartsWith("Hrm")||"Off"||==Personal non-Admin row → it BEATS any earlier grant; opening Hrm needs either excluding Hrm_HoSo/Dashboard from the revoke OR granting AFTER :2040. · 2026-06.md · substring:"S65 recon — public HRM module for all-role"

Prod facts / census / wipe

  • [cao] prod test-data wipe + FK + PE tree · VIỆC: wipe prod test PE + retree by Hạng mục. KẾT-LUẬN: prod PE=10 active (MaPhieu A/031-040, all WorkItemId NULL) + Contracts=7 all [DEMO] V1; FK: PE children CASCADE except Quotes→PE NO_ACTION (multi-path) — Plan R proved a single DELETE FROM PurchaseEvaluations works (NO_ACTION checked end-of-statement after Details→Quotes cascade); PE.ApprovalWorkflowId Restrict → wipe PE before deleting AW. Demo gate OK (SeedDemoContracts/PE inside DemoSeed:Disabled). FE tree = pe/PurchaseEvaluationsListPage.tsx:138-179 Project>Year>Supplier, PeListItem already has workItemId/Name → FE-only change. BÀI-HỌC: ~10 orphan upload folders from S23 (files not deleted on wipe). BẤT-NGỜ: 20 REAL users batched 2026-06-11 06:01 (S58 seed-fix landed; thanh.lethanh now exists, correcting stale S57bis memory). · 2026-06.md · substring:"S59 recon — prod test-data wipe + PE tree"
  • [cao] prod user census + pwd-policy env divergence · VIỆC: why is the demo-user lock a no-op. KẾT-LUẬN: LockDemoSampleUsersAsync DbInitializer.cs:1552 hardcodes 14 named-person emails = a population that exists ONLY on Dev; prod has 34 all-active users (20 UAT-matrix placeholders hand-created 2026-05-13, 9 real staff, binh.lethanh, a typo-domain chuong.phan@solution.com.vn dup, admin/catalog.manager/nv.test). ROOT CAUSE seed-users-never-on-prod = prod Identity:Password:RequiredLength=12 vs DemoUserPassword="User@123456"=11 chars → CreateAsync silent-fails every prod startup since 04-21; Dev fallback length 8 → Dev gets the 33 named users. BÀI-HỌC: fix needs 20 real prod emails; keep nv.test (breaking it breaks CI smoke). BẤT-NGỜ: bod.1@ never appears in git pickaxe → created by hand via admin UI, not seed. · 2026-06.md · substring:"S57bis lock no-op — prod user census"
  • [cao] PE entity recon — 4 đầu việc · VIỆC: PE Year/WorkItem/create-UI/perm. KẾT-LUẬN: PE has NO Year, NO WorkItem link (free-text detail); MaPhieu gen-AT-CREATE PurchaseEvaluationCodeGenerator.cs:23 format PE/{YYYY}/{A|B}/{Seq:D3}; PE controller class-[Authorize] only (no policy → opening the menu is enough, no silent-403); Pe_* leaves NOT in MenuKeys.All. BÀI-HỌC: extending InReviewScope must match key == MenuKeys.PurchaseEvaluations EXACT — the prefix "Pe" would also catch PeWorkflows (admin); root inherit cascades. BẤT-NGỜ: WorkItem write is Admin-only (CatalogsController:113-130) so CatalogManager has the menu but the API write is blocked. · 2026-06.md · substring:"S57bis PE recon — 4 đầu việc sếp"

Pre-golive verify / FE-redesign / master-import

  • [cao] pre-golive logic verify — 4 streams PASS · VIỆC: audit P11-B/D/E/F + ApproveV2 + catalogs + S55 wiring. KẾT-LUẬN: LeaveBalance deduction exactly-once (terminal DaDuyet, guard Status!=DaGuiDuyet :296); AttendanceReport classifies day-type in-memory; MaTicket gen-on-Create Serializable; ApproveV2 4-module flatten correct; master-data idempotency PROVEN (re-run → identical counts). BÀI-HỌC: Travel/Vehicle ApproveV2 = 0 tests (cookie-cutter of tested Leave/OT) — add 2 smoke post-golive. BẤT-NGỜ: dept "IT"/Phòng CNTT DOES exist on prod (Id 65CC6307…) but has 0 active users → ItTicket auto-assign no-ops, SLA job no target (corrects stale S52 "no IT dept"); ops fix = assign ≥1 user to dept IT (1 UPDATE). · 2026-06.md · substring:"S56 pre-golive verify — 4 logic streams"
  • [vừa] FE-redesign Phase-2 recon · VIỆC: 25-page redesign audit. KẾT-LUẬN: NOT a rewrite — S55 already redesigned ui-primitives+DataTable+shell so importers auto-inherit density; hover-hidden quick-win ~absent (only 1 real opacity-0×group-hover site, excluded); only 5/25 use <DataTable> (12 roll raw <table>); 3 Drawer candidates (Suppliers/Projects/Users-create); no Drawer.tsx exists yet; bậc-thang inline-edit reference already exists (EmployeesListPage.tsx). BÀI-HỌC: effort mostly S (auto-inherit) + a few M (Drawer/bậc-thang). · 2026-06.md · substring:"S56 Phase 2 FE-redesign RECON — 25 page audit"
  • [cao] master-data Excel-import recon · VIỆC: import 3 masters from Excel. KẾT-LUẬN: WorkItem/"Hạng mục" master EXISTS (Domain/Master/Catalogs/WorkItem.cs, full CRUD) — no new table needed; PE detail is pure free-text (no FK→WorkItem); Project MISSING Year/Investor/Location/Package (only Note free-text); Supplier MISSING Status/bank-acct/legal-rep + "Cả hai" unmappable (Type single-valued); seed = idempotent existingCodes.Contains→skip; no bulk import (Master is single-CRUD, POST one-at-a-time). BÀI-HỌC: nạp via idempotent DbInitializer mirror (NOT API loop) → reaches prod by design. BẤT-NGỜ: SeedDemoMasterData + SeedCatalogs run REGARDLESS of DemoSeed:Disabled (outside the if-block) → real+demo data mix on prod unless gated. · 2026-06.md · substring:"S55 master-data Excel-import recon"

FE mirror / UI-insert recon

  • [cao] mirror Hồ sơ-NS fe-user→fe-admin = patch CSS first · VIỆC: replicate the redesigned employee page from fe-user into fe-admin. KẾT-LUẬN: VERDICT B — a plain page-copy BREAKS COLORS; must patch fe-admin/src/index.css FIRST then cookie-cutter. fe-admin index.css = 86 lines (pinned 7feb53e, pre-S58 redesign) → missing 4 accent palettes (teal/amberx/violet/greenx, each 50/100/500/600/700) + utilities .icon-chip/.app-gradient-brand/.card-accent/.stat-value; brand-50..900 hex already present (incl brand-800 #175685). The fe-user page really depends on text-brand-800 ×9, the 4 accents ×4 each, icon-chip ×3, app-gradient-brand ×1. Wiring already complete in fe-admin (0 changes): route, identical EmployeeCreatePage.tsx, menu Hrm_HoSo+staticMap; ui-primitives/types/api all parity. Scope = 3 files (index.css insert ~40 lines + overwrite EmployeesListPage.tsx + optional heading-700). BÀI-HỌC: mirror exactly like S35 (both apps committed together); write stays Admin-gated at BE. · 2026-06.md · substring:"S66 recon — mirror Hồ sơ NS fe-user"
  • [cao] PE Section-E "Link hồ sơ" insert point · VIỆC: add mục E "Link hồ sơ" right under mục D "Bản so sánh" in the PE form. KẾT-LUẬN: render in 4 files (SHA256-identical 2 apps): components/pe/PeDetailTabs.tsx + PeWorkspaceCreateView.tsx × {fe-user,fe-admin}; NOT tabs — 5 vertical <Section>. Mục D lives in ChonNccSection (PeDetailTabs.tsx:1302-1375), d.Bản so sánh at :1337-1348 = GeneralAttachmentsSection upload filtered supplierId===null purpose=ComparisonTable. INSERT E at PeDetailTabs.tsx:1348 (after mục D's </div>, before paymentTerms :1350); create-view at PeWorkspaceCreateView.tsx:277. BE PurchaseEvaluation.cs has NO URL field — 1 link = add string? HoSoLink(1000)+Mig+cmd+DTO+validator; many links = child entity (heavy). BÀI-HỌC: attachments are IFormFile-only (PurchaseEvaluationAttachmentFeatures.cs:18-55) — cannot reuse for a URL. BẤT-NGỜ: comment :1314 claims "purpose=ComparisonTable OR supplier-row null" but the real filter :1315-17 is ONLY supplierId===null. · 2026-06.md · substring:"S65ter recon — Mục E"

Governance / wave / harness

  • [vừa] Harness 1/2/3 adap-apply recon · VIỆC: apply AI_INFRA broadcast. KẾT-LUẬN: roster 8→10 (+tooling-auditor H1, +harvest-curator H2); SE hmw.js is pre-wave (AI_INFRA = canonical); email id authoritative = se; git check-ignore -v = ground-truth B6 (wave patterns must sit AFTER !.claude/** last-match-wins). BÀI-HỌC: git-diff + chunk-count = defense-in-depth (caught 1 self-MEMORY write, 0 RAG-write). · 2026-06.md · substring:"Harness 1/2/3 adap-apply recon — 3 slice"
  • [cao] wave h2-verify — B6 isolation + Bash surprise · VIỆC: audit wave write-isolation. KẾT-LUẬN: B6 = 2 rules — transient wave-*/+agent-teams/ gitignored (audit-noise=0) AND canonical agent-memory/**/MEMORY.md TRACKED (rogue writes surface in git status); all 10 MEMORY.md tracked. BÀI-HỌC: ordering gotcha — wave/team patterns MUST sit after !.claude/** or it un-ignores everything. BẤT-NGỜ: Bash tool = /usr/bin/bash NOT PowerShell despite env=PowerShell → Get-ChildItem/Select-String/Test-Path fail (exit 2/127); read-only Bash-only subs MUST use POSIX. · 2026-06.md · substring:"S50 wave h2-verify — B6 guardrail audit"

Monthly drift audit

  • [vừa] 2026-06 monthly drift audit · VIỆC: ground-truth counts vs docs. KẾT-LUẬN: migrations=42 (last AddLeaveBalances) / gotchas highest=#56 (file header has no self-count) / tests=154 / tables≈91; biggest drift = ef-core-migration SKILL (says 31 mig / 59 bảng / 111 test). BÀI-HỌC: schema-diagram migration table stops at Mig 16 → missing §§ for Mig 27-42. BẤT-NGỜ: STATUS backlog "Curate 4 agent MEMORY 35.7/…" is STALE (already curated S40) → remove. · 2026-06.md · substring:"MONTHLY DRIFT AUDIT"

CỤM BỔ SUNG [coverage-diff @S152 D2 — máy-trích nguyên-văn + lead-review; KHÔNG phải re-distill, distill-gen giữ]

Token load-bearing có trong verbatim 2026-06.md mà gist thiếu — mỗi dòng = token + TRÍCH NGUYÊN-VĂN dòng chứa nó (Ctrl-F token trong verbatim để đọc trọn). Chuẩn gate: gotcha#/Mig/file-ref/guard phải sống trong gist. (Đính-chính nhãn @lead-review: #N > 83 = Run/PR-ref CI, KHÔNG phải gotcha — repo max #83; đổi nhãn ref.)

  • ref #346 · trích: "finalize/price audit (FROZEN Mig 59 Run#346 — patchwork hunt):** TWO finalize mechanisms COEXIST + BOTH LIVE (NOT dead): (1) `AllowApproverFinalize"
  • gotcha #44 · trích: "on-disk):** Mục 6 CRITICAL (gotcha #44 family) RESOLVED-FAVORABLE: EmployeesController.cs:23-25 = class [Authorize(Policy='Hrm_HoSo.Read')]"
  • gotcha #66 · trích: "140),.label-eyebrow(:89). ⚠️ GOTCHA #66 = index.css:79-83 h1,h2,h3,h4{color:#0b1220;font-weight:700} OUTSIDE @layer → TW-v4 unlayered wins →"
  • gotcha #70 · trích: "lti-winner + mirror-drift + dead-code + #70):** Post-Mig58 multi-winner (isWinner bool) NOW implemented (supersedes 06-24 'SINGLE' recon). **All 6"
  • gotcha #72 · trích: "notify/TZ audit (FROZEN Mig 59 — gotcha #72):** (a-TZ) UtcDateTimeJsonConverter registered ONLY on AddControllers().AddJsonOptions `Program.cs:3"
  • gotcha #73 · trích: "datePeDraft edit-preserve audit (gotcha #73-class hunt, FROZEN Mig 59):** LATENT #73-CLASS BUG FOUND: UpdatePeDraftHandler absolute-sets `enti"
  • Mig Mig 26 · trích: "g Mig 16 (line 487); detail § cuối =§15=Mig 26 (§16=Related KHÔNG phải mig) → thiếu § cho Mig 27-42 (16 mig). database-guide:4 '47 bảng/13 mig'→91"
  • Mig Mig 29 · trích: "nting', '[Bypass]'/'[SkipFinal]' = test Mig 29-31 flags) + 9 real staff hand-created 05-04→05-12 + binh.lethanh@ (người thật Lê Thanh Bình — seed dù"
  • Mig Mig 39 · trích: "hỉ Office/VehicleBooking.cs (request, Mig 39) dùng FREE-TEXT (VehicleLicense/VehicleName/DriverName? strings, :13-19 comment 'defer catalog Ph"
  • Mig Mig 43 · trích: "chỉ HolidayConfiguration.cs:18 đã fix Mig 43). → Vehicle/Driver Code UNIQUE PHẢI add filter ngay từ đầu. Mig 44 BẮT BUỘC CREATE TABLE (mỗi kind"
  • Mig Mig 52 · trích: "oLink → editing header CLEARS HoSoLink (Mig 52) to null. HoSoLink set separately in PeDetailTabs.tsx:2012-2020 HoSoLinkRow (re-sends all absolute fi"
  • Mig Mig 53 · trích: "s column-PE(per-phiếu) = em-main quyết. Mig 53 CeoApprovalThreshold+cờ-gấp đã có khung CEO-duyệt-theo-ngưỡng. Tag `[pe-price-model, gia-chao-thau-deri"
  • Mig Mig 54 · trích: "legationOPT-IN param threshold-gated (Mig 54):879-915`. AUTO runs FIRST + returns → if both eligible, OPT-IN flag silently ignored (coherent, no d"
  • Mig Mig 56 · trích: "REA-2 (budget matrix + Section B 3-col, Mig 56/59):** BAND-AID CONFIRMED SetPeCcmBudgetPeriodCommand+Validator+Handler (`PeSuggestedPriceFeatu"
  • Mig Mig 58 · trích: "pproverFinalizeper-Level AUTO config (Mig 58)PurchaseEvaluationWorkflowService.cs:861-877+ (2)finalizeByCcmDelegation` OPT-IN param threshold-"
  • Mig Mig 59 · trích: "ve audit (gotcha #73-class hunt, FROZEN Mig 59):** LATENT #73-CLASS BUG FOUND: UpdatePeDraftHandler absolute-sets `entity.HoSoLink = request.H"
  • Mig Mig47 · trích: "14-21): Code(50,UNIQUE [IsDeleted]=0` Mig47)+Name(200) REQUIRED, StartDate/EndDate/BudgetTotal(18,2)/Note(1000)/ManagerUserId optional. **THIẾU Ye"
  • Mig Mig50 · trích: "/b/c/d map — SUPERSEDED bởi S65ter post-Mig50 Budget-drop; test mirror PurchaseEvaluationWorkflowServiceGuardTests). Full text git."
  • Mig Mig58 · trích: "rror-drift + dead-code + #70):** Post-Mig58 multi-winner (isWinner bool) NOW implemented (supersedes 06-24 'SINGLE' recon). **All 6 PE components"
  • guard-kw race · trích: "eBudgetSummaryDto:290-291; auto-create race-safe PeWorkItemBudgetEnsurer.EnsureTrackedAsync:34`; KHÔNG ràng Phase. NO AutoMapper (DTO project tay)."
  • file-ref AdminLayout.tsx · trích: "under separate 'Cá nhân' group); admin AdminLayout.tsx:87-119 splits by function not HR/office. NAMGROUP Đơn từ/Phòng họp/Đề xuất = flat singl"
  • file-ref App.tsx · trích: "faults+ types/hrm-config.ts DTO (10)App.tsx:90route/hrm/configs/:kindSẴN catch-all → KHÔNG cần sửa, chỉ +menuKeys (11)menuKeys.ts:38-42` +"
  • file-ref AppRoles.cs · trích: "enuKey), NO DB upsert. 13 AppRoles AppRoles.cs:23: Admin(system)+12 employee. 4 inherit-roots GetMyMenuTreeQuery.cs:56-84: Contracts/Workf"
  • file-ref ApplicationDbContext.cs · trích: "oTable+.HasIndex(Code).IsUnique()(3)ApplicationDbContext.cs:95-98DbSet (4)IApplicationDbContext.cs:102-105DbSet (5)HrmConfigFeatures.cs` +"
  • file-ref ApprovalWorkflow.cs · trích: "approvers = specific ApproverUserId (ApprovalWorkflow.cs:80), OR-of-N = N Level rows same Order (GroupBy :687). 'Phòng CCM' = seed Step NAME + n"
  • file-ref ApprovalWorkflowsV2Page.tsx · trích: "L both DTOs.** (A) Designer fe-admin ApprovalWorkflowsV2Page.tsx: read-only render DefinitionCard:446-454 (level group → approver `{approverUs"
  • file-ref AuditingInterceptor.cs · trích: "Deleted)** + Delete via .Remove()AuditingInterceptor.cs(State Deleted→Modified, IsDeleted=true) + CreateAnyAsync(x=>x.Code==req.Code)NO"
  • file-ref CatalogsConfiguration.cs · trích: "Unit(50)/Description/IsActive), config CatalogsConfiguration.cs:60-74, full CRUD CatalogsFeatures.cs:260-324 → group(VẬT TƯ/THẦU PHỤ/MEP)→Category"
  • file-ref CatalogsController.cs · trích: "21, all POST/PUT/DEL Roles='Admin'; CatalogsController.cs:14same (write:23+Admin);MeetingRoomsController.cs:15same (comment:9-10` expl"
  • file-ref CatalogsFeatures.cs · trích: "logsConfiguration.cs:60-74, full CRUD CatalogsFeatures.cs:260-324` → group(VẬT TƯ/THẦU PHỤ/MEP)→Category, '1 Mat'→Code, item→Name. KHÔNG cần table/m"
  • file-ref ChamCongPage.tsx · trích: "(595) · DanhBaPage.tsx(756 tree+grid) · ChamCongPage.tsx(809). ⚠️ Style/màu lấy chỗ khác per task — chỉ structure. SE đã có analog (fe-user `InternalL"
  • file-ref ContractClauseConfiguration.cs · trích: "). SKIP 3: (a) ContractClause (ContractClauseConfiguration.cs:18) — NO Create/Update/Delete handler ANYWHERE (only `IApplicationDbContext.cs"
  • file-ref ContractCreatePage.tsx · trích: "×group-hover= **only 1 real site**ContractCreatePage.tsx:196` (EXCLUDED scope) + DataTable.tsx:15 is a comment forbidding it (good). In-scope ="
  • file-ref DanhBaPage.tsx · trích: "age(month-grid) · TicketPage.tsx(595) · DanhBaPage.tsx(756 tree+grid) · ChamCongPage.tsx(809). ⚠️ Style/màu lấy chỗ khác per task — chỉ structure. SE"
  • file-ref DataTable.tsx · trích: "tCreatePage.tsx:196` (EXCLUDED scope) + DataTable.tsx:15 is a comment forbidding it (good). In-scope = 0 hover-hidden fixes. **DataTable adoption"
  • file-ref DateTimeService.cs · trích: "e: n.CreatedAt=clock.UtcNow=Kind.Utc (DateTimeService.cs:7) → default STJ writes 'Z' for Utc-kind, FE new Date(iso) NotificationBell.tsx:23 OK. La"
  • file-ref DeXuatPage.tsx · trích: "ePage.tsx(dashboard) · PageHeader.tsx · DeXuatPage.tsx(1676 KPI+table+detail) · DonTuPage.tsx(1269 +DonTuCalendar.tsx toggle) · XeCongPage/PhongHopPag"
  • file-ref Department.cs · trích: "). GAP THẬT: (1) NO org-treeDepartment.cs FLAT (Code/Name/ManagerUserId/Note, KHÔNG ParentId), DepartmentsController chỉ GET list+byId"
  • file-ref DependencyInjection.cs · trích: "ment :1675-79 đã biết); Dev fallback 8 (DependencyInjection.cs:67 ?? 8, Development.json no Identity section) → Dev đủ 33 user named-person. `bod.1@"
  • file-ref DonTuCalendar.tsx · trích: "KPI+table+detail) · DonTuPage.tsx(1269 +DonTuCalendar.tsx toggle) · XeCongPage/PhongHopPage(month-grid) · TicketPage.tsx(595) · DanhBaPage.tsx(756 tre"
  • file-ref DonTuPage.tsx · trích: "DeXuatPage.tsx(1676 KPI+table+detail) · DonTuPage.tsx(1269 +DonTuCalendar.tsx toggle) · XeCongPage/PhongHopPage(month-grid) · TicketPage.tsx(595) · Da"
  • file-ref Dtos.cs · trích: "alLevelApproverDto (PurchaseEvaluationDtos.cs:129-132= UserId/FullName/Email, **NO role**). **(C) Role-resolve for LIST userId:** codebase usesu"
  • file-ref EmployeeFeatures.cs · trích: "6 EmployeeCode+UserId) — Delete soft (EmployeeFeatures.cs:437) BUT Create BLOCKS reuse by design: UserId check AsNoTracking().FirstOrDefault(UserI"
  • file-ref EmployeeProfile.cs · trích: "Entity gần đủ screenshot:** Domain/Hrm/EmployeeProfile.cs (137 LOC) CÓ: DOB/Gender/Ethnicity/Religion/Nationality/Height/Weight(:98-99)/IdCard(số+ng"
  • file-ref EmployeeProfileConfiguration.cs · trích: "eleted :113. (c) **EmployeeProfile** (EmployeeProfileConfiguration.cs:24/26 EmployeeCode+UserId) — Delete soft (EmployeeFeatures.cs:437`) BUT Crea"
  • file-ref Enums.cs · trích: "iority{Low,Medium,High,Urgent} Office/Enums.cs:48-54) AddColumn no-new-table; notify INotificationService.NotifyAsync(userId,type,title,desc?,href"
  • file-ref HomePage.tsx · trích: "dex=HomePage. Landing / = internal/HomePage.tsx (296L): grid 2-col (LEFT 2/3 stack 4 WidgetCard: Đề xuất/Nghỉ phép/Bình luận/Truyền-thông · RI"
  • file-ref HrDashboardController.cs · trích: "nRead row = API ALSO unlocked, NO 403. HrDashboardController.cs:8-11 = [Authorize] any-auth only (/api/hr/dashboard). GET list = `/api/employees"
  • file-ref HrmConfigFeatures.cs · trích: "icationDbContext.cs:102-105DbSet (5)HrmConfigFeatures.cs` +Region N (DTO+List/Create/Update/Delete handler+validator, mega 4-region :30/125/222/32"
  • file-ref HrmConfigsController.cs · trích: "or, mega 4-region :30/125/222/328) (6) HrmConfigsController.cs +4 route hardcode [HttpGet/Post/Put/Delete('{kind}')] (Post/Put/Del `[Authorize(Rol"
  • file-ref HrmConfigsPage.tsx · trích: "issionsAsyncloop idempotent). FE (9)HrmConfigsPage.tsx:45 KIND_CONFIG+entry +:114 KINDS[]+:379 renderCellsbranch +:166 smart-defaults`"
  • file-ref IApplicationDbContext.cs · trích: "plicationDbContext.cs:95-98DbSet (4)IApplicationDbContext.cs:102-105DbSet (5)HrmConfigFeatures.cs` +Region N (DTO+List/Create/Update/Delete ha"
  • file-ref INotificationService.cs · trích: "serId,type,title,desc?,href?,refId?) (INotificationService.cs:10)+SignalR interceptor; LogTransition notifies DRAFTER-only on terminal (:960-980`)"
  • file-ref InternalLayout.tsx · trích: "y (NOT DB seed),** index=order: client InternalLayout.tsx:83-118 (Nhân sự 3-item / Văn phòng số 6-item FLAT / Chấm công under separate 'Cá nhân' gro"
  • file-ref Layout.tsx · trích: "ỉ +menuKeys (11) menuKeys.ts:38-42 + Layout.tsx:60-63 staticMap. gotcha #57 CONFIRMED còn trần: LeaveTypeConfiguration.cs:19 + `ShiftPattern"
  • file-ref MeetingRoomConfiguration.cs · trích: "t CRUD-reachable. (b) MeetingRoom (MeetingRoomConfiguration.cs:20) — Delete sets IsActive=false NOT IsDeleted (MeetingFeatures.cs:178, comme"
  • file-ref MeetingRoomsController.cs · trích: "ller.cs:14same (write:23+Admin);MeetingRoomsController.cs:15same (comment:9-10` explicit). → granting FE read on Hrm_Config/Catalogs/Meeti"
  • file-ref MenuKeys.cs · trích: "hải +&& OtPoliciesNew.AnyAsync() (8) MenuKeys.cs:88-92 +const + :149 All[] (Admin auto-grant SeedAdminPermissionsAsync loop idempotent). FE (9"
  • file-ref NotificationBell.tsx · trích: "es 'Z' for Utc-kind, FE new Date(iso) NotificationBell.tsx:23 OK. Latent: any future SignalR push of an EF-READ (Unspecified) DateTime would skew. N"
  • file-ref NotificationPushInterceptor.cs · trích: "no .AddJsonProtocol, separate STJ): NotificationPushInterceptor.cs:77 pushes createdAt=n.CreatedAt over SendAsync. BENIGN at runtime: `n.Crea"
  • file-ref PageHeader.tsx · trích: "rumb + actions slot, components/shared/PageHeader.tsx); (b) KPI stat-cards clickable filter (DeXuat :1643 6-card / Ticket :197 5-card — 'PURO KP"
  • file-ref PeCcmBudgetPeriodSetterAuthzTests.cs · trích: "sit). Test+comments already self-flag (PeCcmBudgetPeriodSetterAuthzTests.cs:14). ⚠️ **Role-gate ASYMMETRY (intentional, NOT a bug — but inconsistent"
  • file-ref PeHeaderForm.tsx · trích: "e PeWorkspaceCreateView.tsx · header PeHeaderForm.tsx. FE type types/purchaseEvaluation.ts PeBudgetSummary:292-307+winnerQuoteTotal:445. ⚠️"
  • file-ref PeListPanel.tsx · trích: "RESIDUAL single-winner BUG (low): PeListPanel.tsx:168 renders p.selectedSupplierName (list-card winner label) → BLANK when ≥2 joint winners ("
  • file-ref PeSuggestedPriceFeatures.cs · trích: "udgetPeriodCommand+Validator+Handler (PeSuggestedPriceFeatures.cs:153-199) is a BUDGET setter (writes pe.CcmBudgetPeriodAmount`) MISPLACED in a pr"
  • file-ref PeUrgentFeatures.cs · trích: "GetUsersInRoleAsync(role) (reverse, PeUrgentFeatures.cs:74). IApplicationDbContext exposes DbSet<Role> Roles :29 but **NO UserRoles join-tabl"
  • file-ref PeWorkItemBudget.cs · trích: "htoànsrc/Backend=0 + FE=0. Entity PeWorkItemBudget.cs6 field plain, KHÔNG cờIsInitialLocked/SubmitCount`; record per-cặp(Project×WorkItem)"
  • file-ref PeWorkItemBudgetFeatures.cs · trích: "||CostControl(DTO arg :856). HandlerPeWorkItemBudgetFeatures.cs: PRO :86-91CCM:152-157` fail-closed ForbiddenException role-only TRƯỚC side-"
  • file-ref PeWorkflowPanel.tsx · trích: ":474,:526 · IPe…Service:32 · FE both PeWorkflowPanel.tsx:184,584 ô-tích) — NOT orphan. ALL 3 DaDuyet paths bind giá chốt via `ApplyApprovedPriceOn"
  • file-ref Permission.cs · trích: "rs CanRead=true. Permission entity Permission.cs:3-15: RoleId/MenuKey/CanRead/Create/Update/Delete. Dedup=app-level skip-existing per(RoleId,Men"
  • file-ref Program.cs · trích: "zer.InitializeAsync chạy MỌI startup (Program.cs:197unless--no-db-init) → MigrateAsyncTHEN seed; demo gatedconfig.GetValue('DemoSeed"
  • file-ref Project.cs · trích: "d WorkItems non-breaking. Project (Project.cs:5-14, cfg :14-21): Code(50,UNIQUE [IsDeleted]=0 Mig47)+Name(200) REQUIRED, StartDate/EndDate/B"
  • file-ref PurchaseEvaluationCreatePage.tsx · trích: "ctive. PeHeaderForm reachable as EDIT (PurchaseEvaluationCreatePage.tsx:13,26 editId from URL ?id=, deep-link 'Sửa header'). Field table: TenGoiTh"
  • file-ref PurchaseEvaluationDetail.cs · trích: "n mới. PE detail = pure free-text (PurchaseEvaluationDetail.cs GroupCode/GroupName/ItemCode/NoiDung strings, NO FK→WorkItem) → load WorkItems no"
  • file-ref PurchaseEvaluationDetailFeatures.cs · trích: "seEvaluationWinnerCommand(PEId,Guid?) PurchaseEvaluationDetailFeatures.cs:392handler:398-423(null=clear S85-C5); ctrl/select-winner Purcha"
  • file-ref PurchaseEvaluationDtos.cs · trích: "seEvaluationApprovalLevelApproverDto (PurchaseEvaluationDtos.cs:129-132` = UserId/FullName/Email, NO role). **(C) Role-resolve for LIST userId:*"
  • file-ref PurchaseEvaluationFeatures.cs · trích: "valuationDetail.cs:10-13). Create cmd PurchaseEvaluationFeatures.cs:19-30; MaPhieu gen-AT-CREATE :114-116formatPE/{YYYY}/{A|B}/{Seq:D3} (Pur"
  • file-ref PurchaseEvaluationQuote.cs · trích: "at/ChuaVat/ThanhTiendecimal non-nullPurchaseEvaluationQuote.cs:12-14· PE-headerBudgetPeriodAmount(row3 drafter)/ExpectedRemainingAmount`(row"
  • file-ref PurchaseEvaluationType.cs · trích: "6)+DetailBundleDto(:201). Type A/B (PurchaseEvaluationType.cs:6-10`) constrains pinnable ApplicableType only — ZERO type-conditional routing. ⚠️ '"
  • file-ref PurchaseEvaluationUrgentFeatures.cs · trích: "t. (b-authz) Urgent SET/UNSET branches PurchaseEvaluationUrgentFeatures.cs:54-73 SYMMETRIC + fail-CLOSED both (if(!allowed)throw BEFORE mutate); 1"
  • file-ref PurchaseEvaluationWorkflowService.cs · trích: "ted 3 nơi đồng-predicate: submit-guard PurchaseEvaluationWorkflowService.cs:188-192 · detail-GET PurchaseEvaluationFeatures.cs:818-826(→`CurrentPr"
  • file-ref PurchaseEvaluationsController.cs · trích: "roller class-level [Authorize] only (PurchaseEvaluationsController.cs:15) → handler gates ARE the boundary. Tests solid (PeWorkItemBudgetTests 30+"
  • file-ref Supplier.cs · trích: ":87 AnyAsync(Code==). Supplier (Supplier.cs:5-16, cfg :14-27): Code/Name req + Type enum + TaxCode(20)/Phone/Email/Address/ContactPerson/No"
  • file-ref SupplierType.cs · trích: "hone/Email/Address/ContactPerson/Note. SupplierType.cs: NhaCungCap=1/NhaThauPhu=2/ToDoi=3/DonViDichVu=4/ChuDauTu=5. **THIẾU Status/TinhTrang (KHÔN"
  • file-ref TicketPage.tsx · trích: "· XeCongPage/PhongHopPage(month-grid) · TicketPage.tsx(595) · DanhBaPage.tsx(756 tree+grid) · ChamCongPage.tsx(809). ⚠️ Style/màu lấy chỗ khác per tas"
  • file-ref config.ts · trích: "nfigKindunionfe-admin/src/types/hrm-config.ts:4+ route param. **Add 1 kind = mirror FULL entity stack 11 chỗ:** BE (1) DomainHrm/{X}.cs` Audit"
  • file-ref detectors.ps1 · trích: ") BASELINE-DRIFT ALIGNED:** governance-detectors.ps1 staleness = CANONICAL-ANCHOR vs docs/STATUS.md (Get-StatusValue:133 parse `| label | *N"
  • file-ref employee.ts · trích: "· EmptyState/cn/api/apiError · types/employee.ts identical · Paged types/master · DepartmentTreeNode định nghĩa INLINE trong page (:65 m"
  • file-ref gate.ps1 · trích: "ale) — ZERO age-window. memory-archive-gate.ps1 over-cap = byte-MEASURE+2-strike-hysteresis (:106 bytes>cap), A7 = substring-pointer-resolve. Neit"
  • file-ref memory.ps1 · trích: "ined headroom' + scripts/measure-agent-memory.ps1 real-bytes), bump-not-cut khi curate drops markers. Hysteresis drain-to-BELOW-low-water (gate:33"
  • file-ref menuKeys.ts · trích: "ll → KHÔNG cần sửa, chỉ +menuKeys (11) menuKeys.ts:38-42 + Layout.tsx:60-63 staticMap. gotcha #57 CONFIRMED còn trần: `LeaveTypeConfiguration."
  • file-ref purchaseEvaluation.ts · trích: "Panel3 separate. PeApprovalFlow DTO purchaseEvaluation.ts + BE PurchaseEvaluationApprovalLevelApproverDto (PurchaseEvaluationDtos.cs:129-132"

BỔ-SUNG-2 [F1/F2 sau Fidelity-gate @S152 — mở đuôi infra {yml,yaml,json,slnx,csproj,sql,config} + guard IsUnique/optimistic. N/A CỐ-Ý (F5): bundle-hash xoay #69 · tên-giả phép-thử ZZfakehash* · đuôi .md]

  • file-ref appsettings.Production.json · trích: "Identity:Password:RequiredLength=12 (appsettings.Production.json) vs DemoUserPassword='User@123456'=11 chars → CreateAsync silent-fail MỌI startu"
  • file-ref appsettings.json · trích: "uTreeQuery.cs:49-82). Demo gate: prod appsettings.json:35 DemoSeed:Disabled=true→ 7[DEMO]HĐ + 4[DEMO]PE (MaPhieu[DEMO]-A-001`) KHÔNG lên"
  • file-ref memory-budget.json · trích: "ỗi team-size). (1) BUDGET ALIGNED: memory-budget.json grep decay|recency|retention|age|TTL|expire=0 hit. Params = autoinject_cap 25600/`so"
  • file-ref trial-state-lock.json · trích: "recall@5 gate 0.7, rerank≥0.7) + eval/trial-state-lock.json (baseline recall@5=1.0, chunk-drift 5% threshold) + eval/runs/*.json. BUT: weekly-Fri"