67da186672
- Add context config endpoints (GET/PUT /api/ai/prompts/:type/:version/context-config) - Add execution profile endpoints (CRUD /api/ai/execution-profiles) - Add sandbox RAG Prep endpoint (POST /api/ai/admin/sandbox/rag-prep) - Create Prompt Management UI with multi-type support - Add ContextConfigEditor, PromptEditor, RuntimeParametersPanel components - Add SandboxTabs for 3-step workflow (OCR, Extract, RAG Prep) - Add database deltas for ai_execution_profiles and additional prompt types - Update quickstart.md with production backend URLs - Add comprehensive test coverage for new features
6.0 KiB
6.0 KiB
Session — 2026-06-14 (Correspondence Module Review Fixes + RFA ADR-001/021 Refactor)
Summary
สองงานหลักใน session นี้:
- Correspondence Module Code Review Fixes — แก้ทุก item จาก
speckit-reviewerreport (HIGH + MEDIUM + Remaining) - RFA Service ADR-001/021 Migration — User refactor
rfa.service.tsตัด deprecated routing-template entities ออก และ rewire workflow ผ่าน Unified Workflow Engine
Part 1: Correspondence Module Review Fixes
ปัญหาที่พบ (Root Cause)
รายการจาก code review report ที่ต้องแก้ไข:
| # | Severity | ปัญหา |
|---|---|---|
| 1 | HIGH | throw new Error ใน processAction — ละเมิด ADR-007 |
| 2 | HIGH | CSV export capped ที่ 10 rows เพราะ findAll ใช้ default limit: 10 |
| 3 | MEDIUM | bulkCancel empty catch {} — ไม่ log error |
| 4 | MEDIUM | escapeCsv ไม่กัน formula injection (OWASP) |
| 5 | MEDIUM | update() re-index search ด้วย hardcoded status: 'DRAFT' |
| 6 | LOW | processAction ไม่มี @Audit decorator |
| R1 | Remaining | recipients DTO ไม่มี nested validation |
| R2 | Remaining | PUT /:uuid ใช้ permission correspondence.create แทน correspondence.edit |
| R3 | Remaining | ไม่มี Idempotency protection บน mutation endpoints |
การแก้ไข (Fix)
| ไฟล์ | การเปลี่ยนแปลง |
|---|---|
correspondence.controller.ts |
เพิ่ม import { ValidationException } + แทน throw new Error ด้วย throw new ValidationException |
correspondence.controller.ts |
เพิ่ม @Audit('correspondence.workflow_action', 'correspondence') บน processAction |
correspondence.controller.ts |
แก้ PUT /:uuid → @RequirePermission('correspondence.edit') (permission id=73 มีใน seed แล้ว) |
correspondence.controller.ts |
เพิ่ม @UseInterceptors(IdempotencyInterceptor) ทุก 7 mutation endpoints |
correspondence.service.ts |
bulkCancel catch block เพิ่ม this.logger.warn(...) |
correspondence.service.ts |
exportCsv force limit: 10000 override |
correspondence.service.ts |
escapeCsv เพิ่ม prefix ' สำหรับ values เริ่มต้นด้วย =, +, -, @, \t, \r |
correspondence.service.ts |
update() re-index ใช้ currentRevisionStatus จาก revisions.find(r => r.isCurrent) แทน 'DRAFT' |
dto/create-correspondence.dto.ts |
เพิ่ม RecipientDto class + @ValidateNested({ each: true }) + @Type(() => RecipientDto) |
กฎที่ Lock แล้ว
- CSV export ต้อง override
limitก่อน callfindAllเสมอ (ห้ามใช้ pagination default) escapeCsvต้องกัน OWASP formula injection (prefix'สำหรับ=+−@\t\r)- Mutation endpoints ใน correspondence controller ต้องมี
@UseInterceptors(IdempotencyInterceptor) PUT /:uuidต้องใช้correspondence.editpermission (ไม่ใช่correspondence.create)
Part 2: RFA Service ADR-001/021 Migration (User-driven)
สิ่งที่ User เปลี่ยนแปลง
| ไฟล์ | การเปลี่ยนแปลง |
|---|---|
rfa.service.ts |
ลบ CorrespondenceRouting, RoutingTemplate, RoutingTemplateStep imports และ repos |
rfa.service.ts |
เพิ่ม RfaMapped interface fields: workflowInstanceId, workflowState, availableActions (ADR-021) |
rfa.service.ts |
เพิ่ม static constants: WORKFLOW_CODE, STATE_TO_STATUS, DEFAULT_APPROVED_CODE |
rfa.service.ts |
EC-RFA-001 check ย้ายเข้า transaction + FOR UPDATE lock (กัน TOCTOU race condition) |
rfa.service.ts |
createInstance ใช้ RfaService.WORKFLOW_CODE constant แทน hardcoded 'RFA_APPROVAL' |
rfa.service.ts |
findOneByUuid ดึง workflow instance ผ่าน getInstanceByEntity() และ expose ADR-021 fields |
rfa.service.ts |
submit() ตัด templateId parameter ออก — rewire ผ่าน workflowEngine.processTransition() |
rfa.service.ts |
processAction() ตัด routing-template lookup ออก — ใช้ workflowEngine.processTransition() |
rfa.service.ts |
เพิ่ม syncRevisionStatus() helper: map workflow state → RFA status code + approve code |
rfa.service.ts |
เพิ่ม notifyRecipients() helper: ADR-008 async notify ผ่าน notificationService.send() |
rfa.module.ts |
ตัด deprecated routing-template entities ออกจาก TypeOrmModule.forFeature([...]) |
กฎที่ Lock แล้ว
- RFA ใช้
workflowEngine.processTransition()เป็น single entry point สำหรับ submit/approve/reject syncRevisionStatus()ต้องใช้STATE_TO_STATUSmap — ห้าม hardcode status code- EC-RFA-001 ต้องทำใน transaction ด้วย
FOR UPDATElock (ไม่ใช่ก่อน transaction) - Notification ต้องเรียกหลัง transaction commit แบบ
void ... .catch(...)(ADR-008)
Verification
pnpm --filter backend buildผ่าน (ต้องตรวจสอบหลัง rfa.module.ts cleanup ครบ)pnpm --filter backend exec tsc --noEmitไม่มี type error- ทดสอบ
POST /correspondenceswithIdempotency-Keyheader — duplicate request ต้องได้ cached response - ทดสอบ CSV export มีมากกว่า 10 rows
- ทดสอบ
PUT /correspondences/:uuidกับ user ที่มีcorrespondence.editpermission - ทดสอบ
recipientsDTO validation กัน invalidtype(ไม่ใช่ TO/CC)