---
title: "เอกสารประกอบระบบและการถ่ายทอดเทคโนโลยี"
titleEn: "System Documentation and Technology Transfer"
clauses: ["4.10.3", "4.11.1"]
phase: 3
category: "ส่งมอบ"
generated: false
---

# เอกสารประกอบระบบและการถ่ายทอดเทคโนโลยี (System Documentation)

**อ้างอิง TOR:** ข้อ 4.10.3 (เอกสารประกอบระบบ/ถ่ายทอดเทคโนโลยี) และข้อ 4.11.1 (ส่งมอบ Source Code, Configuration, Prompt, Benchmark)
**ฉบับ:** 1.0 — วันที่ 3 ตุลาคม พ.ศ. 2569 · เวอร์ชันระบบ `1.0.0-demo` (`package.json`)
**ผู้อ่าน:** ทีมพัฒนา/ดูแลระบบของมหาวิทยาลัยที่รับช่วงต่อ

> เอกสารนี้อธิบายโครงสร้างซอร์สโค้ดและการปฏิบัติงานของระบบตามที่มีจริงใน repository ข้อกำหนดเชิงหน้าที่อยู่ที่ `/documents/srs` การติดตั้งอยู่ที่ `/documents/deployment-guide` เอกสารนี้ **ไม่ระบุค่าความลับใด ๆ** (ระบุเฉพาะชื่อตัวแปร)

---

## 1. ภาพรวมเทคนิค

| หัวข้อ | รายละเอียด |
|---|---|
| ภาษา/รันไทม์ | TypeScript (strict) บน Node.js ≥22 |
| เฟรมเวิร์ก | Next.js 15.5 App Router (หน้าเว็บ SSR + Route Handlers เป็น backend), React 19.1 |
| ฐานข้อมูล | Prisma 6.19 + SQLite (ระบบสาธิต) — schema ที่ `prisma/schema.prisma` 25 models |
| AI | LangGraph.js (`@langchain/langgraph`) StateGraph 8 โหนด; LLM ค่าเริ่มต้น Typhoon `typhoon-v2.5-30b-a3b-instruct` ผ่าน OpenAI-compatible API |
| ค้นคืน | BM25 + pseudo-embedding 512 มิติ + RRF ในหน่วยความจำ + Heuristic reranker |
| UI | Tailwind CSS 4, next-intl (th/en), next-themes, recharts, react-markdown |
| ทดสอบ | vitest (unit/API/coverage), Playwright (E2E) |
| ส่งมอบ IaC | `.github/workflows/ci-cd.yml`, `infra/helm/mbu-buddhist-ai/` |

## 2. โครงสร้าง Repository

```
mbu-buddhist-ai/
├── .github/workflows/ci-cd.yml        # CI/CD (lint → test → security → build → e2e → deploy-dev/test/prod)
├── infra/helm/mbu-buddhist-ai/        # Helm chart 8 microservices + HPA + Ingress + values dev/test/prod
├── config/prompts/                    # prompt ต้นฉบับ (qa-persona v1/v2, dhamma-talk, guard-classifier, judge, query-rewrite)
├── docs/
│   ├── build-plan.md                  # แผนพัฒนาระบบสาธิต
│   ├── dev-conventions.md             # ข้อตกลงการพัฒนา
│   └── deliverables/*.md              # เอกสารส่งมอบ (แสดงที่ /documents)
├── messages/{th,en}/*.json            # ข้อความ UI สองภาษา (แยก namespace)
├── prisma/
│   ├── schema.prisma                  # data model
│   ├── migrations/                    # init + audit_immutable (trigger ห้ามแก้/ลบ AuditLog)
│   └── seed.ts                        # ข้อมูลตั้งต้น
├── public/{assets,icons}/             # ตราสัญลักษณ์ มมร. และ favicon
├── scripts/
│   ├── backup-db.sh restore-db.sh restore-test.sh _db-common.sh generate-dev-cert.sh
│   ├── data/                          # fetch_corpus.py, import-knowledge.ts, import-benchmarks.ts, benchmarks/ (สร้างชุดทดสอบ)
│   ├── eval/run-acceptance.ts         # รันการประเมิน 7 ชุดกับ LLM จริง
│   ├── perf/                          # load-test.ts, seed-perf-users.ts
│   ├── prompts/publish.ts             # เผยแพร่ prompt จากไฟล์
│   ├── reports/                       # coverage-report, ingestion-report, evaluation-export, sla-export
│   ├── security/                      # npm-audit-report.ts
│   ├── purge-conversations.ts         # ลบบทสนทนาที่หมดอายุ
│   └── gen-tor-map.py                 # สร้าง src/data/tor-map.ts จากตาราง TOR
├── seed/
│   ├── knowledge/                     # คลังความรู้ 169 ไฟล์ + _manifest.json
│   ├── benchmarks/                    # ชุดทดสอบ CSV 8 ไฟล์ + SOURCES.md
│   ├── guardrail-topics.json  pricing.json  users.json
├── server.https.js                    # HTTPS self-signed (:3443)
├── src/
│   ├── middleware.ts                  # requestId, rate limit, CSRF, admin IP allowlist, locale
│   ├── instrumentation.ts / instrumentation-node.ts   # เริ่มนับ uptime + scheduler ลบบทสนทนาหมดอายุ
│   ├── data/                          # tor-map.ts (200 ข้อ), routes.ts
│   ├── styles/tokens.ts               # design tokens + contrast
│   ├── domain/                        # กฎทางธุรกิจ pure TypeScript
│   ├── application/                   # use cases
│   ├── server/                        # adapters (db, llm, retrieval, ingestion, ai, auth, notification ...)
│   ├── components/                    # UI components (admin, chat, layout, auth, ...)
│   ├── i18n/                          # routing/navigation ของ next-intl
│   └── app/                           # หน้าเว็บ [locale]/... และ api/...
├── tests/{unit,api,e2e,helpers,fixtures}/
├── vitest.config.ts  playwright.config.ts  next.config.ts  tsconfig.json  eslint.config.mjs
└── .env.example  .env.development  .env.production
```

ไฟล์/โฟลเดอร์ที่สร้างขณะรันและไม่ควร commit: `.env`, `prisma/*.db`, `storage/`, `logs/`, `backups/`, `certs/`, `coverage/`, `test-results/`, `.next/`

## 3. สถาปัตยกรรมโค้ดและโมดูล

กติกาการพึ่งพา: `src/app` → `src/application` → `src/server` → `src/domain` (domain ไม่ import framework ใด ๆ)

### 3.1 `src/domain` (กฎทางธุรกิจ)

| โมดูล | ไฟล์ | หน้าที่ |
|---|---|---|
| ai | `guardrail-policy.ts`, `citation.ts`, `token-budget-policy.ts` | จำแนกคำถาม (scope/injection/sensitive/yes-no) และตรวจคำตอบ; รูปแบบ/ตรวจ citation; เพดานโทเคน ความยาว input และการตัดบริบท |
| retrieval | `tokenizer.ts`, `bm25.ts`, `embedding.ts`, `rrf.ts`, `synonyms.ts`, `heuristic-reranker.ts`, `relevance-scoring.ts`, `types.ts` | ตัดคำไทย (`Intl.Segmenter`), BM25, pseudo-embedding, RRF, พจนานุกรมไทย–บาลี–อังกฤษ, reranker, precedence |
| ingestion | `chunking-policy.ts`, `sanitize.ts` | แบ่ง chunk (ตามข้อ/semantic), กรองคำสั่งแฝง |
| identity | `rbac.ts`, `password-policy.ts`, `lockout-policy.ts` | บทบาท นโยบายรหัสผ่าน การล็อกบัญชี |
| privacy | `pii-masking.ts` | ปิดบังเลขบัตรประชาชน โทรศัพท์ อีเมล ชื่อ |
| audit | `hash-chain.ts` | คำนวณ/ตรวจ hash chain ของ Audit Log |
| evaluation | `scorers.ts` | exact match, Recall@K, mock judge, refusal, aggregate |
| report | `sla-policy.ts` | SLA ชั่วโมงทำการ overdue และค่าปรับ |
| config | `ai-config.ts` | คีย์ ค่าตั้งต้น schema และกลุ่มของ AI config |

### 3.2 `src/application` (use cases)

| โมดูล | ไฟล์หลัก |
|---|---|
| chat | `ask.ts` — `askStream()` (SSE), `loadOwnedConversation()` |
| evaluation | `runner.ts` (evaluateItem/createRun/executeRun), `datasets.ts`, `reports.ts`, `run-registry.ts` |
| ingestion | `kb-admin.ts` (upload/metadata/reindex), `coverage.ts` (ความครอบคลุม 91 เล่ม) |
| identity | `auth-usecases.ts`, `admin-user-usecases.ts` |
| privacy | `privacy-usecases.ts`, `purge.ts` (scheduler) |
| config | `ai-config-usecases.ts`, `prompt-usecases.ts`, `guardrail-usecases.ts`, `pricing-usecases.ts` |
| ops | `dashboard.ts`, `defects.ts`, `backup.ts`, `data-destruction.ts`, `range*.ts` |
| report | `sla.ts` |

### 3.3 `src/server` (adapters)

| โมดูล | หน้าที่ |
|---|---|
| `db.ts` | Prisma client (`import { prisma } from "@/server/db"`) |
| `api/with-api.ts` | ตัวห่อทุก route: auth/RBAC, zod, audit helper, `ApiRequestLog`, error mapping, ติดตามการเรียกเพื่อ openapi-coverage |
| `api/openapi/*` | registry เอกสาร API → `/api/openapi.json` |
| `ai/graph.ts` | LangGraph StateGraph 8 โหนด (`runRagGraph`) |
| `ai/{availability,context,prompts,texts,usage}.ts` | ตรวจงบ/สถานะ, สร้างบริบท DATA, โหลด prompt ที่ active, ข้อความปฏิเสธ, บันทึกโทเคน + แจ้งเตือน |
| `llm/*` | `LlmGateway` + adapter: `openai-compatible.ts` (Typhoon/OpenAI), `gemini.ts`, `claude.ts`, `mock.ts`; `index.ts` เลือก adapter |
| `retrieval/*` | `KnowledgeIndex` singleton, `reranker.ts` (heuristic/tei), `tei-reranker.ts`, `elasticsearch-adapter.ts` (โครงสำหรับ production) |
| `ingestion/*` | `pipeline.ts` (job runner), `parsers/index.ts` |
| `auth/*`, `identity/oauth/*`, `security/*` | session JWT, current user, OAuth (google/facebook/mock), CSRF, IP, rate limit |
| `repos/user-repo.ts`, `crypto.ts` | เข้า/ถอดรหัส PII (AES-256-GCM), `hashEmail` |
| `audit/audit-logger.ts` | `appendAudit()` + hash chain |
| `notification/index.ts` | `LogNotificationAdapter` / `SmtpNotificationAdapter`, `sendAlert`, `sendAlertOnce` |
| `config/ai-config-store.ts` | `getAiConfig()`, `updateAiConfig()` (สร้าง ConfigSnapshot) |
| `documents/index.ts` | อ่าน `docs/deliverables/*.md` + frontmatter |
| `logger.ts`, `uptime.ts`, `site-info.ts`, `storage/` | log, uptime, ข้อมูล footer, ที่เก็บไฟล์ |

## 4. ตัวแปรสภาพแวดล้อม (`.env.example`)

คัดลอก `.env.example` เป็น `.env` แล้วกำหนดค่า (**ห้าม commit `.env`**) ตารางนี้แสดงเฉพาะชื่อและหน้าที่

| ตัวแปร | หน้าที่ | ถ้าไม่ตั้ง |
|---|---|---|
| `DATABASE_URL` | ที่อยู่ฐานข้อมูล SQLite (`file:./dev.db` สัมพัทธ์กับ `prisma/`) | จำเป็น |
| `AUTH_SECRET` | คีย์เซ็น JWT session (≥32 ตัวอักษร) | ใช้ค่าตั้งต้นสำหรับพัฒนา — **ต้องตั้งเสมอใน Production** |
| `DATA_ENCRYPTION_KEY` | คีย์ AES-256-GCM เข้ารหัสอีเมล/ชื่อ (`base64:` + 32 ไบต์, สร้างด้วย `openssl rand -base64 32`) | จำเป็น |
| `LLM_PROVIDER` | provider เริ่มต้น (ค่าที่ใช้จริงอ่านจาก `/admin/ai-config`) | — |
| `TYPHOON_API_KEY`, `TYPHOON_BASE_URL` | Typhoon (OpenAI-compatible; base URL ค่าเริ่มต้น `https://api.opentyphoon.ai/v1`) | ใช้ Mock LLM |
| `OPENAI_API_KEY`, `OPENAI_BASE_URL` | OpenAI หรือบริการ OpenAI-compatible อื่น | ใช้ Mock เมื่อเลือก openai |
| `GEMINI_API_KEY` | Google Gemini | ใช้ Mock เมื่อเลือก gemini |
| `ANTHROPIC_API_KEY` | Anthropic Claude | ใช้ Mock เมื่อเลือก claude |
| `TEI_EMBED_URL`, `TEI_RERANK_URL` | Text Embeddings Inference (bge-m3 / bge-reranker) | pseudo-embedding / HeuristicReranker |
| `GOOGLE_OAUTH_CLIENT_ID`, `GOOGLE_OAUTH_CLIENT_SECRET` | Google Login จริง | Mock OAuth Provider |
| `FACEBOOK_OAUTH_CLIENT_ID`, `FACEBOOK_OAUTH_CLIENT_SECRET` | Facebook Login จริง | Mock OAuth Provider |
| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS` | ส่งอีเมลแจ้งเตือน | บันทึกใน `AlertEmailLog` |
| `ALERT_EMAIL_TO` | ผู้รับแจ้งเตือน | — |
| `ADMIN_IP_ALLOWLIST` | IP ที่เข้าส่วนผู้ดูแลได้ (คั่นด้วยจุลภาค) | เฉพาะ localhost |
| `NEXT_PUBLIC_APP_NAME` | ชื่อแอป | — |
| `NEXT_PUBLIC_GA_ID` | Google Analytics 4 (โหลดหลังยินยอมคุกกี้) | ไม่โหลด GA |
| `NEXT_PUBLIC_BASE_URL` | URL ฐานของระบบ (ใช้กำหนด cookie `Secure` และ OAuth redirect) | — |
| `LOG_FILE` | ไฟล์ log (ค่าเริ่มต้น `logs/app.log`) | — |
| `STORAGE_DIR` | โฟลเดอร์ไฟล์อัปโหลด (ค่าเริ่มต้น `storage/uploads`) | — |

ตัวแปรเสริมที่โค้ดอ่าน (ไม่อยู่ใน `.env.example`): `ENABLE_HSTS` (ตั้งใน `.env.production`), `LLM_FORCE_MOCK` (ชุดทดสอบ), `LLM_MAX_CONCURRENT` (ค่าเริ่มต้น 4), `RATE_LIMIT_LOGIN_PER_MIN` / `RATE_LIMIT_WRITE_PER_MIN` / `RATE_LIMIT_READ_PER_MIN`, `DISABLE_RATE_LIMIT`, `BACKUP_DIR`, `HTTPS_PORT` / `HTTPS_HOST` / `HTTPS_KEY_FILE` / `HTTPS_CERT_FILE`, `E2E_PORT` / `E2E_BASE_URL` / `CHROMIUM_PATH`, `LOG_DEBUG`

ไฟล์ `.env.development` และ `.env.production` แยก `DATABASE_URL` (`dev.db` / `prod.db`) เพื่อแยกสภาพแวดล้อม (TOR 4.6.2)

## 5. Prompt (ส่งมอบตาม TOR 4.11.1)

| ไฟล์ใน `config/prompts/` | key | ใช้ที่ |
|---|---|---|
| `qa-persona.v1.md`, `qa-persona.v2.md` | `qa-persona` | โหนด generate (ถาม-ตอบ) — v1 ใช้รอบ baseline |
| `dhamma-talk.v1.md` | `dhamma-talk` | โหนด generate (Dhamma Talk) |
| `guard-classifier.v1.md` | `guard-classifier` | โหนด inputGuardrail (เมื่อใช้ LLM จริง) |
| `query-rewrite.v1.md` | `query-rewrite` | โหนด inputGuardrail/rewriteQuery |
| `judge.v1.md` | `judge` | ผู้ตัดสินคะแนน NT-2 |

- ตอน seed ระบบเผยแพร่ไฟล์ทั้งหมดเป็น `PromptVersion` และตั้งเวอร์ชันล่าสุดของแต่ละ key เป็น active
- หลังติดตั้ง แหล่งความจริงคือฐานข้อมูล (แก้ที่ `/admin/prompts`) หรือแก้ไฟล์แล้ว `npm run prompts:publish` (เพิ่ม `-- --activate` เพื่อใช้งานทันที) — สร้างเวอร์ชันใหม่เฉพาะเมื่อเนื้อหาต่างจากเดิม
- prompt สำหรับข้อสอบปรนัย (MCQ) ของระบบประเมินผลฝังอยู่ใน `src/server/ai/graph.ts` (`MCQ_SYSTEM`)

## 6. ข้อมูลตั้งต้น (Seed) และ Benchmark

### 6.1 `prisma/seed.ts`

ลำดับ: ผู้ใช้สาธิต (`seed/users.json`, 6 บัญชี) → ค่า AI config ตั้งต้น → prompt → หัวข้อ guardrail (`seed/guardrail-topics.json` 15 หัวข้อ: scope_allow 6, refuse_sensitive 3, injection_pattern 4, yes_no_pattern 2) → อัตราค่าโทเคน (`seed/pricing.json`) → คลังความรู้ (`seed/knowledge/*.md`) → ชุดทดสอบ (`seed/benchmarks/*.csv`) → ข้อมูลการใช้งานสังเคราะห์ย้อนหลัง 14 วัน (ผู้ใช้สาธิต 01–30, บทสนทนา โทเคน feedback เพื่อให้ Dashboard มีข้อมูล) → audit `system` แรก แต่ละขั้นข้ามถ้ามีข้อมูลอยู่แล้ว

### 6.2 คลังความรู้ `seed/knowledge/`

169 เอกสาร (tipitaka 151, atthakatha 4, contemporary 11, teacher_dhamma 3) จากแหล่งออนไลน์ที่เผยแพร่สาธารณะ/สาธารณสมบัติ/ของ มมร. — ที่มาและสิทธิ์: `scripts/data/README.md`; สร้างซ้ำ: `npm run data:fetch`; นำเข้าเพิ่ม: `npm run data:import` รายละเอียดใน `/documents/data-ingestion-plan`

### 6.3 Benchmark `seed/benchmarks/`

| ไฟล์ | ชุด | ข้อ | ที่มา |
|---|---|---:|---|
| `ds-1-dhammasuksa-mcq.csv` | DS-1 | 100 | ข้อสอบธรรมศึกษาสนามหลวงจริง พ.ศ. ๒๕๖๓ พร้อมเฉลยทางการ |
| `nt-2-nakdham-short.csv` | NT-2 | 50 | ข้อสอบนักธรรมสนามหลวงจริง พ.ศ. ๒๕๖๒ พร้อมเฉลยทางการ |
| `ret-1-vinaya.csv`, `ret-2-sutta.csv`, `ret-3-abhidhamma.csv` | RET-1..3 | 100 × 3 | คำถามที่ตั้งจากข้อความจริงในคลัง พร้อม `expected_refs` |
| `gr-1-out-of-scope.csv` | GR-1 | 100 | เรียบเรียงขึ้นเอง |
| `gr-2-sensitive.csv` | GR-2 | 50 | เรียบเรียงขึ้นเอง |
| `injection-cases.csv` | INJ | 20 | เรียบเรียงขึ้นเอง |

แหล่งที่มา วิธีคัดเลือก และวิธีสร้างซ้ำ: `seed/benchmarks/SOURCES.md` และสคริปต์ `scripts/data/benchmarks/`

## 7. คำสั่งที่ใช้บ่อย (จาก `package.json`)

| คำสั่ง | หน้าที่ |
|---|---|
| `npm run dev` / `npm run build` / `npm start` | พัฒนา / build production / รัน production |
| `npm run start:https` | HTTPS self-signed (`server.https.js`, :3443) |
| `npm run lint` | ESLint |
| `npm test` | vitest ทั้งชุด + openapi-coverage |
| `npm run test:coverage` | vitest + coverage gate |
| `npm run test:e2e` | Playwright |
| `npm run test:sit` | API tests |
| `npm run db:migrate` / `db:seed` / `db:reset` | migrate / seed / reset ฐานข้อมูล (reset ลบข้อมูลทั้งหมด) |
| `npm run db:prod:setup` | สร้าง `prisma/prod.db` (migrate deploy + seed) |
| `npm run report:security` / `report:perf` / `report:restore-test` / `report:ingestion` / `report:evaluation` / `report:sla` / `report:all` | สร้างรายงานลง `docs/deliverables/` |
| `npm run eval:acceptance` | รันการประเมิน 7 ชุด (label acceptance) |
| `npm run purge:conversations` | ลบบทสนทนาที่หมดอายุทันที |
| `npm run prompts:publish` | เผยแพร่ prompt จากไฟล์ |
| `npm run seed:perf-users -- --count=N` | สร้างบัญชีจำนวนมากใน `prisma/perf.db` |
| `npm run data:fetch` / `data:import` | ดึงคลังความรู้จากแหล่งออนไลน์ / นำเข้าเข้า DB |
| `bash scripts/backup-db.sh` / `restore-db.sh <file>` | สำรอง/กู้คืน |
| `npx tsx scripts/reports/coverage-report.ts` | รายงาน coverage |

## 8. Logging และการเฝ้าระวัง

| แหล่ง | รายละเอียด |
|---|---|
| `logs/app.log` (`LOG_FILE`) | JSON lines: `level`, `time`, `msg`, `requestId`, `userId`, `path`, `status`, `durationMs` และฟิลด์อื่น; พิมพ์ stdout ด้วย (debug เมื่อ `LOG_DEBUG=1`) |
| ตาราง `ApiRequestLog` | ทุกคำขอ API: path pattern, method, status, durationMs, ttftMs (SSE) — ใช้คำนวณรายงาน SLA |
| `Message.traceJson` | RAG trace รายคำตอบ (เวลาแต่ละโหนด model prompt version โทเคน) |
| ตาราง `AuditLog` | เหตุการณ์สำคัญ append-only + hash chain |
| ตาราง `AlertEmailLog` | การแจ้งเตือนทั้งหมด |
| header `x-request-id` | ผูกคำขอกับ log ทุกชั้น |
| `/api/health` | สถานะฐานข้อมูลและจำนวน chunk ในดัชนี (ใช้เป็น probe) |

Production: ส่ง stdout เข้า Loki/ELK และ metrics เข้า Prometheus/Grafana ตาม Solution Architecture

## 9. การสลับ LLM และ Adapter โดยไม่แก้โค้ด

| ต้องการ | วิธี |
|---|---|
| เปลี่ยน LLM/โมเดล | `/admin/ai-config` → `llm.provider` (`typhoon` / `openai` / `gemini` / `claude` / `mock`) + `llm.model`; ใส่ API key ที่มหาวิทยาลัยจัดหาใน `.env` แล้วรีสตาร์ต; กด **ทดสอบ LLM** |
| โมเดลผู้ตัดสินการประเมิน | `eval.judgeModel` |
| Re-ranker โมเดล (bge-reranker) | ตั้ง `TEI_RERANK_URL` แล้วตั้ง `retrieval.reranker = "tei"` |
| ค้นหาด้วย Elasticsearch | implement ต่อจาก `src/server/retrieval/elasticsearch-adapter.ts` (interface `SearchGateway`) — ระบบสาธิตเป็นโครงยังไม่เชื่อมจริง |
| Google/Facebook Login จริง | ตั้ง `*_OAUTH_CLIENT_ID/SECRET` (redirect URI: `<BASE_URL>/api/auth/oauth/<provider>/callback`) |
| อีเมลแจ้งเตือนจริง | ตั้ง `SMTP_*` และ `ALERT_EMAIL_TO` |
| GA4 | ตั้ง `NEXT_PUBLIC_GA_ID` |
| Prompt | `/admin/prompts` หรือ `npm run prompts:publish` |

เพิ่ม provider ใหม่: สร้างคลาสที่ implement `LlmGateway` (`complete`, `stream`) ใน `src/server/llm/` เพิ่มกรณีใน `createLlm()` และรายการใน `listProviders()` แล้วเพิ่มกรณีทดสอบใน `tests/unit/llm-adapters.test.ts`

## 10. แนวทางการพัฒนาต่อ

1. อ่าน `docs/dev-conventions.md` (รูปแบบ route ด้วย `withApi`, การบันทึก audit, i18n, การลงทะเบียน OpenAPI, กติกาสี/responsive)
2. Endpoint ใหม่ต้องลงทะเบียนใน `src/server/api/openapi/<group>.ts` และมีกรณีทดสอบใน `tests/api` (มิฉะนั้น openapi-coverage ล้มเหลว)
3. ข้อความ UI ใหม่ต้องมีทั้ง `messages/th` และ `messages/en` (key ตรงกัน)
4. ห้ามแก้ `prisma/schema.prisma` โดยไม่สร้าง migration และทบทวน Data Dictionary ใน SRS
5. ก่อน merge: `npx tsc --noEmit`, `npm run lint`, `npm test`, `npm run test:e2e`

## 11. รายการเอกสารส่งมอบ

ศูนย์เอกสาร `/documents` (ไฟล์ `docs/deliverables/*.md`, ดาวน์โหลด .md หรือพิมพ์ PDF) — รายการที่ต้องมี 36 ฉบับตาม `tests/unit/documents.test.ts`

| หมวด | เอกสาร |
|---|---|
| บริหารโครงการ | project-plan, team-structure, risk-plan, meeting-minutes-template, progress-report-template, periodic-summary-template |
| ออกแบบ | requirements-summary, srs, ux-deliverables, data-ingestion-plan |
| ทดสอบ | master-test-plan, test-checklist, test-reports-index |
| รายงานอัตโนมัติ | coverage-report, vulnerability-scan-report, pentest-report, performance-report, restore-test-report, ingestion-report, baseline-evaluation-report, guardrail-security-report, sla-monthly-report, data-destruction-certificate |
| คู่มือ | user-manual, admin-manual, training-materials |
| ส่งมอบ | system-documentation, deployment-guide, backup-restore-guide, transition-plan, cicd-pipeline |
| สัญญา | contract-summary, confidentiality-statement, ip-statement, general-terms, pdpa-dpa |

(การจัดหมวดของแต่ละฉบับยึดตาม frontmatter `category` ของไฟล์นั้น)

## 12. สิ่งที่ส่งมอบตาม TOR 4.11.1

| รายการ | ตำแหน่ง |
|---|---|
| Source Code | ทั้ง repository (`src/`, `scripts/`, `tests/`, `prisma/`) |
| Configuration | `.env.example`, `.env.development`, `.env.production`, `next.config.ts`, `vitest.config.ts`, `playwright.config.ts`, `infra/helm/`, `.github/workflows/ci-cd.yml`, ค่าตั้งต้น AI config (`src/domain/config/ai-config.ts`) |
| Prompt | `config/prompts/*.md` (+ เวอร์ชันในตาราง `PromptVersion`) |
| Benchmark | `seed/benchmarks/*.csv` + `SOURCES.md` + `scripts/data/benchmarks/` |
| ข้อมูลตั้งต้น | `seed/` |
| เอกสาร | `docs/` |
