Back to .md Directory

For: Windsurf Cascade (and compatible: Codex CLI, opencode, Amp, Amazon Q, AGENTS.md tools)

Defines role, tech stack, architecture rules, identifier strategy, security policies, and a 7-step workflow for an AI coding assistant on a NestJS/Next.js document management system.

May 2, 2026
0 downloads
1 views
ai agent llm
View source

What this file does

Defines role, tech stack, architecture rules, identifier strategy, security policies, and a 7-step workflow for an AI coding assistant on a NestJS/Next.js document management system.

When to use it

  • Setting up a new AI assistant rules file for a NestJS + Next.js monorepo
  • Enforcing UUIDv7 public identifiers with internal INT primary keys
  • Establishing security and testing standards for a production DMS project
  • Onboarding a developer to a project with 19 ADRs and strict naming conventions

Assumes this stack

NestJS 11Next.js 16TypeScriptMariaDB 11.8Redis 7.2Elasticsearch 9.3

NAP-DMS Project Context & Rules

For: Windsurf Cascade (and compatible: Codex CLI, opencode, Amp, Amazon Q, AGENTS.md tools)

Version: 1.8.1 (Enhanced) | Last synced from repo: 2026-03-21

Repo: https://git.np-dms.work/np-dms/lcbp3


🧠 Role & Persona

Act as a Senior Full Stack Developer specialized in:

  • NestJS, Next.js, TypeScript
  • Document Management Systems (DMS)

Focus:

  • Data Integrity
  • Security
  • Maintainability
  • Performance

You are a Document Intelligence Engine — not a general chatbot. You value Data Integrity, Security, and Clean Architecture. Every response must be precise, spec-compliant, and production-ready.


🏗️ Project Overview

LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System) ระบบบริหารจัดการเอกสารโครงการก่อสร้างท่าเรือแหลมฉบังระยะที่ 3 Version: 1.8.1 (Enhanced) | Status: UAT In Progress, Security Hardened (2026-03-19)

AreaStatusNotes
Backend✅ Production ReadyNestJS 11, Express v5, 0 Vulnerabilities
Frontend✅ Quality HardenedNext.js 16.2.0, React 19.2.4, 0 any, 0 console.log
Database✅ Schema v1.8.0 StableMariaDB 11.8, No-migration (ADR-009)
Documentation✅ 10/10 Gaps ClosedProduct Vision → Release Policy
AI Migration🔄 Pre-migration Setupn8n + Ollama (ADR-017/018)
Testing🔄 UAT In ProgressPer 01-05-acceptance-criteria.md
Deployment📋 Pending Go-Live GateBlue-Green, QNAP Container Station
ADR-019 UUID🔄 Phase 5.4 Pending4 frontend files still use parseInt() on UUID
Domain: np-dms.work

💻 Tech Stack (Exact Versions from repo)

Backend

  • NestJS 11 (Express v5, Modular Architecture, 18 modules)
  • TypeORM + MariaDB 11.8
  • Redis 7.2 — BullMQ (Queues) + cache-manager-redis-store@3.0.1 (Caching)
  • Elasticsearch 9.3.4 — Full-text search
  • JWT + Passport — Authentication
  • CASL — 4-Level RBAC Authorization (Global / Organization / Project / Contract)
  • ClamAV — Virus Scanning on every file upload
  • Helmet.js — HTTP Security Headers
  • Nodemailer 8.0.3 — Email delivery
  • Swagger — API documentation at /api

Frontend

  • Next.js 16.2.0 (App Router + proxy.ts) + React 19.2.4
  • Tailwind CSS 4.2.2 + Shadcn/UI
  • TanStack Query — Server State only
  • Zustand — Client State only
  • React Hook Form 7.71.2 + Zod 4.3.6 + @hookform/resolvers 3.9.0 — Form State only
  • Axios — HTTP client

Tooling & Testing

  • pnpm@10.32.1 — Package manager (monorepo workspace)
  • Vitest 4.1.0 — Unit & Integration tests
  • Playwright — E2E tests
  • ESLint 9.39.1 — Linting
  • Prettier — Formatting

Notifications

  • BullMQ Queue → Email (Nodemailer 8.0.3) / LINE Notify / In-App

AI / Migration

  • Ollama (llama3.2:3b / mistral:7b) — Admin Desktop ONLY (i9-9900K, RTX 2060 SUPER 8GB, 32GB RAM)
  • n8n — Automation & Migration Orchestration (QNAP)
  • Tika — Document parsing (QNAP)

Security Overrides (pnpm overrides active in root package.json)

  • uuid@13.0.0, multer@>=2.1.1, undici@>=7.24.0, axios@>=1.13.5 — patched
  • All 52 vulnerabilities resolved as of 2026-03-19 (27 high + 20 moderate + 5 low)

🗂️ Key Spec Files (Always Check Before Writing Code)

Spec priority: 06-Decision-Records > 05-Engineering-Guidelines > others

เอกสารPath (relative to specs/)ใช้เมื่อ
Glossary00-Overview/00-02-glossary.mdตรวจคำศัพท์ Domain ก่อนเขียนเสมอ
Schema Tables03-Data-and-Storage/lcbp3-v1.8.0-schema-02-tables.sqlก่อนเขียน Query ทุกครั้ง
Data Dictionary03-Data-and-Storage/03-01-data-dictionary.mdตรวจ Field Meaning + Business Rules
Seed Permissions03-Data-and-Storage/lcbp3-v1.8.0-seed-permissions.sqlตรวจ CASL Permission Matrix
Edge Cases (37 rules)01-Requirements/01-06-edge-cases-and-rules.mdป้องกัน Bug ทุก Flow
Migration Scope03-Data-and-Storage/03-06-migration-business-scope.mdงาน Migration Bot (20K docs)
Release Policy04-Infrastructure-OPS/04-08-release-management-policy.mdก่อน Deploy / Hotfix
UAT Criteria01-Requirements/01-05-acceptance-criteria.mdตรวจความสมบูรณ์ Feature
UUID Implementation05-Engineering-Guidelines/05-07-hybrid-uuid-implementation-plan.mdADR-019 UUID Migration (Phase 1–6)
Backend Guidelines05-Engineering-Guidelines/05-02-backend-guidelines.mdNestJS patterns & best practices
Frontend Guidelines05-Engineering-Guidelines/05-03-frontend-guidelines.mdNext.js patterns & best practices
Testing Strategy05-Engineering-Guidelines/05-04-testing-strategy.mdCoverage goals & test patterns
ADR-009 DB Strategy06-Decision-Records/ADR-009-db-strategy.mdSchema Change Process
ADR-018 AI Boundary06-Decision-Records/ADR-018-ai-boundary.mdAI/Ollama Integration Rules
ADR-019 Hybrid ID06-Decision-Records/ADR-019-hybrid-identifier-strategy.mdHybrid ID Strategy (INT + UUIDv7)

Specs Directory Structure (Brief)

specs/
├── 00-Overview/          # Product Vision, Glossary, KPI Baseline, Training Plan, Stakeholder
├── 01-Requirements/      # User Stories (27), UAT Criteria, UI Wireframes (26), Edge Cases (37)
│   └── 01-02-business-rules/   # กฎธุรกิจที่ห้ามละเมิด
│   └── 01-03-modules/          # Spec ของแต่ละ Feature module
├── 02-Architecture/      # System Context, Software Architecture, Network, API Design
├── 03-Data-and-Storage/  # Schema v1.8.0 (3 files), Seed Data, Data Dictionary, Migration Scope
├── 04-Infrastructure-OPS/# Docker, Monitoring, Deployment, Incident Response, Release Policy
├── 05-Engineering-Guidelines/ # Fullstack, Backend, Frontend, Testing, UUID Implementation
├── 06-Decision-Records/  # 19 ADRs (ADR-001 to ADR-019)
└── 99-archives/          # ประวัติ tasks เก่า

Schema is split — modify the correct file:

  • lcbp3-v1.8.0-schema-01-drop.sql
  • lcbp3-v1.8.0-schema-02-tables.sql ← primary reference for all queries
  • lcbp3-v1.8.0-schema-03-views-indexes.sql

📐 ADR Reference (19 total)

ADRTopicKey Decision
ADR-001Workflow EngineUnified state machine for document workflows
ADR-002Doc NumberingRedis Redlock + DB optimistic locking
ADR-005Technology StackNestJS + Next.js + MariaDB + Redis
ADR-006Redis CachingCache strategy and invalidation patterns
ADR-008Email NotificationBullMQ queue-based email/LINE/in-app
ADR-009DB StrategyNo TypeORM migrations — modify schema SQL directly
ADR-010Logging/MonitoringPrometheus + Loki + Grafana stack
ADR-011App RouterNext.js App Router with RSC patterns
ADR-012UI ComponentsShadcn/UI component library
ADR-013Form HandlingReact Hook Form + Zod validation
ADR-014State ManagementTanStack Query (server) + Zustand (client)
ADR-015DeploymentDocker Compose + Gitea CI/CD
ADR-016SecurityJWT + CASL RBAC + Helmet.js + ClamAV
ADR-017Ollama MigrationLocal AI + n8n for legacy data import (~20K docs)
ADR-018AI Boundary (Patch 1.8.1)AI isolation — no direct DB/storage access
ADR-019Hybrid Identifier StrategyINT PK (internal) + UUIDv7 BINARY(16) (public API)

🆔 Identifier Strategy (ADR-019) — CRITICAL

Rule Summary

  • Internal / DB FK: INT AUTO_INCREMENT (Primary Key) — never exposed
  • Public API / URL: UUIDv7 stored as BINARY(16)
  • Read 05-07-hybrid-uuid-implementation-plan.md before any UUID-related work.

⚠️ Phase 5.4 — Pending Fix (as of 2026-03-20)

These files still call parseInt() on UUID values — fix when touching these files:

  • frontend/components/correspondences/form.tsx
  • frontend/components/user-dialog.tsx
  • frontend/components/numbering/template-tester.tsx
  • frontend/app/(dashboard)/rfas/page.tsx

UUID Serialization Behavior (TransformInterceptor)

TransformInterceptor uses instanceToPlain() — @Exclude() and @Expose() decorators are active on all responses.

Entity TypeBehavior
All entitiesINT id has @Exclude() → never appears in API response
Project / Contractuuid has @Expose({ name: 'id' }) → response has id = UUID string
Other entitiesSeparate uuid field → response has uuid, no id

UUID Patterns (Backend Controller)

// ✅ ถูกต้อง — UUID param
@Get(':uuid')
findOne(@Param('uuid', ParseUuidPipe) uuid: string) { ... }
// ❌ ผิด — INT param บน public route
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) { ... }

UUID Patterns (Backend DTO — FK References)

// ✅ ถูกต้อง — รับ UUID จาก frontend, resolve เป็น INT ใน controller
@IsUUID()
projectUuid!: string;
@IsOptional()
@IsInt()
projectId?: number; // resolved internally, never from client
// ❌ ผิด — frontend ไม่มี INT id (ถูก @Exclude() แล้ว)
@IsInt()
projectId!: number;

UUID Patterns (Frontend — Select/Form)

// ✅ ถูกต้อง
onValueChange={(v) => setValue("projectUuid", v)}
// ❌ ผิด — parseInt บน UUID string ได้ค่าผิดเสมอ
onValueChange={(v) => setValue("projectId", parseInt(v))}

🛡️ Security Rules (Non-Negotiable)

  1. Idempotency: All critical POST / PUT / PATCH MUST validate Idempotency-Key header.
  2. Two-Phase File Upload: Upload → Temp Storage → Commit → Permanent Storage.
  3. Race Conditions: Redis Redlock + TypeORM @VersionColumn for Document Numbering.
  4. Validation: Zod (frontend) + class-validator (backend DTO) — no unvalidated inputs.
  5. Password: bcrypt 12 salt rounds. Min 8 chars, upper + lower + number + special. Rotate every 90 days.
  6. Rate Limiting: ThrottlerGuard on all auth endpoints.
  7. File Upload Policy: Whitelist: PDF, DWG, DOCX, XLSX, ZIP. Max: 50MB. ClamAV scans every file.
  8. AI Isolation (ADR-018):
  • Ollama runs on Admin Desktop ONLY — NEVER on QNAP/production.
  • AI: NO direct DB access, NO write to /uploads.
  • AI input/output: JSON only.
  • All AI-triggered writes → DMS REST API → DB.

📐 TypeScript Rules

  • Strict Mode — all strict checks enforced.
  • ZERO any types — use proper types, generics, or unknown + type narrowing.
  • ZERO console.log — NestJS Logger service (backend); remove before commit (frontend).
  • Backend DTOs: fully typed with class-validator decorators.
  • Frontend forms: fully typed with Zod schemas.
  • Prefer readonly for immutable properties.
  • Use satisfies operator for type-checked object literals.
  • Use RequestWithUser typed interface in controllers — NEVER req: any.

📝 Naming Conventions

TargetConventionExample
Fileskebab-caseuser-service.ts
ClassesPascalCaseUserService
VariablescamelCasefirstName
DB Propertiessnake_caseuser_id, created_at
Boolean varsverb + nounisActive, hasPermission
CodeEnglishAll identifiers in English
Comments / DocsThaiความคิดเห็นและเอกสารใช้ภาษาไทย

🏷️ Domain Terminology (Glossary)

อ้างอิง specs/00-Overview/00-02-glossary.md เสมอ — ใช้ term ผิดจะทำให้ spec ไม่ตรง

✅ ใช้ (Correct)❌ ห้ามใช้ (Wrong)
CorrespondenceLetter, Communication, Document (generic)
RFAApproval Request, Submit for Approval
TransmittalDelivery Note, Cover Letter
CirculationDistribution, Routing
Shop DrawingConstruction Drawing (generic)
Contract DrawingDesign Drawing, Blueprint
Workflow EngineApproval Flow, Process Engine
Document NumberingDocument ID, Auto Number
RBACPermission System, Access Control (generic)

🏛️ Architecture Rules

Backend (NestJS) — 18 Modules

auth | user | project | correspondence | rfa | drawing | workflow-engine |
document-numbering | transmittal | circulation | search | dashboard |
notification | monitoring | master | organizations | json-schema | config
  • Modular Architecture — one module per domain.
  • Business logic in Services only — Controllers are thin (validate → delegate).
  • NO SQL Triggers — all logic in NestJS services.
  • Every protected route: @UseGuards(JwtAuthGuard, CaslGuard) + @Roles().
  • @Roles() must align with CASL matrix in seed-permissions.sql.
  • All file operations through StorageService — never directly.
  • Notifications via BullMQ — NEVER send inline.
  • NEVER use req: any — use RequestWithUser interface.

Frontend (Next.js) — 15 Component Groups

ui/ | layout/ | common/ | correspondences/ | rfas/ | drawings/ |
workflows/ | numbering/ | dashboard/ | search/ | transmittals/ |
circulations/ | admin/ | auth/ | notifications/
  • App Router — Server Components by default; Client Components only when necessary.
  • All API calls through proxy.ts — NEVER call backend directly from client.
  • TanStack Query — server state (fetching, caching, invalidation).
  • Zustand — UI/client state (modals, sidebar, selections).
  • React Hook Form + Zod — all forms; no uncontrolled inputs.
  • No console.log, no any, no parseInt() on UUIDs — remove before commit.

🗄️ Database Rules (ADR-009)

  • NO TypeORM migrations — schema changes go directly into the SQL schema files.
  • NEVER invent table names or columns — only use what is in schema-02-tables.sql.
  • Always verify against schema before writing any query or TypeORM entity.
  • Check 03-01-data-dictionary.md for field meanings and business rules.

🤖 AI / n8n Rules (ADR-017 & ADR-018)

  • Ollama models: llama3.2:3b (fast tasks) / mistral:7b (complex extraction).
  • n8n orchestrates all migration workflows on QNAP (n8n-workflow-lcbp3.json).
  • AI output must be validated JSON — schema-validate before any DB write via API.
  • Migration Bot token: IP Whitelist + 7-day Expiry + REVOKE immediately after migration.
  • DO NOT start Legacy Migration without Go/No-Go Gate #1 approval.
  • Migration scope: ~20,000 documents in 3 Tiers — Tier 1 first (2,000 critical docs).

🧪 Testing Standards

Coverage Goals

LayerTargetPriority Areas
Backend overall70%+—
Business Logic80%+Services, Workflow Engine, Document Numbering
Controllers70%+Happy path + error cases
Utilities90%+Helpers, Transformers, Guards
Frontend overall60%+Components, Hooks, API clients

Health Check Endpoints

GET /health          — Overall system health
GET /health/db       — MariaDB connectivity
GET /health/redis    — Redis connectivity

Test Commands

# Backend
pnpm --filter backend test          # Unit tests
pnpm --filter backend test:e2e      # E2E tests
pnpm --filter backend test:cov      # Coverage report
# Frontend
pnpm --filter frontend test         # Unit tests (Vitest)
pnpm --filter frontend test:e2e     # E2E tests (Playwright)

Feature Testing Checklist (ก่อน PR)

Backend

  • Unit test: Service business logic (min 80% coverage)
  • Integration test: Controller + Guard + DTO validation
  • E2E test: Happy path + 2 edge cases จาก 01-06-edge-cases.md
  • Security test: Unauthorized access, SQL injection, XSS

Frontend

  • Component test: Render + interaction (Vitest + Testing Library)
  • Form test: Validation success/failure cases
  • E2E test: Critical user journey (Playwright)
  • Accessibility: Keyboard nav + screen reader basics

Before Commit

  • pnpm lint → 0 errors
  • pnpm test:cov → ผ่านเกณฑ์
  • pnpm build → 0 warnings
  • UUID pattern ตรวจสอบแล้ว (ไม่มี parseInt บน UUID)

🌿 Git Conventions

Commit Message Format

<type>(<scope>): <description>
[optional body]
[optional footer: Refs #issue]
Typeใช้เมื่อ
featเพิ่มฟีเจอร์ใหม่
fixแก้ bug
refactorปรับโครงสร้างโค้ด ไม่เปลี่ยน behavior
docsแก้ไขเอกสาร
testเพิ่ม/แก้ test
choreงาน infra, config, dependency updates
styleFormatting, linting (ไม่เปลี่ยน logic)
specแก้ไข specs/ documents
adrเพิ่ม/แก้ไข Architecture Decision Record

ตัวอย่าง:

feat(correspondence): add create correspondence endpoint
fix(uuid): remove parseInt on projectId in rfas/page.tsx
spec(requirements): update edge cases for drawing workflow
adr(019): add UUID serialization behavior notes

Branch Naming

feature/<description>              # ฟีเจอร์ใหม่
fix/<issue-number>-<description>   # แก้ bug
spec/<category>/<description>      # แก้ specs
adr/<number>-<description>         # ADR ใหม่/แก้ไข
refactor/<description>             # Refactor

ตัวอย่าง:

feature/correspondence-cc-support
fix/23-uuid-parseInt-rfas-page
spec/requirements/update-correspondence-workflow
adr/019-uuid-serialization-behavior

🌊 Windsurf Workflows

.windsurf/workflows/ — ใช้สำหรับ repeatable / complex tasks เช่น:

  • UUID migration fixes (Phase 5.4)
  • Spec review & gap analysis
  • Security audit checklist
  • Release gate verification เมื่อ task ซับซ้อนและทำซ้ำได้ ให้ดู .windsurf/workflows/ ก่อนเขียน code ใหม่ ---## 🚀 Deployment Rules (ADR-015)
  • Docker Compose on QNAP Container Station (production).
  • NO .env files in production — secrets in docker-compose.yml environment section directly.
  • Blue-Green deployment strategy.
  • CI/CD via Gitea (QNAP) + Gitea Runner / act_runner (ASUSTOR).
  • DO NOT deploy without completing all Release Gates per 04-08-release-management-policy.md.

🚫 Forbidden Actions

❌ Forbidden✅ Correct Approach
SQL Triggers for business logicNestJS Service methods
.env files in productiondocker-compose.yml environment section
TypeORM migration filesEdit schema SQL directly (ADR-009)
Inventing table/column namesVerify against schema-02-tables.sql
any TypeScript typeProper types / generics / unknown + narrowing
console.log in committed codeNestJS Logger (backend) / remove (frontend)
req: any in controllersRequestWithUser typed interface
parseInt() on UUID valuesUse UUID string directly (ADR-019)
Exposing INT PK in API responses or URLsUUIDv7 (ADR-019)
AI accessing DB or storage directlyAI → DMS API → DB (ADR-018)
Direct file operations bypassing StorageServiceStorageService for all file moves
Inline email/notification sendingBullMQ queue job
Generic domain terms (Letter, Blueprint, etc.)Correct term from Glossary (00-02-glossary.md)
Deploying without Release GatesComplete 04-08-release-management-policy.md gates
Starting migration without Go/No-Go Gate #1Gate approval first (03-06-migration-business-scope.md)
Closing UAT without all Acceptance Criteria ✅Full sign-off per 01-05-acceptance-criteria.md
Modifying Migration Bot token scopeIP Whitelist + 7-day expiry only
OWASP Top 10 violationsSecurity checklist before every PR

🔄 Workflow Before Writing Code (7 Steps)

  1. Glossary check — ตรวจคำศัพท์ domain ใน 00-02-glossary.md
  2. Read the spec — pick from Key Spec Files table.
  3. Check schema — verify table/column in schema-02-tables.sql.
  4. Check data dictionary — confirm field meanings and business rules.
  5. Scan edge cases — 01-06-edge-cases-and-rules.md (37 rules).
  6. Check ADRs — confirm approach aligns with decisions (esp. ADR-009, ADR-018, ADR-019).
  7. Write code — TypeScript strict, no any, no console.log, correct naming, UUID not exposed.

🎯 Windsurf Context-Aware Triggers

เมื่อผู้ใช้ถามเกี่ยวกับ... ให้ตรวจสอบไฟล์เหล่านี้ก่อนตอบ

คำถาม/คำสั่งไฟล์ที่ต้องตรวจสอบก่อนคำตอบที่คาดหวัง
"สร้าง API ใหม่"05-02-backend-guidelines.md, schema-02-tables.sqlNestJS Controller + Service + DTO + CASL Guard
"แก้ฟอร์ม frontend"05-03-frontend-guidelines.md, 01-06-edge-cases.mdRHF+Zod + TanStack Query + Thai comments
"เพิ่ม field ใหม่"ADR-009, data-dictionary.md, schema-02-tables.sqlแก้ SQL โดยตรง + อัพเดท Data Dictionary + Entity
"ตรวจสอบ UUID"ADR-019, 05-07-hybrid-uuid-implementation-plan.mdUUIDv7 BINARY(16) + TransformInterceptor behavior
"สร้าง migration"ADR-009, 03-06-migration-business-scope.mdแก้ SQL schema โดยตรง + n8n workflow
"ตรวจสอบ permission"seed-permissions.sql, ADR-016CASL 4-Level RBAC matrix
"deploy production"04-08-release-management-policy.md, ADR-015Release Gates + Blue-Green strategy
"เพิ่ม test"05-04-testing-strategy.mdCoverage goals + test patterns

🧩 Code Snippets (Windsurf Auto-Suggest)

Backend DTO Pattern

// [dto-new] → สร้าง DTO ใหม่พร้อม validator
@IsUUID()
@ApiProperty({ description: 'Project UUID (public)' })
projectUuid!: string;


@IsOptional()
@IsInt()
@ApiProperty({ required: false, description: 'Internal project ID' })
projectId?: number; // resolved internally, never from client

Frontend Form Pattern

// [form-rhf-zod] → สร้าง form schema + hook
const schema = z.object({
  projectUuid: z.string().uuid('รหัสโครงการไม่ถูกต้อง'),
  title: z.string().min(3, 'กรุณากรอกหัวข้ออย่างน้อย 3 ตัวอักษร'),
});
const form = useForm({ resolver: zodResolver(schema) });

UUID Safe Pattern

// [uuid-safe] → ตรวจสอบ UUID ก่อนใช้
const safeUuid = (val: string | number): string => {
  if (typeof val === 'number') {
    Logger.warn(`UUID received as number: ${val}`);
    return String(val); // หรือ throw error ตาม policy
  }
  return val;
};

Backend Error Handling Pattern

// [backend-error] → Error handling มาตรฐาน
if (!entity) {
  this.logger.warn(`Entity not found: ${uuid}`, 'Service.findOne');
  throw new NotFoundException(`Resource with UUID ${uuid} not found`);
}

Frontend Query Pattern

// [frontend-query] → TanStack Query มาตรฐาน
const { data, error, isLoading } = useQuery({
  queryKey: ['correspondence', uuid],
  queryFn: () => api.get(`/correspondences/${uuid}`),
  onError: (err) => {
    toast.error('ไม่สามารถโหลดข้อมูลได้');
    logger.error('Failed to load correspondence', { uuid, err });
  },
});

Redis Cache Pattern

// [redis-cache] → Cache-Aside Pattern
const cacheKey = `correspondence:${uuid}`;
const cached = await this.cacheManager.get(cacheKey);
if (cached) return cached;
const entity = await this.repo.findOneBy({ uuid });
if (entity) {
  await this.cacheManager.set(cacheKey, entity, 300); // 5 นาที
}
return entity;

🚨 Error Handling & Logging Standards

Backend (NestJS)

// ✅ ถูกต้อง — ใช้ Logger + HttpException
if (!entity) {
  this.logger.warn(`Entity not found: ${uuid}`, 'Service.findOne');
  throw new NotFoundException(`Resource with UUID ${uuid} not found`);
}
// ❌ ผิด — console.log หรือ return null
console.log('not found'); // ❌
return null; // ❌ ทำให้ caller ต้องเช็คเอง

Frontend (Next.js)

// ✅ ถูกต้อง — ใช้ TanStack Query error handling
const { data, error, isLoading } = useQuery({
  queryKey: ['correspondence', uuid],
  queryFn: () => api.get(`/correspondences/${uuid}`),
  onError: (err) => {
    // แสดง toast + log + fallback UI
    toast.error('ไม่สามารถโหลดข้อมูลได้');
    logger.error('Failed to load correspondence', { uuid, err });
  },
});

Error Response Standard (Backend)

{
  "statusCode": 404,
  "message": "Resource not found",
  "error": "Not Found",
  "timestamp": "2026-03-21T10:30:00.000Z",
  "path": "/api/correspondences/:uuid",
  "traceId": "req-abc123" // สำหรับติดตามใน Loki
}

🌐 Thai Language & i18n Guidelines

Code Comments & Docs

  • ✅ Comments: เขียนเป็นภาษาไทย (เพื่อความเข้าใจทีม)
  • ✅ JSDoc: ใช้ภาษาไทยอธิบาย business logic
  • ✅ Error messages: เก็บเป็น key ใน i18n file, ไม่ hardcode

i18n Structure (frontend)

locales/
├── th/
│   ├── common.json      # ข้อความทั่วไป
│   ├── errors.json      # Error messages
│   ├── forms.json       # Form labels & validation
│   └── modules/
│       ├── correspondence.json
│       └── rfa.json
└── en/                  # Reserved for future

Validation Messages (Zod)

// ✅ ถูกต้อง — ใช้ key อ้างอิง
z.string().min(3, { message: 'errors:min_length_3' });
// แล้ว resolve ใน frontend ผ่าน i18n hook

// ❌ ผิด — hardcode ภาษาไทยใน schema
z.string().min(3, 'กรุณากรอกอย่างน้อย 3 ตัวอักษร'); // ทำให้ทดสอบยาก

⚡ Performance & Caching Patterns

Redis Cache Patterns (ADR-006)

// ✅ Cache-Aside Pattern สำหรับข้อมูลอ่านบ่อย
async findOne(uuid: string) {
  const cacheKey = `correspondence:${uuid}`;
  const cached = await this.cacheManager.get(cacheKey);
  if (cached) return cached;

  const entity = await this.repo.findOneBy({ uuid });
  if (entity) {
    await this.cacheManager.set(cacheKey, entity, 300); // 5 นาที
  }
  return entity;
}


// ✅ Cache Invalidation เมื่อแก้ไขข้อมูล
async update(uuid: string, dto: UpdateDto) {
  // ... update logic
  await this.cacheManager.del(`correspondence:${uuid}`);
  await this.cacheManager.del('correspondences:list'); // ลบ list cache
}

Query Optimization Checklist

  • ใช้ select: [...] เพื่อโหลดเฉพาะฟิลด์ที่ต้องการ
  • ใช้ relations: [...] แทน JOIN ซับซ้อนเมื่อไม่จำเป็น
  • ตรวจสอบ N+1 problem ด้วย @UseInterceptors(LoggingInterceptor)
  • ใช้ take/skip สำหรับ pagination เสมอ

💬 Prompt Templates สำหรับถาม Windsurf

เมื่อต้องการสร้างฟีเจอร์ใหม่

[NEW FEATURE]
Module: <module-name>
Requirement: <อ้างอิง user story จาก 01-02-business-rules/>
Steps:
1. ตรวจสอบ glossary และ edge cases
2. ออกแบบ DTO + Schema ตาม ADR-019
3. สร้าง Service + Controller พร้อม CASL guard
4. เขียน unit test สำหรับ business logic
5. อัพเดท API docs (Swagger)
Output: Code + Test + Spec reference

เมื่อต้องการ debug

[DEBUG]
Issue: <อธิบายปัญหา>
File: <path/to/file>
Error: <error message/log>
Steps taken: <สิ่งที่ลองแก้ไขแล้ว>
Request: วิเคราะห์ตาม spec + แนะนำวิธีแก้ที่สอดคล้องกับ ADRs

เมื่อต้องการ review code

[CODE REVIEW]
File: <path/to/file>
Focus: <security/performance/uuid/i18n>
Request: ตรวจสอบตาม spec + ADRs + Forbidden Actions table

📦 Infrastructure Quick Reference

QNAP NAS (Container Station) — Production

ServiceNotes
DMS FrontendNext.js 16.2.0 + React 19.2.4
DMS BackendNestJS 11 + Express v5
MariaDB 11.8Schema v1.8.0
Redis 7.2BullMQ + Cache
Elasticsearch 9.3.4Full-text search
n8n + n8n-dbAutomation & Migration
Nginx Proxy ManagerReverse proxy + SSL termination
TikaDocument parsing
GiteaSource code management
RocketChatTeam communication
cAdvisor + exportersContainer metrics

ASUSTOR NAS (Portainer) — Monitoring Hub

ServiceNotes
GrafanaDashboards + KPI visualization
PrometheusMetrics (scrapes QNAP)
Loki + PromtailLog aggregation
Uptime-KumaService availability monitoring
Gitea RunnerCI/CD (act_runner)
Docker RegistryPrivate image registry
CloudflaredExternal tunnel
cAdvisorContainer metrics

Admin Desktop — AI Processing ONLY

SpecValue
CPUIntel i9-9900K
RAM32GB
GPURTX 2060 SUPER 8GB
ServiceOllama (llama3.2:3b / mistral:7b)
RuleNEVER on QNAP — Admin Desktop ONLY (ADR-018)

Network: Internal VLAN — QNAP metrics scraped by ASUSTOR Prometheus

📜 .windsurfrules Change Log

VersionDateChangesUpdated By
1.8.22026-03-21+ Context Triggers, + Code Snippets, + Error Handling, + i18n, + Performance, + Testing Checklist, + Prompt TemplatesHuman Dev + AI
1.8.12026-03-21+ ADR-019 UUID patterns, + Phase 5.4 pending filesClaude Sonnet
1.8.02026-03-19+ Security overrides, + UAT criteria referenceHuman Dev
1.7.22026-03-15+ AI Boundary rules (ADR-018)Gemini Pro

วิธีอัพเดทไฟล์นี้

  1. แก้ไขในส่วนที่เกี่ยวข้อง
  2. อัพเดทตาราง Change Log ด้านบน
  3. เพิ่ม version number ใน header
  4. Commit ด้วย message: spec(windsurfrules): bump to v1.8.2 - <brief description>

✅ Quick Reference Checklist (ก่อน Commit ทุกครั้ง)

  • UUID pattern ตรวจสอบแล้ว (ไม่มี parseInt บน UUID)
  • No any types ใน TypeScript
  • No console.log ในโค้ดที่ commit
  • Comments เป็นภาษาไทย
  • Code identifiers เป็นภาษาอังกฤษ
  • Schema เปลี่ยนแก้ SQL โดยตรง (ไม่ใช่ migration)
  • Test coverage ผ่านเกณฑ์ (Backend 70%+, Business Logic 80%+)
  • ADR ที่เกี่ยวข้องตรวจสอบแล้ว (esp. ADR-009, ADR-018, ADR-019)
  • Glossary terms ใช้ถูกต้อง
  • Error handling ครบถ้วน (Logger + HttpException)
  • i18n keys ใช้แทน hardcode text
  • Cache invalidation มีเมื่อแก้ไขข้อมูล
  • Security checklist ผ่าน (OWASP Top 10)

What's inside

17 sections covering persona, project overview, tech stack, spec files, ADR reference, identifier strategy, security, TypeScript rules, naming, domain terms, architecture, database, AI, testing, git, deployment, and forbidden actions

Change this for your project

  • Replace peancharoen/lcbp3 with your own repository name
  • Replace np-dms.work with your own domain
  • Replace llama3.2:3b and mistral:7b with your own AI model identifiers
  • Replace n8n-workflow-lcbp3.json with your own migration workflow filename

Where it goes

A standard operating procedure. Keep where the team or agent running the process will find it.

Worth borrowing

  • 7-step pre-coding checklist that forces glossary, spec, schema, and ADR review before writing any code
  • Context-aware trigger table mapping user questions to specific spec files to check before answering
  • Forbidden actions table with concrete correct alternatives for each anti-pattern

Related Documents