diff --git a/docs/asset-license-management.md b/docs/asset-license-management.md index 49ecbd5..2d8b5aa 100644 --- a/docs/asset-license-management.md +++ b/docs/asset-license-management.md @@ -74,6 +74,8 @@ QR gán asset vào slot (bước 1, thủ công hàng ngày) **không phải IoT - Cron job (vd gửi email cảnh báo license sắp hết hạn hàng ngày) **không cần tách backend riêng** — làm 1 script độc lập (`scripts/send-license-expiry-emails.ts`) query thẳng Postgres, lịch chạy qua Windows Task Scheduler (đã có tiền lệ ở `xibo-signage.md`, workspace ngoài repo này) hoặc container cron riêng trong Docker. Cần chốt sau: SMTP nào, ngưỡng cảnh báo bao nhiêu ngày, gửi cho ai. - Cân nhắc thay thế cho MVP: Airtable/Google Form nếu muốn test quy trình trước khi build — nhưng approval workflow nhiều bước + audit trail sẽ gượng ép nếu để lâu dài trên low-code. - Reverse proxy khi deploy: **Nginx Proxy Manager** (đã chốt 2026-07-30) — tự host, có UI quản lý + tự động Let's Encrypt. Chưa dựng ngay vì app còn ở local dev, chưa tới bước deploy production. Khi deploy, app này khả năng sẽ dùng chung 1 NPM instance với các service self-host khác trong workspace (vd Xibo) thay vì mỗi app 1 reverse proxy riêng — cần xác nhận lại lúc thực sự deploy. +- Postgres: **không expose ra internet qua domain** (đã chốt 2026-07-31) — dù kỹ thuật làm được giống các cloud DB (domain + TLS + password mạnh), việc đó bắt tự vận hành toàn bộ phần bảo mật mà cloud provider thường lo (firewall theo IP, TLS, fail2ban, vá lỗi định kỳ) trong khi DB chứa data công ty thật. Quyết định: **dev/test dùng Postgres local riêng từng máy** (Docker, không expose). Khi deploy production ở nhà (Proxmox), Postgres prod chạy **riêng biệt, không public** — nếu cần connect từ máy khác (vd máy công ty) thì qua **VPN/SSH tunnel**, không mở port DB ra ngoài. +- Docker-compose: **giữ chung 1 stack** (app + `db` cùng 1 `docker-compose.yml`) thay vì tách file riêng cho DB — đã note tên network/volume/container tường minh (`asset-license-mgmt-net`, `asset-license-mgmt-db-data`, `asset-license-mgmt-db`) sẵn từ đầu nên tách sau này (nếu có consumer thứ 2 độc lập cần DB — vd cron container, IoT bridge) vẫn rẻ: chỉ cần đổi network thành `external: true` ở cả 2 file, volume tự nhận lại theo tên, gần như không downtime. ### Khi nào nên tách backend riêng (chưa áp dụng, chỉ ghi lại trigger)