Files
lcbp3/AGENTS.md
T
admin e3c476f011
CI / CD Pipeline / build (push) Successful in 15m14s
CI / CD Pipeline / release (push) Failing after 20s
CI / CD Pipeline / deploy (push) Has been skipped
260323:1050 fix CI : Verify Build frontend #02 correct _???
2026-03-23 10:50:20 +07:00

889 lines
39 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NAP-DMS Project Context & Rules
- For: Windsurf Cascade (and compatible: Codex CLI, opencode, Amp, Amazon Q, AGENTS.md tools)
- Version: 1.8.3 (Enforcement Tiers Added) | Last synced from repo: 2026-03-21
- Repo: [https://git.np-dms.work/np-dms/lcbp3](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**.
---
## 🧭 Rule Enforcement Tiers
ทุก rule ในไฟล์นี้จัดระดับตามนี้ — ใช้ตัดสินใจว่าอะไรต้อง block ทันที อะไรรอ review ได้:
### 🔴 Tier 1 — CRITICAL (CI BLOCKER)
บังคับอัตโนมัติ ผ่าน CI/CD + runtime — **ผิดแล้ว build fail ทันที:**
- Security (Auth, RBAC, Validation)
- UUID Strategy (ADR-019) — ห้าม `parseInt` / `Number` / `+` บน UUID
- Database correctness — ตรวจ schema ก่อนเขียน query เสมอ
- File upload security (ClamAV + whitelist)
- AI validation boundary (ADR-018)
- Forbidden patterns: `any`, `console.log`, UUID misuse
### 🟡 Tier 2 — IMPORTANT (CODE REVIEW)
ตรวจใน PR review — ไม่ block build แต่ต้องแก้ก่อน merge:
- Architecture patterns (thin controller, business logic ใน service)
- Test coverage (80%+ business logic, 70%+ backend overall)
- Cache invalidation
- Naming conventions
### 🟢 Tier 3 — GUIDELINES
Best practice — ทำตามถ้าทำได้ ไม่ block:
- Code style / formatting (Prettier จัดให้)
- Comment completeness
- Minor optimizations
---
## 🏗️ Project Overview
**LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System)**
ระบบบริหารจัดการเอกสารโครงการก่อสร้างท่าเรือแหลมฉบังระยะที่ 3
**Version:** 1.8.3 (Enforcement Tiers Added) | **Status:** UAT In Progress, Security Hardened (2026-03-19)
| Area | Status | Notes |
| ------------- | ---------------------- | ------------------------------------------------------ |
| Backend | ✅ Production Ready | NestJS 11, Express v5, 0 Vulnerabilities |
| Frontend | ✅ Quality Hardened | Next.js 16.2.0, React 19.2.4, 0 `any`, 0 `console.log` |
| Database | ✅ Schema v1.8.0 Stable | MariaDB 11.8, No-migration (ADR-009) |
| Documentation | ✅ 10/10 Gaps Closed | Product Vision → Release Policy |
| AI Migration | 🔄 Pre-migration Setup | n8n + Ollama (ADR-017/018) |
| Testing | 🔄 UAT In Progress | Per `01-05-acceptance-criteria.md` |
| Deployment | 📋 Pending Go-Live Gate | Blue-Green, QNAP Container Station |
| ADR-019 UUID | 🔄 Phase 5.4 Pending | 4 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@11.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/`) | ใช้เมื่อ |
| ------------------------- | -------------------------------------------------------------------- | ----------------------------------- |
| **Glossary** | `00-Overview/00-02-glossary.md` | ตรวจคำศัพท์ Domain ก่อนเขียนเสมอ |
| **Schema Tables** | `03-Data-and-Storage/lcbp3-v1.8.0-schema-02-tables.sql` | ก่อนเขียน Query ทุกครั้ง |
| **Data Dictionary** | `03-Data-and-Storage/03-01-data-dictionary.md` | ตรวจ Field Meaning + Business Rules |
| **Seed Permissions** | `03-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 Scope** | `03-Data-and-Storage/03-06-migration-business-scope.md` | งาน Migration Bot (20K docs) |
| **Release Policy** | `04-Infrastructure-OPS/04-08-release-management-policy.md` | ก่อน Deploy / Hotfix |
| **UAT Criteria** | `01-Requirements/01-05-acceptance-criteria.md` | ตรวจความสมบูรณ์ Feature |
| **UUID Implementation** | `05-Engineering-Guidelines/05-07-hybrid-uuid-implementation-plan.md` | ADR-019 UUID Migration (Phase 16) |
| **Backend Guidelines** | `05-Engineering-Guidelines/05-02-backend-guidelines.md` | NestJS patterns & best practices |
| **Frontend Guidelines** | `05-Engineering-Guidelines/05-03-frontend-guidelines.md` | Next.js patterns & best practices |
| **Testing Strategy** | `05-Engineering-Guidelines/05-04-testing-strategy.md` | Coverage goals & test patterns |
| **ADR-009 DB Strategy** | `06-Decision-Records/ADR-009-db-strategy.md` | Schema Change Process |
| **ADR-018 AI Boundary** | `06-Decision-Records/ADR-018-ai-boundary.md` | AI/Ollama Integration Rules |
| **ADR-019 Hybrid ID** | `06-Decision-Records/ADR-019-hybrid-identifier-strategy.md` | Hybrid 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)
| ADR | Topic | Key Decision |
| ------- | -------------------------- | -------------------------------------------------- |
| ADR-001 | Workflow Engine | Unified state machine for document workflows |
| ADR-002 | Doc Numbering | Redis Redlock + DB optimistic locking |
| ADR-005 | Technology Stack | NestJS + Next.js + MariaDB + Redis |
| ADR-006 | Redis Caching | Cache strategy and invalidation patterns |
| ADR-008 | Email Notification | BullMQ queue-based email/LINE/in-app |
| ADR-009 | DB Strategy | No TypeORM migrations — modify schema SQL directly |
| ADR-010 | Logging/Monitoring | Prometheus + Loki + Grafana stack |
| ADR-011 | App Router | Next.js App Router with RSC patterns |
| ADR-012 | UI Components | Shadcn/UI component library |
| ADR-013 | Form Handling | React Hook Form + Zod validation |
| ADR-014 | State Management | TanStack Query (server) + Zustand (client) |
| ADR-015 | Deployment | Docker Compose + Gitea CI/CD |
| ADR-016 | Security | JWT + CASL RBAC + Helmet.js + ClamAV |
| ADR-017 | Ollama Migration | Local AI + n8n for legacy data import (~20K docs) |
| ADR-018 | AI Boundary (Patch 1.8.1) | AI isolation — no direct DB/storage access |
| ADR-019 | Hybrid Identifier Strategy | INT 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 Type | Behavior |
| ------------------ | ---------------------------------------------------------------------- |
| All entities | INT `id` has `@Exclude()`**never appears in API response** |
| Project / Contract | `uuid` has `@Expose({ name: 'id' })` → response has `id` = UUID string |
| Other entities | Separate `uuid` field → response has `uuid`, no `id` |
### UUID Patterns (Backend Controller)
```typescript
// ✅ ถูกต้อง — 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)
```typescript
// ✅ ถูกต้อง — รับ 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)
```typescript
// ✅ ถูกต้อง
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
| Target | Convention | Example |
| ------------------- | ----------- | --------------------------- |
| Files | kebab-case | `user-service.ts` |
| Classes | PascalCase | `UserService` |
| Variables | camelCase | `firstName` |
| DB Properties | snake_case | `user_id`, `created_at` |
| Boolean vars | verb + noun | `isActive`, `hasPermission` |
| **Code** | English | All identifiers in English |
| **Comments / Docs** | Thai | ความคิดเห็นและเอกสารใช้ภาษาไทย |
---
## 🏷️ Domain Terminology (Glossary)
อ้างอิง `specs/00-Overview/00-02-glossary.md` เสมอ — ใช้ term ผิดจะทำให้ spec ไม่ตรง
| ✅ ใช้ (Correct) | ❌ ห้ามใช้ (Wrong) |
| ------------------ | ------------------------------------------- |
| Correspondence | Letter, Communication, Document (generic) |
| RFA | Approval Request, Submit for Approval |
| Transmittal | Delivery Note, Cover Letter |
| Circulation | Distribution, Routing |
| Shop Drawing | Construction Drawing (generic) |
| Contract Drawing | Design Drawing, Blueprint |
| Workflow Engine | Approval Flow, Process Engine |
| Document Numbering | Document ID, Auto Number |
| RBAC | Permission 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
| Layer | Target | Priority Areas |
| ---------------- | ------ | --------------------------------------------- |
| Backend overall | 70%+ | — |
| Business Logic | 80%+ | Services, Workflow Engine, Document Numbering |
| Controllers | 70%+ | Happy path + error cases |
| Utilities | 90%+ | Helpers, Transformers, Guards |
| Frontend overall | 60%+ | Components, Hooks, API clients |
### Health Check Endpoints
```
GET /health — Overall system health
GET /health/db — MariaDB connectivity
GET /health/redis — Redis connectivity
```
### Test Commands
```bash
# 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 |
| `style` | Formatting, 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 logic | NestJS Service methods |
| `.env` files in production | `docker-compose.yml` environment section |
| TypeORM migration files | Edit schema SQL directly (ADR-009) |
| Inventing table/column names | Verify against `schema-02-tables.sql` |
| `any` TypeScript type | Proper types / generics / `unknown` + narrowing |
| `console.log` in committed code | NestJS Logger (backend) / remove (frontend) |
| `req: any` in controllers | `RequestWithUser` typed interface |
| `parseInt()` on UUID values | Use UUID string directly (ADR-019) |
| Exposing INT PK in API responses or URLs | UUIDv7 (ADR-019) |
| AI accessing DB or storage directly | AI → DMS API → DB (ADR-018) |
| Direct file operations bypassing StorageService | `StorageService` for all file moves |
| Inline email/notification sending | BullMQ queue job |
| Generic domain terms (Letter, Blueprint, etc.) | Correct term from Glossary (`00-02-glossary.md`) |
| Deploying without Release Gates | Complete `04-08-release-management-policy.md` gates |
| Starting migration without Go/No-Go Gate #1 | Gate 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 scope | IP Whitelist + 7-day expiry only |
| OWASP Top 10 violations | Security checklist before every PR |
---
## 🔄 Development Flow (Tiered)
เลือก flow ตามประเภทงาน — ไม่ต้องอ่าน spec ทั้งหมดทุกครั้ง:
### 🔴 Critical Work — DB / API / Security / Workflow Engine
**MUST ทำครบทุก step:**
1. **Glossary check** — ตรวจคำศัพท์ domain ใน `00-02-glossary.md`
2. **Read the spec** — เลือกจาก Key Spec Files table
3. **Check schema** — verify table/column ใน `schema-02-tables.sql`
4. **Check data dictionary** — ยืนยัน field meanings + business rules
5. **Scan edge cases**`01-06-edge-cases-and-rules.md` (37 rules)
6. **Check ADRs** — ตรวจแนวทางตรงกับ decisions (esp. ADR-009, ADR-018, ADR-019)
7. **Write code** — TypeScript strict, no `any`, no `console.log`, UUID ไม่ expose
### 🟡 Normal Work — UI / Feature / Integration
- ดู existing patterns ในโค้ดที่มีอยู่
- ตรวจ spec เฉพาะ module ที่เกี่ยวข้อง
- ไม่ต้องอ่าน spec ทั้งหมด
### 🟢 Quick Fix — Bug Fix / Typo / Style
- แก้โดยตรง
- เพิ่ม minimal test ถ้าแก้ logic
- ตรวจ forbidden patterns ก่อน commit
---
## 🎯 Windsurf Context-Aware Triggers
เมื่อผู้ใช้ถามเกี่ยวกับ... ให้ตรวจสอบไฟล์เหล่านี้ก่อนตอบ
| คำถาม/คำสั่ง | ไฟล์ที่ต้องตรวจสอบก่อน | คำตอบที่คาดหวัง |
| -------------------- | ------------------------------------------------------- | ------------------------------------------------- |
| "สร้าง API ใหม่" | `05-02-backend-guidelines.md`, `schema-02-tables.sql` | NestJS Controller + Service + DTO + CASL Guard |
| "แก้ฟอร์ม frontend" | `05-03-frontend-guidelines.md`, `01-06-edge-cases.md` | RHF+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.md` | UUIDv7 BINARY(16) + TransformInterceptor behavior |
| "สร้าง migration" | `ADR-009`, `03-06-migration-business-scope.md` | แก้ SQL schema โดยตรง + n8n workflow |
| "ตรวจสอบ permission" | `seed-permissions.sql`, `ADR-016` | CASL 4-Level RBAC matrix |
| "deploy production" | `04-08-release-management-policy.md`, `ADR-015` | Release Gates + Blue-Green strategy |
| "เพิ่ม test" | `05-04-testing-strategy.md` | Coverage goals + test patterns |
---
## 🧩 Code Snippets (Windsurf Auto-Suggest)
### Backend DTO Pattern
```typescript
// [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
```typescript
// [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
```typescript
// [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
```typescript
// [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
```typescript
// [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
```typescript
// [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)
```typescript
// ✅ ถูกต้อง — ใช้ 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)
```typescript
// ✅ ถูกต้อง — ใช้ 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)
```json
{
"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)
```typescript
// ✅ ถูกต้อง — ใช้ 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)
```typescript
// ✅ 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
| Service | Notes |
| -------------------- | ------------------------------- |
| DMS Frontend | Next.js 16.2.0 + React 19.2.4 |
| DMS Backend | NestJS 11 + Express v5 |
| MariaDB 11.8 | Schema v1.8.0 |
| Redis 7.2 | BullMQ + Cache |
| Elasticsearch 9.3.4 | Full-text search |
| n8n + n8n-db | Automation & Migration |
| Nginx Proxy Manager | Reverse proxy + SSL termination |
| Tika | Document parsing |
| Gitea | Source code management |
| RocketChat | Team communication |
| cAdvisor + exporters | Container metrics |
### ASUSTOR NAS (Portainer) — Monitoring Hub
| Service | Notes |
| --------------- | ------------------------------- |
| Grafana | Dashboards + KPI visualization |
| Prometheus | Metrics (scrapes QNAP) |
| Loki + Promtail | Log aggregation |
| Uptime-Kuma | Service availability monitoring |
| Gitea Runner | CI/CD (act_runner) |
| Docker Registry | Private image registry |
| Cloudflared | External tunnel |
| cAdvisor | Container metrics |
### Admin Desktop — AI Processing ONLY
| Spec | Value |
| ------- | ------------------------------------------------ |
| CPU | Intel i9-9900K |
| RAM | 32GB |
| GPU | RTX 2060 SUPER 8GB |
| Service | Ollama (`llama3.2:3b` / `mistral:7b`) |
| Rule | **NEVER on QNAP** — Admin Desktop ONLY (ADR-018) |
## **Network:** Internal VLAN — QNAP metrics scraped by ASUSTOR Prometheus
## 📜 .windsurfrules Change Log
| Version | Date | Changes | Updated By |
| ------- | ---------- | --------------------------------------------------------------------------------------------------------------------- | -------------- |
| 1.8.3 | 2026-03-21 | + Rule Enforcement Tiers (🔴🟡🟢), + Tiered Development Flow | Human Dev + AI |
| 1.8.2 | 2026-03-21 | + Context Triggers, + Code Snippets, + Error Handling, + i18n, + Performance, + Testing Checklist, + Prompt Templates | Human Dev + AI |
| 1.8.1 | 2026-03-21 | + ADR-019 UUID patterns, + Phase 5.4 pending files | Claude Sonnet |
| 1.8.0 | 2026-03-19 | + Security overrides, + UAT criteria reference | Human Dev |
| 1.7.2 | 2026-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.3 - <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)