[CLAUDE] Docs: S22 chốt cuối — gotcha #47 + 4 agent MEMORY flush + session log cumulative
Session 22 chốt cuối — bro confirm sub-agent solution OK. Highlights cumulative S21 chốt → S22 chốt: - 11 commits S22 pushed remote `3d725c4..b04a11a` - Plan G S22 evidence: 4 sub-agents (3 seeds-only + 1 CICD Monitor Run #188 PASS) - Plan C + D + E done · Plan F ABORTED pre-flight blocker - 5 turn S22+ feedback iteration (disable 3 button + seed 20 user + rename role-based + attachment view + Mig 30 per-NV opt-in) Docs updates: - STATUS Last updated S22 chốt + S22 prev row preserved (§6.5 KEEP narrative) - HANDOFF Last updated S22 chốt + S22 prev row preserved - Session log mới `2026-05-13-2200-s22-chot-cuoi.md` (~12KB narrative + 11 commit table + 7 lessons learned + handoff S23) - Gotcha #47 mới `.claude/agent-memory/** thiếu paths-ignore filter` (CICD waste 3.5min per MEMORY flush) — PENDING bro fix `.gitea/workflows/deploy.yml` 4 agent MEMORY.md flushed S22: - Investigator: 30 mig + 104 test + S22 context essentials + Mig 30 entry + cross-ref `feedback_per_nv_permission_scope` 2× reinforced - Implementer: +6 patterns (7-12 per-NV opt-in / tách endpoint narrow scope / defense-in-depth FE+BE / reflection regression / cookie-cutter test infra / InternalsVisibleTo) + S22 activity (REFUSED 100% cross-stack) - Reviewer: +Gotcha #47 + Mig 30 + 104 test baseline + S22 self-review narrative + Identity password ≥12 chars note - CICD Monitor: refresh test 84 → 104 + Mig 29 → 30 (Run #188 PASS preserved) User memory reinforcement: - `feedback_per_nv_permission_scope.md` +Section "Reinforcement S22+5" — pattern proven 2× với Mig 30 F4. Anti-pattern default scope expansion. Decision tree thêm scope khi feedback ambiguous → admin opt-in flag per slot - `MEMORY.md` index entry updated cross-ref S22+5 reinforcement Stats final: - 30 migrations (+1 Mig 30) - 104 tests PASS (+20 S22) - 47 gotchas (+1 #47 pending fix) - ~146 endpoints (+3) - 33 active prod users (rename role-based) - 6 skills · 4 sub-agents unchanged KHÔNG cắt narrative cũ — Edit specific lines + Append new entries per §6.5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -102,6 +102,66 @@ const isValidPhone = (s: string) => !s || PHONE_RE.test(s.replace(/[\s\-.]/g, ''
|
||||
const isValidEmail = (s: string) => !s || EMAIL_RE.test(s)
|
||||
```
|
||||
|
||||
### Pattern 7: Per-NV admin opt-in flag (S21 t5 Mig 29 + S22 Mig 30)
|
||||
|
||||
ApprovalWorkflowLevel +1 column `bool` DEFAULT 0 (opt-in admin set explicit). EF config `HasDefaultValue(false)`. DTO extend field. FE Designer checkbox inline mỗi Level row.
|
||||
|
||||
Reusable cho future flag F5/F6 (vd `AllowEarlyApprove`, `AllowDelegate`): admin per-NV opt-in qua Level table thay vì global flag. Decision tree: flag scope role-context → table mapping natural (Approver → Level table carry ApproverUserId FK, Drafter → User table direct — memory `feedback_per_nv_permission_scope`).
|
||||
|
||||
Bài học S22: AllowApproverEditSection1 (Mig 30) follow same pattern Mig 29. 0 schema redesign cần.
|
||||
|
||||
### Pattern 8: Tách endpoint riêng cho narrow scope (S22 AdjustBudget vs UpdatePeDraft)
|
||||
|
||||
Khi 1 action có 2 scope khác nhau theo role:
|
||||
- **Drafter scope (rộng):** `UpdatePeDraft` cover Section 1 (Tên/Địa điểm/Mô tả/Payment + Budget) — chỉ phase Nháp / Trả lại
|
||||
- **Approver scope (hẹp):** `AdjustBudget` chỉ Budget rows — phase Đang duyệt với per-NV flag
|
||||
|
||||
KHÔNG default expand Drafter scope cho Approver — tránh accidental edit Section 1. Endpoint tách riêng = guard tự nhiên + audit trail rõ.
|
||||
|
||||
Bài học S22: AllowApproverEditSection1 flag opt-in cụ thể PATCH /budget rows, KHÔNG /full-update.
|
||||
|
||||
### Pattern 9: Defense-in-depth FE + BE guard pair (S22+1)
|
||||
|
||||
UI button `disabled={!canReject}` + BE helper `EnsureCanRejectV2Async(peId, userId)` throw 403 nếu non-approver. Tránh request forge non-approver gọi PATCH direct qua DevTools.
|
||||
|
||||
Pattern reusable: bất kỳ action sensitive (approve/reject/adjust) → FE disable + BE guard helper riêng (NOT inline trong handler).
|
||||
|
||||
Bài học S22+1: 3 button (Duyệt / Trả lại / Từ chối) — UI disable + BE helper. Tránh leak action qua API direct.
|
||||
|
||||
### Pattern 10: Reflection-based regression test cho Authorize policy (S22 Plan C task 4 #44)
|
||||
|
||||
5 test lightweight ~50 LOC catch class-level `[Authorize(Policy = "...")]` regression:
|
||||
```csharp
|
||||
var attr = typeof(ControllerXxx).GetCustomAttribute<AuthorizeAttribute>();
|
||||
attr.Policy.Should().Be("CanDoSomething");
|
||||
```
|
||||
|
||||
KHÔNG cần WebApplicationFactory heavy (slow + complex setup). Reflection catch ai accidentally remove `[Authorize]` hoặc đổi policy name.
|
||||
|
||||
Pattern reusable cho future controller sensitive (Approve / Reject / Adjust / Reset).
|
||||
|
||||
### Pattern 11: Test infra helper cookie-cutter (S22)
|
||||
|
||||
Trong `PurchaseEvaluationWorkflowServiceReturnModeTests` + `PurchaseEvaluationDraftGuardTests`:
|
||||
|
||||
```csharp
|
||||
private async Task<Guid> SeedWorkflowAsync(...) {
|
||||
// 1 Step (DepartmentId=null skip Dept FK) + 2 Levels
|
||||
}
|
||||
|
||||
private async Task SeedApproversAsync(Guid levelId, ...) {
|
||||
// Multi user via fix.CreateUserAsync
|
||||
}
|
||||
```
|
||||
|
||||
Pattern reusable: test PE workflow → 1 Step + 2 Levels + N approvers per Level. `DepartmentId=null` skip Dept FK ràng buộc. Token cost ~80 LOC repeated cross 2 test class S22.
|
||||
|
||||
### Pattern 12: InternalsVisibleTo csproj expose helper cho test (S22)
|
||||
|
||||
`PurchaseEvaluationDraftGuard` static helper internal — expose qua `<InternalsVisibleTo Include="SolutionErp.Infrastructure.Tests" />` trong `SolutionErp.Application.csproj` thay vì rewrite public API.
|
||||
|
||||
Tránh API surface bloat. Reusable cho future guard / helper internal cần test.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Anti-patterns observed (DO NOT)
|
||||
@ -121,7 +181,7 @@ const isValidEmail = (s: string) => !s || EMAIL_RE.test(s)
|
||||
|
||||
- **BE .NET 10:** PascalCase tiếng Anh entities + DTO records + command names. CQRS + MediatR + FluentValidation + AutoMapper. Repository qua `IApplicationDbContext`. `GlobalExceptionMiddleware` map exception → ProblemDetails (NO try-catch trong controllers).
|
||||
- **FE React 19 + Vite 8 + TS 6:** Named export only (trừ App). TanStack Query. shadcn/ui copy-paste. TS6 `erasableSyntaxOnly` cấm `enum` → const-object pattern. UI 100% tiếng Việt. Mirror 2 app rule §3.9.
|
||||
- **Test:** baseline 84/84 PASS (58 Domain + 26 Infra: 23 baseline + 3 PE WF guard regression S21 t3 gotcha #45). Phase 9 UAT skip per chunk theo memory `feedback_uat_skip_verify`. Stack xUnit + FluentAssertions 7.2 + EF SQLite 10 `TestApplicationDbContext` override `nvarchar(max) → TEXT`.
|
||||
- **Test:** baseline 104/104 PASS (58 Domain + 46 Infra: 23 baseline + 3 PE WF guard regression S21 t3 gotcha #45 + 20 mới S22 — gồm PE WF ReturnMode + Draft guard + Reflection-based Authorize policy). Phase 9 UAT skip per chunk theo memory `feedback_uat_skip_verify`. Stack xUnit + FluentAssertions 7.2 + EF SQLite 10 `TestApplicationDbContext` override `nvarchar(max) → TEXT`.
|
||||
- **Build:** `dotnet build SolutionErp.slnx` clean 0 err + `npm run build` × 2 app pass.
|
||||
- **Commit:** `[CLAUDE] <scope>: <message>` + Co-Authored-By Claude Opus 4.7 (1M context).
|
||||
|
||||
@ -144,6 +204,7 @@ KHÔNG `*` / `latest`. Critical pins:
|
||||
|
||||
## 📅 Recent activity (last 10 FIFO)
|
||||
|
||||
- **2026-05-13 (S22, REFUSED 100%):** Em main classified ALL S22 work as cross-stack reasoning chain (BE Mig + Service guard + DTO + FE Designer + FE Section + FE types + tests) → REFUSE per criteria #3+#4. Em main solo executed. State chốt S22: **30 migrations** (+1 Mig 30 AllowApproverEditSection1 per-NV F4 flag), **104 test PASS** (+20 từ 84 — gồm PE WF ReturnMode + Draft guard + Reflection-based Authorize policy regression), ~146 endpoints (+3), 46 gotchas unchanged, 33 active prod users (13 cũ + 20 mới S22+2). 7 patterns successfully applied throughout S22 (validated continued effectiveness): Pattern 7 per-NV admin opt-in flag (Mig 30 follow Mig 29), Pattern 2 EF migration 3-file rule, Pattern 8 tách endpoint narrow scope (AdjustBudget vs UpdatePeDraft), Pattern 9 defense-in-depth FE+BE guard pair (S22+1 disable 3 button), Pattern 10 Reflection-based regression test cho Authorize policy (Plan C task 4 #44, 5 test ~50 LOC), Pattern 11 test infra helper cookie-cutter (SeedWorkflowAsync + SeedApproversAsync), Pattern 12 InternalsVisibleTo csproj expose internal helper cho test. Mismatches discovered S22: (1) "Đang trong quá trình duyệt = người điều chỉnh cũng là người duyệt" — em first interpret default Approver scope always allowed → bro corrected per-NV admin opt-in flag (Mig 30). Lesson: clarify default behavior vs admin opt-in TRƯỚC khi default scope expansion. (2) `PE.changelogs` field KHÔNG có trong PeDetailBundle — em first design history display trong BudgetAdjustSection, build FAIL TS2339. Fix: removed history display (defer S23+ via separate fetch endpoint). (3) Dialog `size="xl"` NOT supported — only "sm" | "md" | "lg". Use "lg" cho preview iframe. (4) API auth field `accessToken` không phải `token`. Script `seed-test-users-prod.ps1` lần đầu FAIL 401 sau auth — em fix `$authResp.accessToken`.
|
||||
- **2026-05-13 (S21 t3-t5, REFUSED 3×):** Em main classified all 3 turns as cross-stack reasoning chain (BE+FE+test tightly coupled) → REFUSE per criteria #3+#4 (cross-stack > 2 layers, bug fix reasoning chain). Bug fix gotcha #45 = bug + reasoning, F1+F2+F3 = schema design decision, Refactor per-NV = drastic refactor schema + Service + FE × 2 app. All correct REFUSE — em main solo executed. Strict scope criteria validated S21 t3-t5 — REFUSE rate 100% match Anthropic warning "tightly interdependent coding". Cumulative: 84 test, 29 mig, 45 gotcha. Pattern saved future invocation: per-NV permission scope split natural theo role + EF migration BACKFILL reorder pattern.
|
||||
- **2026-05-11 (setup):** Implementer agent initialized. Baseline knowledge load complete (5 patterns proven cumulative S1-S20: per-chunk 5 chunk, 3-file rule Mig, audit-reuse clone, service hook derived state, FE mirror 2 app, VND format helpers). No implementations performed yet. Awaiting first SendMessage from em main. Strict scope auto-refuse criteria active.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user