mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
Stories were written for a subscription SaaS model, but SurfSense is a self-hosted product with BYOK + optional PAYG page packs via Stripe. Key corrections: - Story 3.5: Not "remove BYOK + token billing" → actual gap is adding HTTP-layer quota pre-check before document upload enqueue - Story 5.1: Pricing UI already exists (Free/PAYG/Enterprise) → gap is wiring "Get Started" button to existing Stripe checkout endpoint - Story 5.2: mode=payment PAYG already works → needs verification/hardening not a subscription checkout rewrite - Story 5.3: Webhook already handles checkout.session.completed correctly → no subscription events needed, gap is idempotency test + purchase history UI - Story 5.4: PageLimitService + enforcement in tasks/connectors already exists → gap is HTTP-layer pre-check, quota UI indicator, and 402 frontend handling Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.9 KiB
4.9 KiB
Story 5.4: Enforce Page Quota tại HTTP API Layer & Frontend Feedback
Status: ready-for-dev
Context / Correction Note
⚠️ Story gốc bị sai một phần. Story gốc mô tả implement quota từ đầu (tạo
check_upload_quota(), v.v.). Thực tế, hệ thống quota đã tồn tại đầy đủ vớiPageLimitService, enforcement trong Celery tasks và tất cả connector indexers. Task thực tế chỉ là: (1) thêm check tại HTTP API layer trước khi enqueue task, (2) feedback rõ ràng ở Frontend, (3) hiển thị quota usage trong UI.
Story
As a Người dùng, I want nhận phản hồi ngay lập tức khi tôi hết page quota thay vì đợi task xử lý xong mới biết, so that tôi có thể mua thêm pages trước khi tiếp tục upload.
Actual Architecture (as-is)
Đã implement và đang hoạt động:
surfsense_backend/app/services/page_limit_service.py:PageLimitService.check_page_limit(user_id, estimated_pages)— raisesPageLimitExceededErrorPageLimitService.update_page_usage(user_id, pages_to_add)PageLimitService.get_page_usage(user_id)→(pages_used, pages_limit)PageLimitService.estimate_pages_before_processing(file_path)— ước tính từ file size/typePageLimitService.estimate_pages_from_metadata(filename, file_size)— pure function, không cần file
- Enforcement đã có trong:
surfsense_backend/app/tasks/celery_tasks/document_tasks.py— check trước khi xử lýsurfsense_backend/app/tasks/connector_indexers/google_drive_indexer.pysurfsense_backend/app/tasks/connector_indexers/onedrive_indexer.pysurfsense_backend/app/tasks/connector_indexers/dropbox_indexer.py- (và các connectors khác)
Còn thiếu:
- Check tại HTTP API layer (document upload route) — hiện tại task mới fail sau khi đã enqueue
- Frontend hiển thị
pages_used/pages_limit(quota indicator) - Frontend bắt lỗi 402 từ upload và hiển thị upgrade prompt
Acceptance Criteria
- Khi user upload document và estimated pages sẽ vượt
pages_limit, API trả về 402 ngay lập tức (không enqueue Celery task). - Frontend upload component bắt HTTP 402 và hiển thị toast: "Bạn đã hết page quota (X/Y pages). Mua thêm tại /pricing".
- Dashboard hiển thị quota indicator: "X / Y pages used" với progress bar.
- API
GET /api/v1/users/me(hoặc equivalent) trả vềpages_usedvàpages_limit.
Tasks / Subtasks
- Task 1: Thêm quota pre-check vào Document Upload HTTP route
- Subtask 1.1: Tìm document upload route (search
surfsense_backend/app/routes/cho endpoint nhận file upload). - Subtask 1.2: Inject
PageLimitService, gọiestimate_pages_from_metadata(filename, file_size)để ước tính. - Subtask 1.3: Gọi
check_page_limit(user_id, estimated_pages)— nếu raisesPageLimitExceededError, returnHTTPException(402, "Page quota exceeded. Purchase more pages at /pricing.").
- Subtask 1.1: Tìm document upload route (search
- Task 2: Expose quota info trên user endpoint
- Subtask 2.1: Đảm bảo
GET /api/v1/users/meresponse bao gồmpages_usedvàpages_limit(kiểm traUserReadschema trongdb.py).
- Subtask 2.1: Đảm bảo
- Task 3: Frontend quota indicator
- Subtask 3.1: Đọc
pages_used/pages_limittừ current user data (đã có trong Zero/DB sync hoặc API). - Subtask 3.2: Hiển thị progress bar nhỏ trong Dashboard sidebar hoặc header: "X / Y pages".
- Subtask 3.3: Khi
pages_used / pages_limit > 0.9, đổi màu indicator sang warning (amber).
- Subtask 3.1: Đọc
- Task 4: Frontend upload error handling
- Subtask 4.1: Trong document upload component, bắt HTTP 402 response.
- Subtask 4.2: Hiển thị toast/alert với link đến
/pricing.
Dev Notes
Không cần viết lại PageLimitService
PageLimitService đã có đầy đủ logic. Chỉ cần inject và gọi tại HTTP layer.
Pattern dùng trong Celery tasks (làm mẫu)
# Trong document_tasks.py
page_limit_service = PageLimitService(db_session)
await page_limit_service.check_page_limit(user_id, estimated_pages)
# → raises PageLimitExceededError nếu vượt quota
UserRead schema — kiểm tra xem đã expose pages_used chưa
# Tìm trong db.py hoặc schemas/
class UserRead(schemas.BaseUser[uuid.UUID]):
pages_limit: int
pages_used: int # ← check xem field này có trong schema không
References
surfsense_backend/app/services/page_limit_service.pysurfsense_backend/app/tasks/celery_tasks/document_tasks.py(xem cách dùng làm mẫu)surfsense_backend/app/db.py(UserRead schema / User model)surfsense_web/(document upload component — cần tìm)
Dev Agent Record
Agent Model Used
TBD
File List
surfsense_backend/app/routes/(document upload route)surfsense_backend/app/services/page_limit_service.py(đọc, không sửa)- Frontend upload + dashboard components