3-stage Workflow run-id evidence: investigate wf_be952f3c-97f / implement wf_a58e0d15-beb / audit wf_9520d8cd-4fe. PART 1 (L2 recovery): 4 over-cap sub (cicd-monitor/investigator-codebase/reviewer/implementer-backend) curated L1->L2 byte-exact + archive/_INDEX.md (substring sha-keyed pointers, no line-hints) + <period>.gist.md (4-field distill, distill-gen:1, verbatim frozen). All 4 MEMORY.md now < 25KB auto-inject cap (closes P1 curate-debt). ~240KB archive no longer RAG-dark. 0-byte-loss git+sha verified (Stage C audit + em-main self-gate on 2 reviewer StructuredOutput no-returns). Read-side gap fixed (MEMORY.md L5 header -> _INDEX). + memory-budget.json (seed-by-measure) + scripts/measure-agent-memory.ps1 + .ragignore guard. PART 2/3 (process mandate): every adap = 2 separate workflows (implement + review) + report with run-id; short-but-needs-confirm still requires review. Codified in .claude/commands/adap-apply.md + agents/README.md (Upgrade S70) + session-start.md (§2.1.2 budget-audit, pending-restart). adap-report + email-back to AI_INFRA (body-hash 7c07b716e775). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
26 KiB
Archive 2026-06 — investigator-codebase FIFO overflow
Moved from MEMORY.md L1 (S57bis curate 2026-06-11). Verbatim.
-
2026-06-08 (S50 P11-C Vehicle+Driver — HrmConfigs add-kind pattern VERIFIED on-disk, RAG down): ⭐ HrmConfigs KHÔNG có "kind enum/registry" backend — 4 entity RIÊNG (LeaveType/Holiday/ShiftPattern/OtPolicy), NOT discriminated table. "kind" chỉ FE:
HrmConfigKindunionfe-admin/src/types/hrm-config.ts:4+ route param. Add 1 kind = mirror FULL entity stack 11 chỗ: BE (1) DomainHrm/{X}.csAuditableEntity soft-delete (2)Configurations/{X}Configuration.cs.ToTable+.HasIndex(Code).IsUnique()(3)ApplicationDbContext.cs:95-98DbSet (4)IApplicationDbContext.cs:102-105DbSet (5)HrmConfigFeatures.cs+Region N (DTO+List/Create/Update/Delete handler+validator, mega 4-region :30/125/222/328) (6)HrmConfigsController.cs+4 route hardcode[HttpGet/Post/Put/Delete("{kind}")](Post/Put/Del[Authorize(Roles="Admin")], Get chỉ[Authorize]) (7)DbInitializer.cs:2329 SeedHrmConfigsAsync+if-block + skip-guard :2331 phải +&& OtPoliciesNew.AnyAsync()(8)MenuKeys.cs:88-92+const +:149 All[](Admin auto-grantSeedAdminPermissionsAsyncloop idempotent). FE (9)HrmConfigsPage.tsx:45 KIND_CONFIG+entry +:114 KINDS[]+:379 renderCellsbranch +:166 smart-defaults+ 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+Layout.tsx:60-63 staticMap. gotcha #57 CONFIRMED còn trần:LeaveTypeConfiguration.cs:19+ShiftPatternConfiguration.cs:19+OtPolicyConfiguration.cs:22.IsUnique()CHƯA.HasFilter("[IsDeleted]=0")(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 = bảng riêng, NOT discriminated → +2 bảng Vehicles+Drivers, không phải seed-only). VehicleBooking (Office/VehicleBooking.cs:13-19) pure free-textVehicleLicense/VehicleName/DriverNamestring, NOVehicleId/DriverIdFK (grep empty) → P11-C catalog-only, FK link defer Mig sau. Latest Mig=43FilterHolidayUniqueIndexByIsDeleted(20260601064128), next=44. Tag[p11-c, hrmconfig-add-kind, gotcha57, on-disk-verify]. -
2026-06-07 (S50 wave
h2-verify— B6 guardrail audit, read-only) [em main scribe from findings + H2 harvest]: Verified B6 wave-isolation 3/3 PASS. B6 = TWO complementary rules: (a) transientwave-*/+agent-teams/gitignored (.gitignore:93-94) → audit-noise=0; (b) canonicalagent-memory/**/MEMORY.mdTRACKED → rogue sub-write surfaces ingit status.git check-ignore -v= ground-truth verifier BOTH directions (matched rule:line for ignored; empty for tracked). ⚠️ Ordering gotcha: wave/team patterns MUST sit AFTER!.claude/**(.gitignore:82-83) to win via last-match (:91documents intent) — else!.claude/**un-ignores everything. All 10 MEMORY.md tracked (roster 8→10). Surprise (cross-cutting, both wave subs): Bash tool =/usr/bin/bashNOT PowerShell despite env=PowerShell →Get-ChildItem/Select-String/Test-Pathfail (exit 2/127); read-only Bash-only subs MUST use POSIX (git ls-files/grep/ls). Tag [wave-h2, b6-isolation, posix-not-pwsh]. -
2026-06-08 (S51 gotcha #57 EXTENSION reachability audit — 6 candidate, RAG down, on-disk only): ⭐ Bug class = soft-delete + bare
.IsUnique()on Code → recreate-after-delete throws DbUpdateException 500. Verdict 6 cand: FIX 3 (Master) Department/Supplier/Project (Department/Supplier/ProjectConfiguration.cs:18/24/19bare unique). ALL = AuditableEntity + GLOBALHasQueryFilter(!IsDeleted)+ Delete via.Remove()→AuditingInterceptor.cs(State Deleted→Modified, IsDeleted=true) + CreateAnyAsync(x=>x.Code==req.Code)NO!IsDeletedBUT global filter auto-hides soft-deleted → check passes → unfiltered index 500. CONFIRMED-reachable (DepartmentFeatures.cs:76+125,ProjectFeatures.cs:87+147,CreateSupplierCommand.cs:45+DeleteSupplierCommand.cs:20). SKIP 3: (a) ContractClause (ContractClauseConfiguration.cs:18) — NO Create/Update/Delete handler ANYWHERE (onlyIApplicationDbContext.cs:32DbSet; FormsController = templates only) → not CRUD-reachable. (b) MeetingRoom (MeetingRoomConfiguration.cs:20) — Delete setsIsActive=falseNOT IsDeleted (MeetingFeatures.cs:178, comment :175 "FK Restrict → NOT soft delete") → index never gets soft-deleted row; Create also checks&& !IsDeleted:113. (c) EmployeeProfile (EmployeeProfileConfiguration.cs:24/26EmployeeCode+UserId) — Delete soft (EmployeeFeatures.cs:437) BUT Create BLOCKS reuse by design: UserId checkAsNoTracking().FirstOrDefault(UserId==)(no HRM global filter) sees soft-deleted → throws ConflictException "Cần khôi phục" :160-163; EmployeeCode auto-gen atomic (never user-supplied/reused) → no collision. Completeness (grep ALL.IsUnique()): beyond 3 Master + 6 HRM-fixed (LeaveType/Holiday/Shift/OtPolicy/Vehicle/Driver all.HasFilter([IsDeleted]=0)), every OTHER bare-unique is either composite junction (Permission RoleId+MenuKey, *LevelOpinion, MeetingBookingAttendee, LeaveBalance, Attendance UserId+Date), nullable-code already filtered ([Ma*] IS NOT NULL: Contract/PE/Proposal/Budget/WorkflowApps), or no-soft-delete (WorkflowDefinition/ApprovalWorkflow Code+Version, ContractTemplate FormCode, WorkflowTypeAssignment, DepartmentApprovals). Mig 46 = exactly 3 indexes (Departments/Suppliers/Projects Code). Surprise: Master GLOBAL query filter MAKES the bug (auto-hides soft-deleted from check) — opposite of HRM where bug needs manual!IsDeleted; either way unfiltered index = 500. Tag[gotcha57-ext, reachability-audit, master-global-filter, s51]. -
2026-06-01 (MONTHLY DRIFT AUDIT): Ground truth code: migrations=42 (last
AddLeaveBalances, path.../Persistence/Migrations/*.cs) · gotchas highest=#56 (file header NO self-count → drift chỉ ở file reference gotchas.md) · tests=154 (58 Domain+96 Infra, em main verified) · tables≈91 (45 config class nhưng Catalogs=4+ContractDetails=7+7 Identity untracked → khớp STATUS 91, KHÔNG cheap-exact). Biggest drift: ef-core-migration SKILL (frontmatter:3 "31 migration"→42, :19 history "31"→42 + thiếu rows Mig 27-42, :50 "59 bảng"→91, :80 "111 test"→154, :258/:267 "59 bảng"). dependency-audit SKILL:153 "49 bẫy"→56. CLAUDE.md:53 "40 mig→84 bảng"→42/91, :66 "130 test"→154, :133 "52 bẫy"→56. docs/CLAUDE.md:65 "52"→56. schema-diagram GAP: migration TABLE dừng 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/42. STATUS:97 backlog "Curate 4 agent MEMORY 35.7/35.3/30.9/28.4" STALE (đã curate S4078c9de3, all ≤16KB) → REMOVE. NO-CHANGE: contract-workflow (historical counts OK), form-engine, iis-deploy (no count), HANDOFF (S43 current), PROJECT-MAP (no count). Tag[drift-audit, monthly, 2026-06]. -
2026-06-01 (P11-C Vehicle+Driver catalog pre-flight): Mig 44 next (latest=Mig 43
FilterHolidayUniqueIndexByIsDeletedS45). NO Vehicle/Driver master exists — chỉOffice/VehicleBooking.cs(request, Mig 39) dùng FREE-TEXT (VehicleLicense/VehicleName/DriverName?strings, :13-19 comment "defer catalog Phase 11"). RECOMMEND home = extend HrmConfigs (NOT new module):Application/Hrm/HrmConfigFeatures.csmega 4-region +HrmConfigsController([Authorize]read /[Authorize(Roles="Admin")]write) — add Region 5 Vehicle + 6 Driver (kindvehicles/drivers), pattern proven 12-bis. ⚠️ HRM entities KHÔNG global HasQueryFilter → manual.Where(!IsDeleted)+ UNIQUE soft-delete cần.HasFilter("[IsDeleted]=0")(Holiday Mig 43 lesson, LeaveType/Shift UNIQUE Code chưa có filter → nếu Vehicle BienSo UNIQUE phải add filter). FE cheap:HrmConfigsPage.tsxdeclarative KIND_CONFIG Record — add 2 entry vào KIND_CONFIG + KINDS[] +renderCellsbranch + smart-defaults; NO new page. Menu+perm: add 6 constMenuKeys.cs(+Hrm_Config_Vehicles/Drivers), thêm vàoAll[](:140) → Admin auto-grant quaSeedAdminPermissionsAsyncloop (:1909 idempotent), +2 MenuItemDbInitializer:1757, +2menuKeys.tsmirror. Hrm_Config KHÔNG inherit-root (4 root=Contracts/Workflows/Pe/PeWf only) → leaf cần row riêng (loop lo). Fields (NamGroup XeCong DROPPED Mig 2026-05-15, ref response shape only): Vehicle{Code/BienSo UNIQUE, Hang, MauXe, SoCho int, TrangThai, GhiChu}; Driver{Code/Hoten, SDT, GPLX, Hang bằng, TrangThai}. FK link defer: P11-C = catalog only, optional FKVehicleBooking.VehicleId?/DriverId?giữ free-text back-compat (Mig sau). Tag[pre-flight, p11-c, vehicle-driver-catalog]. -
2026-06-07 (Harness 1/2/3 adap-apply recon — 3 slice, HMW wave): Governance recon AI_INFRA broadcast harness-1/2/3. H1/H2 (Harness 1): roster 8→10 — CREATE 2 sub TÁCH BIỆT
tooling-auditor(H1 freshness 4-mặt skill/sub-role/plugin/docs) +harvest-curator(H2 integrity 5-trục). H2 PARTIAL sẵn:session-end.mdPhase 1.5 §L.b(d) spawn-record 4-field + (f) double-check moved-not-cut + (c) 0-byte AS-8 = Coverage+Completeness+Corruption (3/5); THIẾU Fidelity-escalate + Placement. RE-REPORT @session-start = 0 (chỉ generic Phase 2.7). 2 sub mirror inv-codebase read-set + store_memory strip + NO Write/Edit; color brown+teal (8 màu cũ hết). H2 wave (Harness 2): SEhmw.js= OLD pre-wave (no subMdPath/writeGuard/wave-block); AI_INFRAhmw.js= canonical template. ⭐git check-ignore -v= ground-truth B6:.claude/workflows/wave-test/wave.mdHIỆN match.gitignore:83 !.claude/**= TRACKED → wave pattern PHẢI đặt AFTER!.claude/**(last-match-wins, mẫuhmw-mode.on:87). Read-only sub (4)=inv-cb/inv-api/reviewer/cicd; Write sub (4)=impl×2/test/fe-designer. B5 depends H2 harvest-curator. H3 email (Harness 3): broadcasts/ absent; id authoritative =se(NOT solution_erp), 6 others short{ai_infra,vipix,dyd,namgroup,ashico,bvaau}từAI_INFRA/broadcasts/sister-commands/send-email.md:13-22(folder name = 2nd source-truth);adap-apply.md:14base-path STALE flat →outbox/all/*.md(latent bug). broadcasts/ ở root → commit OK (no gitignore rule). Containment post-P2: git-diff bắt 1 file-write (inv-api self-MEMORY), chunk-count 2414=2414 (0 RAG-write) = defense-in-depth proven. Tag [harness-recon, governance, hmw-wave, 2026-06-07]. -
2026-06-09 (S56 pre-golive verify — 4 logic streams, all PASS): Audited P11-B/D/E/F + ApproveV2 + catalogs + S55 master-wiring. LeaveBalance deduction exactly-once (terminal DaDuyet, guard
Status!=DaGuiDuyet:296 blocks re-approve), FK guard Create+UpdateDraft→Conflict; AttendanceReport classify day-type IN-MEMORY (Holiday DateOnly HashSet), OtPolicy multiplier; MaTicket gen-on-Create Serializable IT/2026/NNN. Tests cover (LeaveBalance 9 + AttReport 2 + codegen 3 = 29 green). ApproveV2 4-module flatten Steps→Levels correct; Travel/Vehicle ApproveV2 = 0 test (cookie-cutter of tested Leave/OT — add 2 smoke post-golive). master-data idempotency PROVEN (DbInitializer re-run → counts identical, per-code guard :2310/:2404/:2422). ⚠️ PROD FACT (corrects stale S52 mem): dept "IT"/Phòng CNTT DOES exist (Id 65CC6307…) but has 0 active users on prod → ItTicket auto-assign no-ops, reassign dropdown empty, SLA job no notify-target. Pre-golive ops fix: assign ≥1 real user to dept IT (1 UPDATE, no code). Tag [s56, pre-golive-verify, logic-pass, dept-IT-empty-prod, travel-vehicle-untested]. -
2026-06-09 (S56 Phase 2 FE-redesign RECON — 25 page audit, on-disk): ⭐ NOT a rewrite — S55 already redesigned ui-primitives + DataTable + shell → any page importing
ui/{Button,Input}+DataTableAUTO-inherits density. Hover-hidden quick-win nearly absent: repo-wide grepopacity-0×group-hover= only 1 real siteContractCreatePage.tsx:196(EXCLUDED scope) + DataTable.tsx:15 is a comment forbidding it (good). In-scope = 0 hover-hidden fixes. DataTable adoption split: only 5/25 use<DataTable>(Suppliers/Projects/Departments/Users/Forms); 12 pages roll RAW<table>(MeetingRooms/Catalogs/HrmConfigs/EmployeesList/Proposals/WorkflowApps/Attendance×2/MenuVisibility/Roles) → custom density pass needed. Drawer ≥8-field candidates = 3: Suppliers (9 fld, Dialog), Projects (10 fld, Dialog), Users-CREATE (~8 fld w/ roles multiselect, 4 Dialogs total but only create is big). All currently big-Dialog → convert. NODrawer.tsxexists (ui/= Button/Dialog/Input/Label/Select/Textarea only) → build first. Bậc-thang reference ALREADY EXISTS:EmployeesListPage.tsx(1200L) = canonical inline add/edit-row for 5 satellites (setEditing{X}Id+addingXmutex, :256-356) → extractInlineEditRowpattern from here, reuse for Catalogs/HrmConfigs/MeetingRooms (these 3 currently edit via Dialog :251/:316/:232, ≤7 cols → bậc-thang candidates). Modal-detail = NONE: ProposalDetail:275 + WorkflowAppDetail:424 Dialogs are tiny action-confirm (just<Textarea>ý kiến), detail body already inline 2-col grid (:181) → NOT convert. fe-user mirrors office/master/hrm (SHA256-identical per comments) but NO system/forms/reports mirror. Custom-layout heavy: InternalDirectory (card-grid :124 not table), MeetingCalendar (693L FullCalendar), EmployeesList (2-panel), HrmConfigs (declarative KIND_CONFIG :45). Effort: Master 3×Drawer=M, Catalogs/HrmConfigs/MeetingRooms bậc-thang=M, Users Drawer=M, rest S (auto-inherit polish). Surprise: hover-hidden NAMGROUP-win essentially pre-solved (team already avoids opacity-0 pattern, DataTable comment enforces) → quick-win section nearly empty. Tag[fe-redesign-p2, recon, drawer-3, basc-thang-ref-exists, s56]. -
2026-06-09 (S55 master-data Excel-import recon — 3 master + seed mechanism, on-disk): ⭐ "Hạng mục"/WorkItem master TỒN TẠI —
Domain/Master/Catalogs/WorkItem.cs:6-14(Code(50)UNIQUE-filtered/Name(200)/Category(100,idx)/DefaultUnit(50)/Description/IsActive), configCatalogsConfiguration.cs:60-74, full CRUDCatalogsFeatures.cs:260-324→ group(VẬT TƯ/THẦU PHỤ/MEP)→Category, "1 Mat"→Code, item→Name. KHÔNG cần table/migration mới. PE detail = pure free-text (PurchaseEvaluationDetail.csGroupCode/GroupName/ItemCode/NoiDung strings, NO FK→WorkItem) → load WorkItems non-breaking. Project (Project.cs:5-14, cfg:14-21): Code(50,UNIQUE[IsDeleted]=0Mig47)+Name(200) REQUIRED, StartDate/EndDate/BudgetTotal(18,2)/Note(1000)/ManagerUserId optional. ❌ THIẾU Year/Investor/Location/Package — chỉ Note free-text catch-all. Create cmdProjectFeatures.cs:67dup-check:87 AnyAsync(Code==). Supplier (Supplier.cs:5-16, cfg:14-27): Code/Name req + Type enum + TaxCode(20)/Phone/Email/Address/ContactPerson/Note.SupplierType.cs: NhaCungCap=1/NhaThauPhu=2/ToDoi=3/DonViDichVu=4/ChuDauTu=5. ❌ THIẾU Status/TinhTrang (KHÔNG có field/enum nào) + bank-acct + legal-rep (≠ContactPerson) + quality-score; "Cả hai" PHÂN LOẠI unmappable (Type single-valued). CreateCreateSupplierCommand.cs:10dup:45. Seed = idempotentexistingCodes.Contains→skip(DbInitializer.SeedDemoMasterDataAsync:2149, today 18 supplier:2155+ 8 project:2222; WorkItems 15 rows tuple-loopSeedCatalogsAsync:576-599). NO bulk import — Master chỉ single CRUD; Import/Upload hits = Forms/PE/Employees attachment only; POST one-at-a-time. Seed→prod:DbInitializer.InitializeAsyncchạy MỌI startup (Program.cs:197unless--no-db-init) →MigrateAsyncTHEN seed; demo gatedconfig.GetValue<bool>("DemoSeed:Disabled")(:80) NHƯNG SeedDemoMasterData+SeedCatalogs chạy BẤT KỂ flag (ngoài if-block :108/:115) → seed method mới auto-reach prod next deploy. Rec: idempotent DbInitializer mirror (NOT API loop). Surprise: real+demo data sẽ trộn chung Suppliers/Projects/WorkItems (18/8/15 demo rows) → cân nhắc gate demo off prod. Tag[master-import, workitem-exists, seed-idempotent, s55]. -
2026-06-10 (S57 perm-broaden blocks A/B/E/F — on-disk): ⭐ BE AUTHZ SPLIT (decision-critical for E): Config controllers gate WRITE behind
[Authorize(Roles="Admin")], READ open to any-authed:HrmConfigsController.cs:15class[Authorize]+GET open:19-21, all POST/PUT/DELRoles="Admin";CatalogsController.cs:14same (write:23+Admin);MeetingRoomsController.cs:15same (comment:9-10explicit). → granting FE read on Hrm_Config/Catalogs/MeetingRooms = pure UI-visibility, BE already correct. 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 perm is only gate, not BE-enforced). Flag em-main: making Suppliers/Projects/Departments visible-to-all ⇒ staff can write master incl. S55 prod data unless add[Authorize(Roles="Admin,CatalogManager")]or per-action policy. S55 PROD DATA location:SeedRealMasterDataAsync:2267-2460writes to Projects(62,:2270), WorkItems(71=CatalogWorkItems key,:2430-2438), Suppliers(3,:2440-2456) — all ungated idempotent per-code. 10 departments now (SeedDepartmentsAsync:2104): 9 orig + IT (:2115). 31 demo users (SeedDemoUsersAsync:1553-1609): dept spread BOD4/PM2/CCM9/PRO6/QS2/FIN2/ACT1/EQU1/HRA2; roles = mostly Drafter/CostControl/Procurement + 1 CatalogManager (catalog.manager@, dept PRO,:1608). NO user has zero-role; every demo user authenticatable. Inherit-root display:GetMyMenuTreeQuery.cs:96 HasAccess = CanRead OR Children.Any(HasAccess)→ a non-inherit root (Hrm/Off/Master) auto-shows if ANY child has CanRead, so granting leaves is enough to reveal the root node (root row itself optional for display, but grant it too for cleanliness). Inherit-roots (Contracts/Pe/Wf/PeWf) cascade root→child so root-row-only suffices there. Menu already S57-edited:Personalgroup +Off_ChamCongre-parent Off→Personal viaparentBackfill:1908. Tag[s57-perm, be-authz-split, master-write-open, s55-data, 31user]. -
2026-06-10 (S57 perm-broaden RECON blocks C/D — RAG down, on-disk): ⭐ SEED MODEL:
SeedAdminPermissionsAsyncDbInitializer.cs:1939-1977Admin loopsMenuKeys.AllCRUD=true skip-existing dedup (:1950/:1952). Calls 2 sub: (a)SeedPurchaseEvaluationPermissionDefaultsAsync:2036-2098→ 7 roles {Drafter,DeptManager,Procurement,CostControl,ProjectManager,Director,AuthorizedSigner} Read+Update on PE keys only; (b)SeedCatalogManagerPermissionsAsync:1984-2029→ role CatalogManager full-CRUD 9 master keys. NO generic per-employee Read seed — plain Drafter user sees ONLY PE keys; DOESN'T see Off_/Hrm_/Master/Contracts. Most non-admin staff today see ~nothing but PE. GetMyMenuTree:96filters CanRead=true. Permission entityPermission.cs:3-15: RoleId/MenuKey/CanRead/Create/Update/Delete. Dedup=app-level skip-existing per(RoleId,MenuKey), NO DB upsert. 13 AppRolesAppRoles.cs:23: Admin(system)+12 employee. 4 inherit-rootsGetMyMenuTreeQuery.cs:56-84: Contracts/Workflows/PurchaseEvaluations/PeWorkflows — root grant auto-cascades to child IF child no own row (:66). Hrm/Off/Master NOT inherit → each leaf needs own row or add to switch. GRANT-ALL pattern (block D): mirror CatalogManager seeder but looproleManager.Roles(all 13) × chosen key-set, CanRead=true only, insertion AFTER SeedCatalogManagerPermissionsAsync:1976. Tag[s57-perm-recon, seed-model, no-employee-default, inherit-4root]. -
2026-06-10 (menu-order cross-repo recon SE↔NAMGROUP, RAG down, on-disk): ⭐ SE menu seed =
SeedMenusAsyncDbInitializer.cstuple-list (NOT partial). Văn phòng số rootOff(Order=29):1769-1792; HR rootHrm"Nhân sự" (Order=28):1754-1767(+Hrm_Dashboardappended out-of-order:1791). ⚠️ HR SCATTERED 2 roots:Hrmholds only Hồ sơ+Cấu hình HRM(6 leaf)+Dashboard; transactional HR (Nghỉ phép/OT/Công tác/Đặt xe/Chấm công/Báo cáo CC) live underOffasOff_DonTu_*/Off_DatXe/Off_ChamCong/Off_AttendanceReport. SEED = UPSERT that RE-SETS Order (:1845-1871if(existing.Order!=o){existing.Order=o}) → reorder in code propagates to Dev/prod next deploy, NO migration. BUT Label/ParentKey/Icon NOT touched on existing rows (:1855comment) — rename needs separatelabelBackfilldict:1874. Order = BE-only:GetMyMenuTreeQuery.cs:35 OrderBy(m.Order); both FELayout.tsxrenderuseAuth().menuas-is,staticMap+menuKeys.ts= key→route ONLY (no sort). FE needs NO edit for pure reorder. NAMGROUP "Puro" = hardcoded FE array (NOT DB seed), index=order: clientInternalLayout.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" group); adminAdminLayout.tsx:87-119splits by function not HR/office. NAMGROUPĐơn từ/Phòng họp/Đề xuất= flat single links (no sub-children) vs SE deep-nested. Tag[menu-order, se-namgroup, seed-upsert-order, fe-be-driven, s57]. -
2026-06-11 (S59 recon — prod test-data wipe + PE tree Hạng mục, prod+on-disk): ⭐ Prod: PE=10 active (1 Nháp + 1 DaDuyet(7) + 8 ChoDuyet(10), MaPhieu A/031-040, ALL WorkItemId NULL) + child 20/10/20/28/138/18/18 (Sup/Det/Quote/Appr/Chg/Att/LvlOp); Contracts=7 ALL
[DEMO]05-08 pin V1 (AwId NULL) + Appr15 + details15; Budgets/WorkflowApps/Proposals/Attendances/Meetings ALL 0; Notifications 64. Seq: PE/2026/A=40 B=1; CT=7 demo prefix LastSeq=1. FK: PE child CASCADE trừQuotes→PE NO_ACTION(multi-path; Plan R S23 proved singleDELETE FROM PurchaseEvaluationsOK — NO_ACTION check end-of-statement sau cascade Details→Quotes). Contract child ALL CASCADE. PE.ApprovalWorkflowId Restrict → wipe PE trước khi xóa AW QT-DN-V2-001 v1 (inactive, còn 1 PE pin). AW V2=8: 7 ghim KEEP. Uploads orphan: purchase-evaluations/ 19 folder vs 10 PE → ~10 orphan từ S23 (file không xóa); contracts/ 1. Demo gate OK: SeedDemoContracts/PE TRONGDemoSeed:Disabled(DbInitializer:80,131-132) → wipe không resurrect. Surprise: Users 55 total / 21 active — 20 user THẬT batch 2026-06-11 06:01 (S58 seed fix ăn; thanh.lethanh NOW EXISTS — stale S57bis mem; chuong.phan typo-domain VẪN active song song twin). FE tree:pe/PurchaseEvaluationsListPage.tsx:138-179Project>Year(createdAt :150)>Supplier; SHA256 identical 2 app; PeListItem ĐÃ có workItemId/Name (types :116-118, BE Features :514/570/644) → đổi tree FE-only. Tag[s59-recon, prod-wipe, pe-tree-workitem]. -
2026-06-11 (S57bis lock no-op — prod user census, on-disk+prod): ⭐
LockDemoSampleUsersAsync(DbInitializer.cs:1552, chạy CUỐI :98) hardcode 14 named-person email (bod.huynh/pm.nguyen/fin.do/qs.hoang…) = population CHỈ CÓ TRÊN DEV. Prod 34 user ALL-active: 20 UAT-matrix placeholder hand-created batch 2026-05-13 15:04-05, scheme{act,equ,fin,hra,pm,qs}.{nv,pp,tp}@+bod.{1,2}@(FullName tự khai "ACT NV - Drafter+Accounting", "[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ùngthanh.lethanh@KHÔNG tồn tại prod) +chuong.phan@solution.com.vnTYPO-domain dup (twin đúng tạo 05-12) + admin/catalog.manager/nv.test. ROOT CAUSE seed-user never-on-prod: prodIdentity:Password:RequiredLength=12(appsettings.Production.json) vsDemoUserPassword="User@123456"=11 chars → CreateAsync silent-fail MỌI startup từ prod-init 04-21 (code comment :1675-79 đã biết); Dev fallback 8 (DependencyInjection.cs:67?? 8, Development.json no Identity section) → Dev đủ 33 user named-person.bod.1@NEVER in git pickaxe = tạo tay qua admin UI, không phải seed. Surprise: _Dev hiện CŨNG chưa khóa (Locked=0; LockoutEnd=MaxValue sẽ persist qua reconcile re-activate :1714 nếu từng chạy) → lock chưa từng execute against _Dev runtime. Fix cần 20 email prod-thật; GIỮ binh.lethanh + 9 real + admin/catalog.manager;nv.test@= creds smoke-verify (khóa = vỡ cicd smoke). Tag[s58, s57bis-lock-noop-recon, prod-user-census, pwd-policy-env-divergence]. -
2026-06-11 (S57bis PE recon — 4 đầu việc sếp, on-disk): ⭐ PE entity NO Year, NO WorkItem link (
PurchaseEvaluation.cs:15ProjectId req; Detail free-textPurchaseEvaluationDetail.cs:10-13). Create cmdPurchaseEvaluationFeatures.cs:19-30; MaPhieu gen-AT-CREATE:114-116formatPE/{YYYY}/{A|B}/{Seq:D3}(PurchaseEvaluationCodeGenerator.cs:23). Main create UI =PeWorkspaceCreateView.tsx(:151 workflow-select isUserSelectable ĐẦU TIÊN → tenGoiThau → projectId → DiaDiem → MoTa → PaymentTerms → budget; canSubmit :129 = wf+project+ten). PE controller class-[Authorize]ONLY no policy → mở menu là đủ, no silent-403. Pe_* leaves NOT inMenuKeys.All(chỉ root :156); PE defaults 7 role × 11 key (root + 2type×{group,WfView,List,Create,Pending})DbInitializer.cs:2098-2160. S57SeedAllRolesReviewReadPermissionsAsync:1993-2001InReviewScope EXCLUDES Pe; extend đúng =key == MenuKeys.PurchaseEvaluationsEXACT (prefix "Pe" sẽ dính PeWorkflows admin!) — root inherit cascade (GetMyMenuTreeQuery.cs:49-82). Demo gate: prodappsettings.json:35 DemoSeed:Disabled=true→ 7[DEMO]HĐ + 4[DEMO]PE (MaPhieu[DEMO]-A-001) KHÔNG lên prod; UNGATED trên prod = 31 users + 18 demo NCC + 8 demo project (:2244-2315) + real 62/71/3 (:2329-2522). ⚠️ Clear-demo gotcha: seed re-add per-code idempotent MỖI startup → xóa DB-only sẽ resurrect, phải gỡ khỏi DbInitializer code. WorkItem write Admin-only (CatalogsController:113-130) — CatalogManager có menu-perm nhưng API write bị chặn. Tag[s57bis, pe-recon, demo-inventory].