- [ ] Subtask 1.1: Gỡ bỏ flow nhập `api_key` tự do ở giao diện LLM Configs (`surfsense_web/app/dashboard/[search_space_id]/llm-configs`), khoá cứng các tuỳ chọn chọn Provider.
- [ ] Subtask 1.2: Triển khai Component `ModelSelector` trên UI Chat (hoặc sửa đổi UI chọn LLM Config cũ sang danh sách LLM thương mại).
- [ ] Task 3: Tích hợp logic Trừ Quota vào RAG Engine (Backend - `rag_engine` / `chat_session_api`)
- [ ] Subtask 3.1: Ở API Endpoint Streaming, kiểm tra `token_balance` trước khi khởi tạo luồng SSE. Nếu <= 0, trả HTTP 402/429.
- [ ] Subtask 3.2: Dùng `tiktoken` hoặc đếm chữ ước tính số tokens Generate để UPDATE trừ lùi vào Database sau mỗi chu kỳ trả lời xong.
- [ ] Task 4: Hiển thị Banner nâng cấp (Frontend)
- [ ] Subtask 4.1: Bắt lỗi 402/429 từ SSE, render Alert UI Upgrade.
## Dev Notes
### Relevant Architecture Patterns & Constraints
- **Billing Pivot Constraint:** Đây là cốt lõi của quá trình chuyển đổi sang nền tảng Thương mại (SaaS SaaS Commercialization). CẤM các logic Hardcode API key người dùng truyền vào, tất cả Server Auth phải lấy từ biến môi trường `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`.
- **Concurrency & Database Locks:** Việc trừ Token balance phải chịu sự cạnh tranh cao (ví dụ mở 2 tab chat đồng thời). Yêu cầu cân nhắc dùng `session.execute(update(User).where(...).values(token_balance=User.token_balance - cost))` để tận dụng Database atomic locks (tránh Race conditions).
- **RAG Endpoint:** `Surfsense` stream thông qua giao thức SSE ở `/api/v1/chat/stream`. Hãy thêm interceptor kiểm tra số dư ngay đầu route (Fail-fast).
### Project Structure Notes
- Module thay đổi:
-`surfsense_backend/app/db.py`
-`surfsense_backend/app/routes/chat_routes.py` (hoặc nơi implement SSE)
- Phải đảm bảo DB schema migration (bằng Alembic) khi có thuộc tính mới `token_balance` ở User.
- Endpoint `/api/v1/chat/stream` hiện đang phụ thuộc vào `NewLLMConfig`. Cần chỉnh sửa kiến trúc để ánh xạ ID Model do người dùng chọn sang Backend Config cố định của hệ thống.