[CLAUDE] Docs: chốt Session 18 wrap-up — PE V2 polish + Clone B + Mig 25 IsUserSelectable + 4 bug fix UAT

Session 18 (16:56 → 19:45, 7 commit `aaa1c6c` → `32a8d4d`):
- B1 Pe Duyệt filter cứng "Đã gửi duyệt"
- B2 HistoryTab filter Trả lại / Gửi lại
- B3 Clone V2 cho B (DuyetNccPhuongAn) — audit reuse pattern
- B4 Fix silent 403 ApprovalWorkflowsV2Controller
- B5 Fix sidebar highlight queryMatches transient keys
- B6 Mig 25 IsUserSelectable + Designer pin toggle + bỏ "(clone)" + Workspace filter
- B7 Cleanup orphan zip files

Updates:
- STATUS — header 24→25 mig + 43→44 gotcha + 1 row Recently Done top + session log link
- HANDOFF — TL;DR S18 đầy đủ + cảnh báo S19+ (giữ S17 narrative §6.5)
- CLAUDE.md root — count 25 mig + Mig 25 description block
- schema-diagram §14 — heading 22→25 + cột IsUserSelectable + filter logic section + Pending S19+ Mig 26/27
- gotchas — +#44 silent 403 + checklist debug 21
- migration-todos — Phase 9 S18 done section
- session log mới đầy đủ E2E narrative

Stats: 25 mig, 58 tables, ~141 endpoints, 81 test pass (no change), 44 gotcha, 14 memory entries, 6 skill, 7 commit S18.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-05-08 19:56:42 +07:00
parent 32a8d4db0b
commit daad79d282
7 changed files with 511 additions and 10 deletions

View File

@ -609,6 +609,34 @@ session log, etc).
**Reference:** Commit `29eb5d9` add filter, verify ở commit `512880c`
(docs-only) → Gitea NO trigger run #113.
### 44. Silent 403 từ class-level `[Authorize(Policy = ...)]` quá strict (Session 18)
**Triệu chứng:** UAT 2026-05-08 — Drafter `nv.test` Workspace tạo phiếu B, dropdown "Quy trình duyệt" empty silent. Admin Designer cùng URL endpoint thấy data đầy đủ. Không có toast error / network panel hint.
**Root cause:** `ApprovalWorkflowsV2Controller` class-level `[Authorize(Policy = "Workflows.Read")]` → non-admin role (Drafter chỉ có `PurchaseEvaluations.Read`) bị 403 Forbidden khi GET `/api/approval-workflows-v2`. TanStack Query catch HTTP error trả `data=undefined`, FE component render dropdown empty không có "loading" / "error" state visible.
**Fix (`f77ea38`):** Tách policy theo action — class-level `[Authorize]` only (any authenticated), action-level chỉ POST/DELETE giữ `[Authorize(Policy = "Workflows.Create")]`:
```csharp
[ApiController]
[Route("api/approval-workflows-v2")]
[Authorize] // ← any authenticated, không hardcode policy
public class ApprovalWorkflowsV2Controller(IMediator mediator) : ControllerBase
{
[HttpGet] // ← Drafter pick workflow lúc create — read-only OK
public async Task<...> Overview(...) { ... }
[HttpPost]
[Authorize(Policy = "Workflows.Create")] // ← admin Designer
public async Task<...> Create(...) { ... }
}
```
**Pattern reusable:** Endpoint dùng cho nhiều use case (admin Designer + user list-pick) — split policy per action thay vì class-level uniform. Read-only list workflow KHÔNG nhạy cảm (chỉ là cấu hình quy trình, không expose business data).
**Phòng tránh tương lai:** Khi controller class-level `[Authorize(Policy)]`, audit role nào cần access từng action. Nếu GET cần broader role hơn POST → split policy. Default `[Authorize]` (any authenticated) cho list-pick endpoint.
**FE diagnostic improvement:** TanStack Query error nên hiển thị warning UI (toast hoặc banner) thay vì silent. Hiện tại `useQuery` catch silent → debug khó. Future: wire `onError` handler global show generic error toast.
## Checklist debug bug mới
1. Build pass không? → fail → check using + package version compat
@ -631,3 +659,4 @@ session log, etc).
18. Nếu CI fail TCP timeout 21s ở "Set up job" → bypass github.com, manual checkout từ Gitea (#39)
19. Nếu npm install caching fail `tsc not found` → KHÔNG dùng junction Move-Item, thử robocopy/Copy-Item (#40)
20. Nếu CI vẫn trigger khi commit MD-only → paths-ignore trong on:push không match patterns đúng (#41)
21. Nếu user phàn nàn "feature work cho admin nhưng user empty/403 silent" → check class-level Authorize policy có over-restrict cho non-admin không, split per action (#44)