feat: initialize agent and claude skill libraries with comprehensive knowledge bases, workflow templates, and implementation artifacts.

This commit is contained in:
Vonic 2026-04-13 09:49:58 +07:00
parent 956d8c6322
commit b35b4337bb
2028 changed files with 565614 additions and 0 deletions

View file

@ -0,0 +1,31 @@
# Story 1.1: Khởi tạo Hạ tầng Dự án & Cơ sở Dữ liệu (Project Infrastructure & Database Init)
**Status:** done
## PRD Requirements
As a Kỹ sư Hệ thống,
I want thiết lập bộ khung Next.js, FastAPI, và cấu hình Docker-compose cho Postgres/Redis/ZeroServer,
So that toàn bộ nền tảng có thể khởi chạy môi trường phát triển (Dev Environment) một cách nhất quán cho tất cả các team.
**Acceptance Criteria:**
**Given** môi trường dự án mới
**When** chạy lệnh `docker-compose -f docker/docker-compose.dev.yml up -d`
**Then** các containers Postgres 16 (với pgvector), Redis, Zero-Server, FastAPI, và Next.js khởi tạo thành công
**And** database tự động migrate được schema ban đầu bao gồm bảng `users` với quy tắc `snake_case`.
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,31 @@
# Story 1.2: Triển khai Backend API Xác thực & JWT (Backend Auth API & JWT)
**Status:** done
## PRD Requirements
As a Người dùng,
I want gọi API an toàn để tạo tài khoản, đăng nhập và lấy mã Token (JWT),
So that hệ thống xác thực được danh tính của tôi và kích hoạt RLS (Row-level Security) bảo vệ dữ liệu trên Database Postgres.
**Acceptance Criteria:**
**Given** thông tin đăng nhập hợp lệ
**When** gửi request tới endpoint liên quan `/api/v1/auth/login`
**Then** hệ thống trả về mã JWT chứa userID hợp lệ, bọc trong cấu trúc Wrapper chuẩn `{ "data": {"token": "xxx"}, "error": null, "meta": null }`
**And** Cấu hình Row-Level Security (RLS) cơ bản cho bảng dữ liệu (người này không query được dữ liệu của người kia).
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,34 @@
# Story 1.3: Giao diện Đăng nhập & Tích hợp Token vào Zero-Client (Frontend Auth UI)
**Status:** done
## PRD Requirements
As a Người dùng,
I want sử dụng giao diện trơn tru để đăng ký/đăng nhập,
So that tôi nhận được Token và ngay lập tức kết nối tới hệ thống dữ liệu Local-first an toàn qua Zero Client.
**Acceptance Criteria:**
**Given** tôi đang ở trạng thái khách (Guest) trên UI
**When** tôi điền form đăng nhập thành công
**Then** giao diện lưu token vào cục bộ và tự động khởi tạo instance `ZeroClient` để bắt đầu mở cầu nối WebSockets.
**And** khi tôi nhấn nút "Đăng xuất" (Log Out), hàm `onLogout()` tự động thực thi dọn dẹp sạch (purge) toàn bộ IndexedDB, chặn bảo mật.
**And** Giao diện (Form đăng nhập, nút bấm) ứng dụng quy chuẩn UX-DR1 (Màu Base Zinc/Accent Indigo, font Inter).
Người dùng dễ dàng kéo thả các tệp PDF/TXT lên hệ thống; hệ thống tự động bóc tách dữ liệu mượt mà trong nền mà không làm gián đoạn công việc. Họ nắm rõ tiến độ nạp file và làm chủ khối lượng tài liệu của mình.
**FRs covered:** FR1, FR2, FR3, FR4, FR12, FR13
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,31 @@
# Story 2.1: Khởi tạo Kiến trúc Tác vụ nền & Xử lý PDF (Celery Worker & PDF Parser)
**Status:** done
## PRD Requirements
As a Kỹ sư Hệ thống,
I want xây dựng hệ thống worker bất đồng bộ (Celery + Redis) để bóc tách văn bản và tạo Vector Embeddings,
So that hệ thống API chính không bị nghẽn khi người dùng upload file, và có thể scale linh hoạt số lượng worker.
**Acceptance Criteria:**
**Given** phần mềm nhận một file PDF/TXT được đẩy vào hàng đợi (Queue)
**When** worker được phân công thực thi tác vụ
**Then** tiến trình phân giải text và nạp Vector qua pgvector hoàn thành dưới 30s (đối với file <5MB)
**And** trạng thái bản ghi tài liệu trên Database được cập nhật tuần tự (Processing -> Completed hoặc Error).
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,31 @@
# Story 2.2: Triển khai API Tải lên & Giới hạn Rate Limit (Upload API & Rate Limiting)
**Status:** done
## PRD Requirements
As a Kỹ sư Backend,
I want xây dựng endpoint FastAPI cho việc upload tài liệu kèm cơ chế Rate Limit,
So that server tiếp nhận an toàn và ngăn chặn upload spam quá mức hệ thống cho phép.
**Acceptance Criteria:**
**Given** người dùng đăng nhập hợp lệ
**When** đính kèm file và gửi POST tới `/api/v1/documents`
**Then** hệ thống check user token, lưu file vô Storage, tạo record ở DB với status 'Queue', và trigger đẩy task vào Celery
**And** nếu user push liên tục quá mức quy định (token/hạn mức tải), API sẽ trả về lỗi `429 Too Many Requests` bọc trong error format chuẩn.
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,31 @@
# Story 2.3: Giao diện Quản lý Tài liệu & Chỉ báo Syncing Khớp nối (Knowledge Base UI & Micro-Sync Indicators)
**Status:** done
## PRD Requirements
As a Người dùng,
I want thấy ngay lập tức danh sách tài liệu đang có và dễ dàng tải file mới lên,
So that tôi biết file nào đã sẵn sàng để chat, file nào đang chạy nền mà không bị gián đoạn thao tác chuột.
**Acceptance Criteria:**
**Given** người dùng ở giao diện không gian làm việc (Workspace)
**When** có một tài liệu đang được tải lên hoặc xử lý (Processing)
**Then** UX hiển thị thanh tiến trình nhỏ ở góc trên màn hình / cạnh danh sách (Micro-Sync Indicator) và không được chặn màn hình (UX-DR5)
**And** danh sách tài liệu được lấy thông qua Zero-client tự động update state realtime khi worker xử lý xong (FR2, FR3).
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,33 @@
# Story 2.4: API và Giao diện Xóa tài liệu khỏi Workspace (Delete Document Flow)
**Status:** done
## PRD Requirements
As a Người dùng,
I want chọn một tài liệu cũ và xóa hoàn toàn,
So that không gian lưu trữ được dọn dẹp và AI sẽ không bao giờ truy cập nội dung đó nữa.
**Acceptance Criteria:**
**Given** người dùng đang có tài liệu hiển thị trên danh sách
**When** người dùng click icon "Xoá" file
**Then** dữ liệu tài liệu lập tức bị loại bỏ khỏi giao diện UI do cơ chế optimism update của Zero
**And** trên Database, bản ghi bị xoá hoặc mark deleted, kèm theo việc dọn dẹp các Vectors rác liên quan trong background.
Người dùng có trải nghiệm truy vấn kho tài liệu "không độ trễ" (Instant Action) thông qua chat. Kết quả được stream về theo thời gian thực như một trợ lý xịn, tích hợp hệ thống Split-pane tinh tế để đối chiếu thẳng với Nguồn trích dẫn.
**FRs covered:** FR5, FR6, FR7
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,31 @@
# Story 3.1: API Tạo & Quản lý Phiên Chat (Chat Session API)
**Status:** done
## PRD Requirements
As a Người dùng,
I want tạo một phiên trò chuyện (chat session) mới với AI,
So that tôi có thể bắt đầu một định mức hội thoại mới, tách bạch hoàn toàn với các chủ đề cũ.
**Acceptance Criteria:**
**Given** cửa sổ Chat
**When** tôi chọn lệnh "New Chat" hoặc nhập thẳng vào input đầu tiên
**Then** hệ thống tạo một "Session" ID mới trên Database và lưu tin nhắn đầu tiên của user (FR5, FR6)
**And** trả về data qua REST API theo wrapper chuẩn để client chốt phiên làm việc.
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,32 @@
# Story 3.2: Khối RAG Engine & Cổng trả Streaming SSE (RAG Engine & SSE Endpoint)
**Status:** done
## PRD Requirements
As a Kỹ sư Backend,
I want xây dựng khối RAG query bằng pgvector và đẩy dữ liệu về dạng Server-Sent Events (SSE),
So that AI có thể phản hồi từng chữ một (streaming) ngay khi lấy được ngữ cảnh, và đảm bảo chuẩn NFR-P1 (< 1.5s).
**Acceptance Criteria:**
**Given** backend nhận một câu hỏi của user và Session ID
**When** gọi tới Model AI (ví dụ OpenAI/Gemini) với ngữ cảnh lấy từ VectorDB
**Then** API `/api/v1/chat/stream` trả dòng response trả về dưới định dạng sự kiện SSE (text/event-stream) (FR7)
**And** ký tự đầu tiên (First token) về tới client dưới 1.5s
**And** ở cuối luồng stream trả về đính kèm bộ Metadata (Array các id/đoạn trích dẫn được dùng).
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,31 @@
# Story 3.3: Giao diện Khung Chat & Tiếp nhận Streaming (Chat UI & SSE Client)
**Status:** done
## PRD Requirements
As a Người dùng,
I want thấy AI gõ từng chữ một vào màn hình chat kèm format Markdown đàng hoàng,
So that tôi không phải mòn mỏi nhìn biểu tượng Loading như các web đời cũ.
**Acceptance Criteria:**
**Given** tôi vừa bấm gửi câu hỏi "Ping"
**When** Next.js client mở luồng SSE kết nối về FastAPI
**Then** tin nhắn được append dần lên UI mượt mà với hoạt ảnh <150ms
**And** render được định dạng Markdown cơ bản (Bold, List, Code block) một cách trơn tru, không xộc xệch nhảy dòng khó chịu.
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/agents/new_chat/utils.py`
- `surfsense_backend/app/schemas/chat_session_state.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/routes/public_chat_routes.py`
- `surfsense_backend/app/schemas/new_chat.py`
- `surfsense_backend/app/tasks/chat/stream_new_chat.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,30 @@
# Story 3.4: Kiến trúc Split-Pane & Tương tác Trích dẫn (Split-Pane Layout & Interactive Citation)
**Status:** done
## PRD Requirements
As a Người dùng,
I want đọc khung chat ở một bên và văn bản gốc ở bên cạnh trên cùng 1 màn hình, bấm vào thẻ [1] ở chat là bên kia nhảy text tương ứng,
So that tôi có thể đối chiếu thông tin AI "bịa" hay "thật" ngay lập tức mà không phải tìm mỏi mắt.
**Acceptance Criteria:**
**Given** UI chia 2 bên (Split-Pane - bằng react-resizable-panels) - Chat trái, Doc phải (UX-DR3)
**When** AI trả lời xong có đính kèm cite `[1]`, tôi click vào `[1]`
**Then** bảng Document tự động đổi sang file tương ứng và auto-scroll + highlight dải vàng đúng dòng text đó (UX-DR4).
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,61 @@
# Story 3.5: Lựa chọn Mô hình LLM dựa trên Subscription (Model Selection via Quota)
Status: ready-for-dev
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
## Story
As a Người dùng,
I want chọn cấu hình mô hình trí tuệ nhân tạo (VD: Claude 3.5 Sonnet, GPT-4) được cung cấp sẵn mà không cần điền API key cá nhân,
so that tôi có thể dùng trực tiếp và chi phí sử dụng được trừ thẳng vào số Token thuộc gói cước của tôi.
## Acceptance Criteria
1. Hệ thống cung cấp Dropdown chọn `LLM Model` trong giao diện Chat.
2. Tuyệt đối không hiển thị ô nhập "Your API Key" ở Frontend (Xóa bỏ logic Bring-Your-Own-Key cũ nếu có).
3. Hệ thống Backend tính toán chi phí (Token * Đơn giá của Model).
4. Hệ thống kiểm tra Quota hàng tháng của người dùng; nếu vượt quá (Quota Exceeded), trả về lỗi 403/429 báo "Hãy nâng cấp gói".
## Tasks / Subtasks
- [ ] Task 1: Dọn dẹp Kiến trúc Client cũ (Frontend)
- [ ] Subtask 1.1: Gỡ bỏ toàn bộ input fields `openAiKey` / `anthropicKey` khỏi Sidebar/Settings.
- [ ] Subtask 1.2: Triển khai Component `ModelSelector` trên UI Chat (gồm ít nhất 2 tuỳ chọn: `GPT-4o-mini` (Rẻ) và `Claude-3.5-Sonnet` (Cao cấp)).
- [ ] Task 2: Cập nhật Schema & Table Quản lý Quota (Backend - `db.py`)
- [ ] Subtask 2.1: Bổ sung column `token_balance` (Integer) vào model `User` (hoặc tạo table `UserSubscription`).
- [ ] Subtask 2.2: Bổ sung ENUM `LLM_MODEL` vào config db.
- [ ] 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)
- `surfsense_web/src/components/chat/`
- Phải đảm bảo DB schema migration khi có thuộc tính mới ở User (hoặc bảng rời). Hãy ưu tiên bảng User chung để truy vấn Rate Limit nhanh chóng thay vì join table phức tạp nếu không cần thiết.
### References
- [Epic 3 - RAG Engine Requirements]: Epic `3.5`.
- [Constraint from BMad Rule]: "All billing must handle quota limits based on the user's current subscription".
## Dev Agent Record
### Agent Model Used
Antigravity Claude 3.5 Sonnet Engine (Context: 120k)
### File List
- `surfsense_backend/app/db.py`
- `surfsense_backend/app/models/...` (nếu có chia module)
- `surfsense_backend/app/routes/chat_routes.py`
- `surfsense_web/src/components/chat/ModelSelector.tsx`

View file

@ -0,0 +1,31 @@
# Story 4.1: Đồng bộ Danh sách Phiên Chat & Lịch sử Tin nhắn (Chat History Sync)
**Status:** done
## PRD Requirements
As a Người dùng,
I want danh sách lịch sử các phiên chat và tin nhắn bên trong tự động đồng bộ xuống máy tôi qua Zero-client,
So that tôi mở app lên là thấy ngay lập tức lịch sử cũ (FR8, FR9) và đọc liên tiếp không cần chờ load từ internet (FR10).
**Acceptance Criteria:**
**Given** thiết bị của tôi đã từng kết nối mạng trước đó
**When** tôi chọn một Session cũ (như hôm qua) trong Sidebar
**Then** hệ thống query trực tiếp từ IndexedDB cục bộ qua thư viện `@rocicorp/zero` và móc lên UI
**And** thời gian data mới từ server đẩy cập nhật xuống dưới Local Storage luôn đảm bảo dưới 3s (NFR-P2).
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,31 @@
# Story 4.2: Giao diện Phân rã Ân hạn khi ngắt mạng (Graceful Degradation Offline UI)
**Status:** done
## PRD Requirements
As a Người dùng,
I want hệ thống tự động khóa các tính năng cần internet như "Chat/Gửi tin/Upload" khi tôi mất wifi,
So that tôi không bị văng lỗi hay hiện màn hình đơ cứng, thay vào đó vẫn thong dong đọc nội dung cũ (NFR-R1).
**Acceptance Criteria:**
**Given** người dùng cấu hình ngắt mạng cố ý hoặc đột ngột mất wifi
**When** họ đang mở app
**Then** giao diện tự động bật mode Graceful Degradation: Input chat bị disable, nút Upload file bị mờ (muted xám)
**And** người dùng vẫn có thể click đọc văn bản trên màn Split-Pane thoăn thoắt không trễ (UX-DR6).
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/auth.py`
- `surfsense_backend/app/agents/new_chat/tools/mcp_tool.py`
- `surfsense_backend/app/services/linear/__init__.py`
- `surfsense_backend/app/services/vision_autocomplete_service.py`
- `surfsense_backend/app/etl_pipeline/parsers/vision_llm.py`
- `surfsense_backend/app/agents/new_chat/tools/jira/update_issue.py`
- `surfsense_backend/app/connectors/teams_connector.py`
- `surfsense_backend/app/utils/rbac.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,33 @@
# Story 4.3: Tích hợp Chỉ báo Trạng thái Mạng Toàn Cục (Global Network & Sync Indicators)
**Status:** done
## PRD Requirements
As a Người dùng,
I want thấy một icon nhỏ hoặc dải màu trực quan cho biết App đang Online, Offline, hay Syncing,
So that tôi chủ động biết ứng dụng có đang "sống" và "khớp nối" dữ liệu với đám mây hay không (FR11).
**Acceptance Criteria:**
**Given** app đang khởi chạy bình thường
**When** trạng thái kết nối mạng của Zero Client hoặc Browser thay đổi
**Then** Header hoặc góc dưới màn hình cập nhật icon (Xanh: Connected / Vàng: Syncing / Đỏ/Xám: Offline)
**And** thiết kế phải hòa hợp với bộ màu ZinC/Slate đã chọn, tuyệt đối không dùng thông báo (alert) nhảy ập vào mặt người dùng.
Hệ thống biến từ một ứng dụng tĩnh thành một nền tảng SaaS thương mại thông qua tích hợp thanh toán Stripe. Người dùng có thể xem bảng giá, chọn gói cước phù hợp, thanh toán an toàn và hệ thống tự động kiểm soát quota sử dụng dựa trên gói đăng ký, đảm bảo mô hình kinh doanh bền vững.
**FRs covered:** FR15, FR16, FR17
## Architecture Compliance & As-Built Context
> *This section is automatically generated to map implemented components to this story's requirements.*
This story has been successfully implemented in the brownfield codebase. The following key files contain the core logic for this feature:
- `surfsense_backend/app/schemas/stripe.py`
- `surfsense_backend/app/services/linear/kb_sync_service.py`
- `surfsense_backend/app/services/page_limit_service.py`
- `surfsense_backend/app/services/google_calendar/kb_sync_service.py`
- `surfsense_backend/app/routes/stripe_routes.py`
- `surfsense_backend/app/services/google_drive/kb_sync_service.py`
- `surfsense_backend/app/services/gmail/kb_sync_service.py`
- `surfsense_backend/app/services/onedrive/kb_sync_service.py`
## Implementation Notes
- **UI/UX**: Needs to follow `surfsense_web` React/Tailwind standards.
- **Backend**: Needs to follow `surfsense_backend` FastAPI standards.

View file

@ -0,0 +1,51 @@
# Story 5.1: Giao diện Bảng giá & Lựa chọn Gói Cước (Pricing Plan Selection UI)
Status: ready-for-dev
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
## Story
As a Khách hàng tiềm năng,
I want xem một bảng giá rõ ràng về các gói cước (ví dụ: Free, Pro, Team) với quyền lợi tương ứng,
so that tôi biết chính xác số lượng file/tin nhắn mình nhận được trước khi quyết định nâng cấp hoặc duy trì để quản lý ví (Wallet/Token) của mình.
## Acceptance Criteria
1. UI hiển thị các mức giá (monthly/yearly) rõ ràng cùng các bullets tính năng.
2. Thiết kế áp dụng chuẩn UX-DR1 (Dark mode, Base Zinc, Accent Indigo) hiện có của app.
3. Kèm theo hiệu ứng hover mượt mà cho các Pricing Cards (<150ms delay).
4. Phân bổ ít nhất 2 gói cước (Free, Pro) gắn liền với Limit.
## Tasks / Subtasks
- [ ] Task 1: Dựng Page Route Pricing (Frontend)
- [ ] Subtask 1.1: Tạo Component `/src/pages/pricing/page.tsx` (app router tuỳ cấu hình Next.js hoặc Vite App).
- [ ] Subtask 1.2: Sử dụng thư viện `framer-motion` (nếu có sẵn) hoặc Tailwind Utilities (`transition-all duration-150`) để thoả mãn Animation criteria.
- [ ] Task 2: Data cấu hình Static Pricing (Frontend)
- [ ] Subtask 2.1: Cấu trúc Object Constant cho Gói "Free" (Limits: 10 docs, 50 LLM messages/day).
- [ ] Subtask 2.2: Cấu trúc Object Constant cho Gói "Pro" (Limits: 100 docs, 1000 LLM messages/day).
- [ ] Task 3: Liên kết Nút "Upgrade" (Frontend)
- [ ] Subtask 3.1: Nút nâng cấp sẽ chèn hàm mock gọi `/api/v1/stripe/checkout` (Endpoint này sẽ được làm chi tiết ở story 5.2).
## Dev Notes
### Relevant Architecture Patterns & Constraints
- **State Management & Data Retrieval:** Vì UI Pricing khá tĩnh, hãy triển khai bằng cấu trúc Const Typescript thay vì gọi DB ở màn đầu tiên nhằm tối ưu tốc độ load.
- Chú ý đến Graceful degradation: Nếu user Offline, màn pricing vẫn load được Static Data, nhưng disable nút "Purchase" để tránh lỗi Network Request.
### Project Structure Notes
- Module thay đổi:
- `surfsense_web/src/pages/pricing/page.tsx` (hoặc tương đương tuỳ thư mục routes).
- `surfsense_web/src/constants/billing.ts` (Lưu định mức cước).
### References
- [Epic 5 - Commercialization & Account Limits].
## Dev Agent Record
### Agent Model Used
Antigravity Claude 3.5 Sonnet Engine
### File List
- `surfsense_web/src/pages/pricing...`

View file

@ -0,0 +1,46 @@
# Story 5.2: Tích hợp Stripe Checkout (Stripe Payment Integration)
Status: ready-for-dev
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
## Story
As a Người dùng,
I want bấm "Nâng cấp" và được chuyển tới trang thanh toán an toàn,
so that tôi có thể điền thông tin thẻ tín dụng mà không sợ bị lộ dữ liệu trên máy chủ của SurfSense.
## Acceptance Criteria
1. Khi User bấm thanh toán, BE gọi API Stripe lấy `sessionId` của Stripe Checkout (Chế độ Subscription / Recurring Mode, không phải Chế độ Mua đứt OTP).
2. Hệ thống redirect User an toàn qua cổng Stripe được Hosted trực tiếp bởi Stripe Server.
## Tasks / Subtasks
- [ ] Task 1: Nâng cấp `stripe_routes.py`
- [ ] Subtask 1.1: Bổ sung Endpoint POST `/api/v1/stripe/create-subscription-checkout`.
- [ ] Subtask 1.2: Phân tích `plan_id` từ Request body hoặc User, cấu hình `mode='subscription'` trong dict truyền cho thư viện Stripe (thay vì chế độ `payment` cũ).
- [ ] Task 2: Liên kết Action Nút ở UI
- [ ] Subtask 2.1: Ở `Pricing` Component, xử lý `onClick` bằng cách submit POST form request tới API mới, bắt `checkout_url` và route trình duyệt tới URL đó bằng thẻ A hoặc JS `window.location.href`.
## Dev Notes
### Relevant Architecture Patterns & Constraints
- Codebase hiện có `surfsense_backend/app/routes/stripe_routes.py` nhưng ĐANG GẮN code Payment Intent cho Token "Page Purchase" One-time 1 lần. DEV cần lưu ý CẤU HÌNH LẠI để route mới sinh này phục vụ riêng cho gói Subscription hàng tháng (Gửi theo CustomerID nếu User đã bind).
- Security: Giá `stripe_price_id` bắt buộc phải map và define ở Back-End environment variable (Vd `STRIPE_PRO_PLAN_ID`), tuyệt đối không chấp nhận param `price` từ Header gửi lên (Phòng tránh giả mạo giá tiền).
### Project Structure Notes
- Module thay đổi:
- `surfsense_backend/app/routes/stripe_routes.py`
- `surfsense_web/src/pages/pricing/page.tsx`
### References
- [Epic 5.2 - Subscriptions]
## Dev Agent Record
### Agent Model Used
Antigravity Claude 3.5 Sonnet Engine
### File List
- `surfsense_backend/app/routes/stripe_routes.py`

View file

@ -0,0 +1,49 @@
# Story 5.3: Webhook & Cập nhật Trạng thái Gói cước (Stripe Webhook Sync)
Status: ready-for-dev
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
## Story
As a Kỹ sư Hệ thống,
I want backend tự động hứng Webhook từ Stripe mỗi khi có thanh toán thành công, gia hạn, hoặc hủy gói,
so that database được cập nhật trạng thái Subscription của user (Active/Canceled) mà không cần can thiệp thủ công.
## Acceptance Criteria
1. Backend bắt được Event Type qua HTTP POST.
2. Kiểm tra chính xác Webhook-Signature tránh Event giả.
3. Update trạng thái (Status, Expiry date, Plan_id) vào User record tương ứng trên Database Postgres.
## Tasks / Subtasks
- [ ] Task 1: Dựng Webhook Route
- [ ] Subtask 1.1: Tạo Route `/api/v1/stripe/webhook` (đã có route cũ dành cho Page Purchase, xem ở `stripe_routes.py` line 281).
- [ ] Subtask 1.2: Code logic giải mãi Signature.
- [ ] Task 2: Listen Subscription Events
- [ ] Subtask 2.1: Phân tích Webhook Event Type. Lắng nghe ít nhất 2 Event cơ bản: `customer.subscription.updated``customer.subscription.deleted`. Xử lý và fetch customer ID để map với User nội bộ (có thể dùng `stripe_customer_id` lưu trên bảng `users`).
- [ ] Task 3: Database User Updates
- [ ] Subtask 3.1: Viết hàm DB handler gọi tới DB để ghi đè `subscription_status` = 'active', set `plan_id`, và cập nhật `token_balance` hàng tháng khi có trigger chu kỳ mới. Cập nhật `users.py` controller.
## Dev Notes
### Relevant Architecture Patterns & Constraints
- **Security Check:** Webhook API endpoint `MUST` parse raw body using `await request.body()`. Nếu FastAPI parse ra Pydantic Object TRƯỚC chữ ký signature thì thư viện Stripe auth sẽ báo lỗi văng Exception.
- **Race Condition in DB:** Do event `checkout.session.completed``customer.subscription.created` có thể call webhook cục bộ gần như đồng thời, phải code check Upsert (Ví dụ: set timestamp check updatedAt để tránh data đè lên nhau).
### Project Structure Notes
- Module thay đổi:
- `surfsense_backend/app/routes/stripe_routes.py`
- `surfsense_backend/app/db.py`
### References
- [Epic 5.3 - Webhook Sync]
## Dev Agent Record
### Agent Model Used
Antigravity Claude 3.5 Sonnet Engine
### File List
- `surfsense_backend/app/routes/stripe_routes.py`

View file

@ -0,0 +1,48 @@
# Story 5.4: Hệ thống Khóa Tác vụ dựa trên Hạn Mức (Usage Tracking & Rate Limit Enforcement)
Status: ready-for-dev
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
## Story
As a Kỹ sư Hệ thống,
I want những người dùng hết quota (vượt quá file upload hoặc số lượng tin nhắn) bị từ chối dịch vụ cho đến khi nâng cấp,
so that mô hình kinh doanh không bị lỗ do chi phí LLM và Storage, áp dụng theo FR13.
## Acceptance Criteria
1. Endpoint Upload (Document Parser) và Endpoint Chat (RAG AI) sẽ query Database để check `Subscription_Status``document_count`, `token_balance`.
2. Nếu Document count >= Limit hệ thống từ chối Upload và trả lỗi `402 Payment Required` hoặc `403`.
3. UI hiển thị Toast Error hoặc một Modal up-sell Upgrade to Pro.
## Tasks / Subtasks
- [ ] Task 1: Check Limits ở Route `/api/v1/documents`
- [ ] Subtask 1.1: Tạo function Utils `check_upload_quota()` query lấy Package Plan của JWT User. Đếm số object hiện có trong DB (Count records trong table `documents` nơi `user_id = X`).
- [ ] Subtask 1.2: Nếu đạt MAX_LIMIT (ví dụ 10 đối với FREE), Raise HTTPException 402/403.
- [ ] Task 2: Refine Frontend Validation
- [ ] Subtask 2.1: Ở component `DocumentUploader`, handle catch Error response `402`. Bật Toast thông báo "Bạn đã hết File Limit miễn phí".
## Dev Notes
### Relevant Architecture Patterns & Constraints
- Yêu cầu NFR Architecture: KHÔNG HARDCODE số file LIMIT vào trong code API mà phải load Enum hoặc Database row. Nên dùng một `config module` tĩnh hoặc Map Object dựa trên `plan_id` enum để check.
- Nếu User Plan là `PRO`, `MAX_LIMIT` là 100.
- Khúc check Chat Token Balance đã được cover một phần ở Story 3.5, nên Story 5.4 tập trung vào `File Upload Rate Limit``Chat Frequency Rate Limit` (tránh crawler/spam theo giờ).
### Project Structure Notes
- Module thay đổi:
- `surfsense_backend/app/routes/documents_routes.py` (hoặc endpoints xử lý Upload mới nhất).
- `surfsense_web/src/components/UploadDocument.tsx`
### References
- [Epic 5.4 - Quota Check]
## Dev Agent Record
### Agent Model Used
Antigravity Claude 3.5 Sonnet Engine
### File List
- `surfsense_backend/app/routes/documents_routes.py`

View file

@ -0,0 +1,73 @@
# generated: 2026-04-13T02:50:25+07:00
# last_updated: 2026-04-13T02:50:25+07:00
# project: SurfSense
# project_key: NOKEY
# tracking_system: file-system
# story_location: {project-root}/_bmad-output/implementation-artifacts
# STATUS DEFINITIONS:
# ==================
# Epic Status:
# - backlog: Epic not yet started
# - in-progress: Epic actively being worked on
# - done: All stories in epic completed
#
# Epic Status Transitions:
# - backlog → in-progress: Automatically when first story is created (via create-story)
# - in-progress → done: Manually when all stories reach 'done' status
#
# Story Status:
# - backlog: Story only exists in epic file
# - ready-for-dev: Story file created in stories folder
# - in-progress: Developer actively working on implementation
# - review: Ready for code review (via Dev's code-review workflow)
# - done: Story completed
#
# Retrospective Status:
# - optional: Can be completed but not required
# - done: Retrospective has been completed
#
# WORKFLOW NOTES:
# ===============
# - Epic transitions to 'in-progress' automatically when first story is created
# - Stories can be worked in parallel if team capacity allows
# - Developer typically creates next story after previous one is 'done' to incorporate learnings
# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended)
generated: 2026-04-13T02:50:25+07:00
last_updated: 2026-04-13T02:50:25+07:00
project: SurfSense
project_key: NOKEY
tracking_system: file-system
story_location: "{project-root}/_bmad-output/implementation-artifacts"
development_status:
epic-1: done
1-1-project-infrastructure-database-init: done
1-2-backend-auth-api-jwt: done
1-3-frontend-auth-ui: done
epic-1-retrospective: optional
epic-2: done
2-1-celery-worker-pdf-parser: done
2-2-upload-api-rate-limiting: done
2-3-knowledge-base-ui-micro-sync-indicators: done
2-4-delete-document-flow: done
epic-2-retrospective: optional
epic-3: in-progress
3-1-chat-session-api: done
3-2-rag-engine-sse-endpoint: done
3-3-chat-ui-sse-client: done
3-4-split-pane-layout-interactive-citation: done
3-5-model-selection-via-quota: backlog
epic-3-retrospective: optional
epic-4: done
4-1-chat-history-sync: done
4-2-graceful-degradation-offline-ui: done
4-3-global-network-sync-indicators: done
epic-4-retrospective: optional
epic-5: backlog
5-1-pricing-plan-selection-ui: backlog
5-2-stripe-payment-integration: backlog
5-3-stripe-webhook-sync: backlog
5-4-usage-tracking-rate-limit-enforcement: backlog
epic-5-retrospective: optional