Files
lcbp3/specs/88-logs/session-2026-06-14-correspondence-review-fixes.md
T
admin 67da186672
CI / CD Pipeline / build (push) Failing after 3m23s
CI / CD Pipeline / deploy (push) Has been skipped
feat(ai): implement unified prompt management UX/UI (ADR-037)
- 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
2026-06-14 19:55:43 +07:00

6.0 KiB
Raw Blame History

Session — 2026-06-14 (Correspondence Module Review Fixes + RFA ADR-001/021 Refactor)

Summary

สองงานหลักใน session นี้:

  1. Correspondence Module Code Review Fixes — แก้ทุก item จาก speckit-reviewer report (HIGH + MEDIUM + Remaining)
  2. 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 ก่อน call findAll เสมอ (ห้ามใช้ pagination default)
  • escapeCsv ต้องกัน OWASP formula injection (prefix ' สำหรับ =+@\t\r)
  • Mutation endpoints ใน correspondence controller ต้องมี @UseInterceptors(IdempotencyInterceptor)
  • PUT /:uuid ต้องใช้ correspondence.edit permission (ไม่ใช่ 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_STATUS map — ห้าม hardcode status code
  • EC-RFA-001 ต้องทำใน transaction ด้วย FOR UPDATE lock (ไม่ใช่ก่อน 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 /correspondences with Idempotency-Key header — duplicate request ต้องได้ cached response
  • ทดสอบ CSV export มีมากกว่า 10 rows
  • ทดสอบ PUT /correspondences/:uuid กับ user ที่มี correspondence.edit permission
  • ทดสอบ recipients DTO validation กัน invalid type (ไม่ใช่ TO/CC)