# Environment & Secrets (เฟส 4 + เฟส 3 Token Security Layer)
อัปเดต: 26 กุมภาพันธ์ 2026

## ไฟล์ตัวอย่าง
- `.env.example` — ค่าพื้นฐานสำหรับ dev (PORT 22222, API base, token placeholder, rate-limit, DB)

## วิธีตั้งค่า
### Dev (เครื่องนักพัฒนา)
1) `cp .env.example .env`
2) ตั้งอย่างน้อย 1 ใน 2 (ถ้าไม่ตั้งใน dev จะ fallback `../WepAppOpus/db/ads.db`):  
   - `DATABASE_URL=mysql://user:pass@host:3306/lnwads_wepappopus` (ใช้ DB ร่วม)  
   - `ADS_DB_PATH=../WepAppOpus/db/ads.db` (ใช้ SQLite dev)  
3) ตั้งค่า token แบบเข้ารหัส (แนะนำ):
   - สร้าง envelope: `npm run token:encrypt -- "<plain-token>"`
   - ใส่ค่าใน `.env` เป็น `API_ACCESS_TOKEN_ENC=v1....`
   - ถ้าจำเป็นยังรองรับ `API_ACCESS_TOKEN` (plaintext/legacy)

### Prod / Staging
- ตั้งค่าเป็น environment variables (หรือ secret manager) ไม่เก็บเป็นไฟล์บนเครื่อง
- เงื่อนไขความปลอดภัยในโค้ด:  
  - รองรับ default token ทั้ง `API_ACCESS_TOKEN_ENC` (แนะนำ) และ `API_ACCESS_TOKEN` (legacy)
  - ถ้าใส่ค่าแบบ encrypted (`v1....`) ต้องมี `TOKEN_ENCRYPTION_KEY` + `TOKEN_ENCRYPTION_KEY_ID` ที่ตรงกัน
  - ต้องมี `DATABASE_URL` หรือ `ADS_DB_PATH` อย่างน้อยหนึ่งตัว ไม่เช่นนั้น service ไม่ start
- PM2: `pm2 start pm2.config.cjs --update-env` แล้ว inject env ผ่าน PM2 ecosystem/OS env

### Rotation / Logging
- Token/API keys: ใส่ผ่าน env, ห้าม log; logger ใช้ pino ไม่พิมพ์ header auth
- เปลี่ยน token: เข้ารหัสใหม่แล้ว reload/restart service (รองรับ PM2 reload)
- ตาราง `auth_user_api_sources` จะ migrate token เก่าแบบ plaintext ให้เป็น encrypted envelope อัตโนมัติเมื่อ service start
- Error message จาก `/live/accounts` และ `/live/dashboard` จะ redaction ค่า token-like text ก่อน log/response

## ตัวแปรหลัก
- `PORT`, `HOST`, `LOG_LEVEL`
- `API_BASE_URL`, `API_ACCESS_TOKEN_ENC`, `API_ACCESS_TOKEN`, `API_RATE_LIMIT_RPS`
- `LIVE_ACCOUNTS_CACHE_TTL_SECONDS`, `LIVE_DASHBOARD_CACHE_TTL_SECONDS`
- `LIVE_ACCOUNTS_FETCH_CONCURRENCY`
- `LIVE_CACHE_L1_TTL_SECONDS`, `LIVE_CACHE_L1_MAX_ENTRIES`, `LIVE_CACHE_PRUNE_INTERVAL_SECONDS`
- `DATABASE_URL` (MySQL prod) หรือ `ADS_DB_PATH` (SQLite dev)
- `TOKEN_ENCRYPTION_KEY`, `TOKEN_ENCRYPTION_KEY_ID` (ใช้ทั้งเข้ารหัส token ใน DB และถอดรหัส `API_ACCESS_TOKEN_ENC`)
- `SECURITY_HEADERS_ENABLED` เปิด/ปิดการใส่ security headers (`nosniff`, `frame`, `referrer-policy`, `permissions-policy`)
- `CSRF_ORIGIN_CHECK_ENABLED`, `CSRF_ALLOWED_ORIGINS` สำหรับกัน CSRF บน endpoint ที่แก้ไขข้อมูล (`/auth/*` ที่เกี่ยวกับแก้ไขบัญชี/โปรไฟล์)
- `LOGIN_RATE_LIMIT_MAX_ATTEMPTS`, `LOGIN_RATE_LIMIT_WINDOW_SECONDS`, `LOGIN_RATE_LIMIT_BLOCK_SECONDS` สำหรับ brute-force protection ของ `/auth/login`

## Validation behavior
- แนะนำใช้ `API_ACCESS_TOKEN_ENC` แทน plaintext
- ถ้า token อยู่ในรูป `v1....` แต่ไม่มี/คีย์ไม่ตรงกับ `TOKEN_ENCRYPTION_KEY` จะ start ไม่ผ่าน
- ทุกโหมด: ต้องมี DB target อย่างน้อยหนึ่งตัว
- `API_RATE_LIMIT_RPS` fallback 8 ถ้าไม่ตั้ง
- แนะนำตั้ง `TOKEN_ENCRYPTION_KEY` เสมอเพื่อรองรับ token profile และ default token แบบเข้ารหัส
