This commit is contained in:
API Test Bot 2026-03-11 19:32:08 +07:00
parent 8bc092e40e
commit f60ba3d01f
5 changed files with 885 additions and 0 deletions

View file

@ -0,0 +1,229 @@
# Story 1.0: Hệ thống Xác thực (Authentication System)
Status: ready-for-dev
## Story
**Là một** SurfSense user,
**Tôi muốn** đăng nhập vào extension với tài khoản SurfSense của tôi,
**Để** extension có thể đồng bộ settings, lịch sử chat, và truy cập backend APIs.
## Acceptance Criteria
### AC 1.0.1: User Login Flow
- **Given** user chưa đăng nhập vào extension
- **When** user click nút "Login" trong side panel header
- **Then** Chrome Identity API popup mở ra với tùy chọn Google OAuth
- **And** user hoàn tất quy trình OAuth
- **Then** extension nhận JWT token từ backend
- **And** extension chuyển hướng về side panel
- **And** avatar/email của user hiển thị trong header
**Error Scenario:**
- **Given** user đang trong quy trình OAuth
- **When** OAuth thất bại (user hủy hoặc lỗi mạng)
- **Then** extension hiển thị error toast "Login failed. Please try again."
- **And** user vẫn ở trạng thái chưa xác thực
### AC 1.0.2: JWT Token Management
- **Given** backend trả về JWT token (hết hạn sau 24 giờ - theo config hiện tại)
- **When** extension nhận được token
- **Then** extension lưu encrypted JWT trong Plasmo Storage
- **And** thời gian hết hạn của token được lưu
**Auto-Refresh:**
- **Given** JWT token còn < 1 giờ hết hạn
- **When** extension kiểm tra token expiry (mỗi 30 phút)
- **Then** extension gọi API `/auth/jwt/refresh`
- **And** extension cập nhật token đã lưu
**Logout:**
- **Given** user click "Logout" trong settings dropdown
- **When** hành động logout được kích hoạt
- **Then** extension xóa JWT khỏi Plasmo Storage
- **And** user chuyển hướng về màn hình welcome/login
### AC 1.0.3: Authenticated API Requests
- **Given** user đã đăng nhập (JWT đã lưu)
- **When** extension thực hiện API request
- **Then** request bao gồm header `Authorization: Bearer {JWT}`
- **And** backend xác thực JWT
- **And** request thành công với status 200
**Expired Token:**
- **Given** JWT token đã hết hạn
- **When** extension thực hiện API request
- **Then** backend trả về lỗi 401 Unauthorized
- **And** extension cố gắng auto-refresh
- **And** nếu refresh thành công, thử lại request ban đầu
- **And** nếu refresh thất bại, chuyển hướng user đến trang login
### AC 1.0.4: Offline Handling
- **Given** user đã đăng nhập trước đó
- **And** user mất kết nối internet
- **When** extension cố gắng kết nối backend
- **Then** extension hiển thị chỉ báo "Offline" trong header
- **And** extension cache trạng thái auth gần nhất
## Tasks / Subtasks
- [ ] Task 1: Chrome Identity API Integration (AC: 1.0.1)
- [ ] 1.1 Tạo `lib/auth/chrome-identity.ts` - wrapper cho Chrome Identity API
- [ ] 1.2 Implement `launchWebAuthFlow` với backend OAuth URL
- [ ] 1.3 Handle OAuth callback và extract JWT từ redirect URL
- [ ] 1.4 Xử lý các error cases (user cancel, network error)
- [ ] Task 2: JWT Token Manager (AC: 1.0.2)
- [ ] 2.1 Tạo `lib/auth/jwt-manager.ts` - quản lý JWT storage
- [ ] 2.2 Implement token encryption/decryption với Plasmo Storage
- [ ] 2.3 Implement token expiry checking và auto-refresh logic
- [ ] 2.4 Implement logout và clear token
- [ ] Task 3: Authenticated API Client (AC: 1.0.3)
- [ ] 3.1 Tạo `lib/auth/api-client.ts` - HTTP client với auth headers
- [ ] 3.2 Implement request interceptor để inject Bearer token
- [ ] 3.3 Implement 401 response handler với auto-retry
- [ ] 3.4 Implement offline detection và caching
- [ ] Task 4: Auth UI Components (AC: 1.0.1, 1.0.4)
- [ ] 4.1 Tạo `sidepanel/auth/LoginButton.tsx` - nút đăng nhập
- [ ] 4.2 Tạo `sidepanel/auth/UserProfile.tsx` - hiển thị avatar/email
- [ ] 4.3 Tạo `sidepanel/auth/AuthProvider.tsx` - React context cho auth state
- [ ] 4.4 Update `sidepanel/chat/ChatHeader.tsx` để integrate auth UI
- [ ] Task 5: Integration Testing
- [ ] 5.1 Test OAuth flow end-to-end
- [ ] 5.2 Test token refresh mechanism
- [ ] 5.3 Test offline mode behavior
- [ ] 5.4 Test logout flow
## Dev Notes
### Backend Authentication (ALREADY EXISTS)
Backend đã có đầy đủ authentication system sử dụng `fastapi-users`:
**Existing Endpoints:**
```
POST /auth/jwt/login - Email/password login
POST /auth/jwt/logout - Logout
GET /auth/google/authorize - Google OAuth initiation
GET /auth/google/callback - Google OAuth callback
POST /auth/register - User registration
GET /verify-token - Verify JWT validity
GET /users/me - Get current user info
```
**JWT Configuration (từ `surfsense_backend/app/users.py`):**
- Secret: `config.SECRET_KEY`
- Lifetime: 24 giờ (`3600 * 24` seconds)
- Transport: Bearer token
- OAuth redirect: `{NEXT_FRONTEND_URL}/auth/callback?token={token}`
### Extension Architecture Pattern
**Plasmo Storage (đã có trong project):**
```typescript
import { Storage } from "@plasmohq/storage";
const storage = new Storage({ area: "local" });
```
**Chrome Identity API:**
```typescript
chrome.identity.launchWebAuthFlow({
url: `${BACKEND_URL}/auth/google/authorize`,
interactive: true,
}, (redirectUrl) => {
// Extract JWT from redirect URL
const url = new URL(redirectUrl);
const token = url.searchParams.get('token');
});
```
### Critical Implementation Details
**1. OAuth Flow cho Extension:**
- Backend hiện redirect về `{NEXT_FRONTEND_URL}/auth/callback?token={token}`
- Extension cần sử dụng Chrome Identity API với custom redirect
- Có thể cần thêm endpoint mới hoặc config cho extension redirect
**2. Token Storage Security:**
- KHÔNG lưu plaintext JWT
- Sử dụng encryption trước khi lưu vào Plasmo Storage
- Xem xét sử dụng `chrome.storage.session` cho sensitive data
**3. CORS Configuration:**
Backend đã có CORS cho localhost, cần thêm extension origin:
```python
# surfsense_backend/app/app.py - line 74-81
allowed_origins.extend([
"chrome-extension://*", # Cần thêm
])
```
### Project Structure Notes
**Files cần tạo mới:**
```
surfsense_browser_extension/
├── lib/
│ └── auth/
│ ├── chrome-identity.ts # Chrome Identity API wrapper
│ ├── jwt-manager.ts # JWT storage & refresh
│ └── api-client.ts # Authenticated HTTP client
└── sidepanel/
└── auth/
├── LoginButton.tsx # Login UI component
├── UserProfile.tsx # User avatar/menu
└── AuthProvider.tsx # Auth context provider
```
**Files cần modify:**
- `sidepanel/chat/ChatHeader.tsx` - Thêm auth UI
- `sidepanel/index.tsx` - Wrap với AuthProvider
- `background/index.ts` - Handle auth messages (nếu cần)
### Dependencies
**Existing (không cần cài thêm):**
- `@plasmohq/storage` - Đã có
- `react`, `react-dom` - Đã có
- `lucide-react` - Đã có (cho icons)
**Backend Dependencies (đã có):**
- `fastapi-users` - Authentication framework
- `httpx-oauth` - Google OAuth client
- `python-jose` - JWT handling
### Security Considerations
1. **KHÔNG** lưu API keys trong extension code
2. Mã hóa JWT trước khi lưu vào storage
3. Sử dụng HTTPS cho tất cả API calls
4. Validate JWT signature trên backend (đã có)
5. Implement CSRF protection cho OAuth flow
### References
- [Source: surfsense_backend/app/users.py] - JWT strategy, OAuth config
- [Source: surfsense_backend/app/app.py#L91-160] - Auth routes registration
- [Source: _bmad-epics/epic-1-ai-powered-crypto-assistant.md#Story-1.0] - Full requirements
- [Source: _bmad-output/architecture-extension.md] - Extension architecture
- [Source: _bmad-output/architecture-backend.md] - Backend auth flow
## Dev Agent Record
### Agent Model Used
{{agent_model_name_version}}
### Completion Notes List
- Story created: 2026-02-04
- Backend auth system already exists and is fully functional
- Extension needs new auth layer to integrate with existing backend
- P0 BLOCKER - This story blocks all sync features (Settings, Chat, Capture)
### Debug Log References
(To be filled during implementation)
### File List
(To be filled during implementation)

View file

@ -0,0 +1,328 @@
# Story 1.6: Đồng bộ Cài đặt (Settings Sync) với Frontend
Status: ready-for-dev
## Story
**Là một** SurfSense user,
**Tôi muốn** extension sử dụng cùng model và search space như web dashboard,
**Để** tôi không phải cấu hình lại.
## Dependencies
- **REQUIRES:** Story 1.0 (Authentication System) - Must be completed first
- Extension must have valid JWT token to call backend APIs
## Acceptance Criteria
### AC 1.6.1: Hiển thị Dropdown Cài đặt
- **Given** user đã đăng nhập
- **When** user click icon ⚙️ trong header
- **Then** settings dropdown mở ra
- **And** dropdown hiển thị:
- Current model: "GPT-4 Turbo" (chỉ xem, bị mờ)
- Current search space: "Crypto Research" (chỉ xem, bị mờ)
- Links đến web dashboard:
- "🔗 Manage Connectors"
- "💬 View All Chats"
- "⚙️ Full Settings"
- Nút "🚪 Logout"
### AC 1.6.2: Đồng bộ Cài đặt khi Đăng nhập
- **Given** user hoàn tất đăng nhập
- **When** nhận được JWT token
- **Then** extension gọi `GET /api/v1/searchspaces` để lấy danh sách search spaces
- **And** extension gọi `GET /api/v1/search-spaces/{id}/llm-preferences` để lấy LLM config
- **And** settings được lưu trong Plasmo Storage
- **And** settings hiển thị trong dropdown
**Response Format (từ backend):**
```json
// GET /api/v1/searchspaces
[
{
"id": 1,
"name": "Crypto Research",
"description": "...",
"agent_llm_id": 0,
"document_summary_llm_id": 0
}
]
// GET /api/v1/search-spaces/{id}/llm-preferences
{
"agent_llm_id": 0,
"document_summary_llm_id": 0,
"agent_llm": {
"id": 0,
"name": "Auto (Load Balanced)",
"provider": "AUTO",
"model_name": "auto"
}
}
```
### AC 1.6.3: Tự động cập nhật Cài đặt
- **Given** user thay đổi model trên web dashboard
- **When** extension phát hiện thay đổi (qua polling)
- **Then** extension lấy settings đã cập nhật
- **And** dropdown phản ánh model mới
- **And** các cuộc chat tiếp theo sử dụng model mới
**Polling:**
- **Given** extension đang hoạt động
- **When** mỗi 5 phút
- **Then** extension polls `GET /api/v1/searchspaces` và LLM preferences
### AC 1.6.4: Search Space Selector
- **Given** user có nhiều search spaces
- **When** user click vào search space selector trong header
- **Then** dropdown hiển thị tất cả search spaces của user
- **And** user có thể chọn search space khác
- **And** extension lưu selection vào Plasmo Storage
- **And** các API calls tiếp theo sử dụng search_space_id mới
### AC 1.6.5: Offline Handling
- **Given** user đã đăng nhập và có settings đã cache
- **When** user mất kết nối internet
- **Then** extension sử dụng settings đã cache
- **And** hiển thị indicator "Using cached settings"
- **When** kết nối được khôi phục
- **Then** extension sync settings mới từ backend
## Tasks / Subtasks
- [ ] Task 1: Settings Service (AC: 1.6.2, 1.6.3)
- [ ] 1.1 Tạo `lib/settings/settings-service.ts` - API calls cho settings
- [ ] 1.2 Implement `fetchSearchSpaces()` - GET /api/v1/searchspaces
- [ ] 1.3 Implement `fetchLLMPreferences(spaceId)` - GET LLM config
- [ ] 1.4 Implement polling mechanism (5 phút interval)
- [ ] 1.5 Implement settings caching trong Plasmo Storage
- [ ] Task 2: Settings State Management (AC: 1.6.1, 1.6.4)
- [ ] 2.1 Tạo `lib/settings/settings-store.ts` - Zustand/Context store
- [ ] 2.2 Define settings types và interfaces
- [ ] 2.3 Implement search space selection logic
- [ ] 2.4 Implement settings sync on login
- [ ] Task 3: Settings UI Components (AC: 1.6.1, 1.6.4)
- [ ] 3.1 Update `sidepanel/chat/ChatHeader.tsx` - Integrate real settings
- [ ] 3.2 Tạo `sidepanel/settings/SettingsDropdown.tsx` - Enhanced dropdown
- [ ] 3.3 Tạo `sidepanel/settings/SearchSpaceSelector.tsx` - Space picker
- [ ] 3.4 Tạo `sidepanel/settings/ModelDisplay.tsx` - Read-only model info
- [ ] Task 4: Integration với Auth (AC: 1.6.2, 1.6.5)
- [ ] 4.1 Hook settings fetch vào auth flow (sau login thành công)
- [ ] 4.2 Implement offline detection và fallback
- [ ] 4.3 Clear settings on logout
- [ ] 4.4 Handle 401 errors (redirect to login)
- [ ] Task 5: Testing
- [ ] 5.1 Test settings sync sau login
- [ ] 5.2 Test polling mechanism
- [ ] 5.3 Test search space switching
- [ ] 5.4 Test offline mode với cached settings
## Dev Notes
### Backend APIs (ALREADY EXISTS)
Backend đã có đầy đủ APIs cho settings:
**Search Spaces:**
```
GET /api/v1/searchspaces - List all user's search spaces
POST /api/v1/searchspaces - Create new search space
GET /api/v1/searchspaces/{id} - Get single search space
PUT /api/v1/searchspaces/{id} - Update search space
DELETE /api/v1/searchspaces/{id} - Delete search space
```
**LLM Preferences:**
```
GET /api/v1/search-spaces/{id}/llm-preferences - Get LLM config for space
PUT /api/v1/search-spaces/{id}/llm-preferences - Update LLM config
```
**Global LLM Configs:**
```
GET /api/v1/global-new-llm-configs - List available LLM models
```
### Existing Extension Code
**ChatHeader.tsx (đã có UI cơ bản):**
- Search space selector dropdown (hardcoded data)
- Settings dropdown với menu items
- User avatar với logout
- Token search bar
**Cần update:**
- Replace hardcoded search spaces với real data từ API
- Add model display trong settings dropdown
- Connect logout button với auth service
### Data Types
**SearchSpace (từ backend):**
```typescript
interface SearchSpace {
id: number;
name: string;
description?: string;
user_id: string;
agent_llm_id: number;
document_summary_llm_id: number;
created_at: string;
}
```
**LLMPreferences (từ backend):**
```typescript
interface LLMPreferences {
agent_llm_id: number;
document_summary_llm_id: number;
agent_llm?: LLMConfig;
document_summary_llm?: LLMConfig;
}
interface LLMConfig {
id: number;
name: string;
provider: string;
model_name: string;
is_global?: boolean;
is_auto_mode?: boolean;
}
```
### Project Structure Notes
**Files cần tạo mới:**
```
surfsense_browser_extension/
├── lib/
│ └── settings/
│ ├── settings-service.ts # API calls
│ ├── settings-store.ts # State management
│ └── types.ts # TypeScript interfaces
└── sidepanel/
└── settings/
├── SettingsDropdown.tsx # Enhanced dropdown
├── SearchSpaceSelector.tsx # Space picker
└── ModelDisplay.tsx # Read-only model info
```
**Files cần modify:**
- `sidepanel/chat/ChatHeader.tsx` - Integrate real settings data
- `sidepanel/index.tsx` - Add SettingsProvider
- `lib/auth/api-client.ts` - Add settings endpoints (từ Story 1.0)
### Implementation Pattern
**Settings Service:**
```typescript
// lib/settings/settings-service.ts
import { apiClient } from '../auth/api-client';
export const settingsService = {
async fetchSearchSpaces(): Promise<SearchSpace[]> {
return apiClient.get('/api/v1/searchspaces');
},
async fetchLLMPreferences(spaceId: number): Promise<LLMPreferences> {
return apiClient.get(`/api/v1/search-spaces/${spaceId}/llm-preferences`);
},
async fetchGlobalLLMConfigs(): Promise<LLMConfig[]> {
return apiClient.get('/api/v1/global-new-llm-configs');
}
};
```
**Settings Store (Plasmo Storage):**
```typescript
// lib/settings/settings-store.ts
import { Storage } from "@plasmohq/storage";
const storage = new Storage({ area: "local" });
export const settingsStore = {
async saveSearchSpaces(spaces: SearchSpace[]) {
await storage.set('searchSpaces', spaces);
},
async getSearchSpaces(): Promise<SearchSpace[] | null> {
return storage.get('searchSpaces');
},
async saveSelectedSpaceId(id: number) {
await storage.set('selectedSearchSpaceId', id);
},
async getSelectedSpaceId(): Promise<number | null> {
return storage.get('selectedSearchSpaceId');
}
};
```
### Polling Implementation
```typescript
// Polling every 5 minutes
const POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes
useEffect(() => {
const pollSettings = async () => {
try {
const spaces = await settingsService.fetchSearchSpaces();
await settingsStore.saveSearchSpaces(spaces);
const selectedId = await settingsStore.getSelectedSpaceId();
if (selectedId) {
const prefs = await settingsService.fetchLLMPreferences(selectedId);
await settingsStore.saveLLMPreferences(prefs);
}
} catch (error) {
console.error('Settings poll failed:', error);
}
};
const interval = setInterval(pollSettings, POLLING_INTERVAL);
return () => clearInterval(interval);
}, []);
```
### Security Considerations
1. Settings API calls require valid JWT (handled by api-client)
2. Cache settings locally for offline access
3. Clear cached settings on logout
4. Handle 401 errors gracefully (redirect to login)
### References
- [Source: surfsense_backend/app/routes/search_spaces_routes.py] - Search space APIs
- [Source: surfsense_backend/app/routes/new_llm_config_routes.py] - LLM config APIs
- [Source: surfsense_browser_extension/sidepanel/chat/ChatHeader.tsx] - Existing UI
- [Source: _bmad-epics/epic-1-ai-powered-crypto-assistant.md#Story-1.6] - Full requirements
- [Source: _bmad-output/implementation-artifacts/1-0-authentication-system.md] - Auth dependency
## Dev Agent Record
### Agent Model Used
{{agent_model_name_version}}
### Completion Notes List
- Story created: 2026-02-04
- Backend APIs already exist and are fully functional
- Extension UI partially exists (ChatHeader.tsx has basic structure)
- DEPENDS ON Story 1.0 (Authentication) - must complete auth first
- Settings are read-only in extension (changes made via web dashboard)
### Debug Log References
(To be filled during implementation)
### File List
(To be filled during implementation)

View file

@ -0,0 +1,88 @@
# Sprint Status - SurfSense Crypto Co-Pilot
# Generated: 2026-02-04
#
# STATUS DEFINITIONS:
# - backlog: Story not yet started, waiting in queue
# - ready-for-dev: Story file created with full context, ready for development
# - in-progress: Development actively underway
# - review: Code complete, awaiting review
# - done: Story completed and verified
#
# EPIC STATUS:
# - backlog: Epic not started
# - in-progress: At least one story in progress
# - done: All stories completed
project: SurfSense 2.0 - Crypto Co-Pilot
sprint: Sprint 1 - Core Infrastructure
start_date: 2026-02-04
development_status:
# Epic 1: AI-Powered Crypto Assistant (Phase 1)
epic-1: in-progress
# Story 1.0 - Authentication System (P0 BLOCKER)
1-0-authentication-system: in-progress
# Stories 1.1-1.9 - Already completed (frontend only)
# These are marked done for frontend, but need backend integration
1-1-side-panel-architecture: done
1-2-ai-chat-interface: done
1-3-page-context-detection: done
1-4-dexscreener-integration: done
1-5-quick-capture: done
1-6-settings-sync: ready-for-dev # Depends on 1-0-authentication-system
1-7-universal-token-search: done
1-8-multi-page-token-detection: done
1-9-floating-quick-action: done
# Epic 1 Retrospective
epic-1-retrospective: backlog
# Epic 2: Smart Monitoring & Alerts (Phase 2)
epic-2: backlog
2-1-realtime-price-alerts: backlog
2-2-whale-activity-tracker: backlog
2-3-rug-pull-warning: backlog
epic-2-retrospective: backlog
# Epic 3: Trading Intelligence (Phase 3)
epic-3: backlog
3-1-one-click-token-analysis: backlog
3-2-smart-entry-exit: backlog
3-3-portfolio-tracker: backlog
epic-3-retrospective: backlog
# Epic 4: Content Creation & Productivity (Phase 4)
epic-4: backlog
4-1-chart-screenshot: backlog
4-2-ai-thread-generator: backlog
4-3-quick-actions-context-menu: done
4-4-smart-notifications: backlog
4-5-keyboard-shortcuts: done
epic-4-retrospective: backlog
# Priority Queue (next stories to work on)
priority_queue:
- 1-0-authentication-system # P0 BLOCKER - Must complete first
- 1-6-settings-sync # Depends on 1-0
- 2-1-realtime-price-alerts # Phase 2 start
# Blockers
blockers:
- id: BLOCK-001
description: "Backend authentication APIs need extension-specific OAuth redirect"
affects: ["1-0-authentication-system"]
status: open
- id: BLOCK-002
description: "DexScreener API integration needed for real data"
affects: ["2-1-realtime-price-alerts", "2-2-whale-activity-tracker"]
status: open
# Notes
notes:
- "Frontend UI for all epics is 100% complete"
- "Backend APIs are the main blocker"
- "Story 1.0 (Auth) is critical path - blocks all sync features"

143
surfsense_backend/nohup.out Normal file
View file

@ -0,0 +1,143 @@
INFO: Will watch for changes in these directories: ['/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend']
INFO: Uvicorn running on http://0.0.0.0:3998 (Press CTRL+C to quit)
INFO: Started reloader process [6491] using WatchFiles
/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/chonkie/chunker/code.py:82: UserWarning: The language is set to `auto`. This would adversely affect the performance of the chunker. Consider setting the `language` parameter to a specific language to improve performance.
warnings.warn("The language is set to `auto`. This would adversely affect the performance of the chunker. " +
INFO: Started server process [6495]
INFO: Waiting for application startup.
ERROR: Traceback (most recent call last):
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 694, in lifespan
async with self.lifespan_context(app) as maybe_state:
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan
async with original_context(app) as maybe_original_state:
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan
async with original_context(app) as maybe_original_state:
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan
async with original_context(app) as maybe_original_state:
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan
async with original_context(app) as maybe_original_state:
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan
async with original_context(app) as maybe_original_state:
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan
async with original_context(app) as maybe_original_state:
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/app/app.py", line 23, in lifespan
await create_db_and_tables()
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/app/db.py", line 1386, in create_db_and_tables
async with engine.begin() as conn:
^^^^^^^^^^^^^^
File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__
return await anext(self.gen)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/engine.py", line 1066, in begin
async with conn:
^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/base.py", line 121, in __aenter__
return await self.start(is_ctxmanager=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/engine.py", line 274, in start
await greenlet_spawn(self.sync_engine.connect)
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 201, in greenlet_spawn
result = context.throw(*sys.exc_info())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3273, in connect
return self._connection_cls(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 145, in __init__
self._dbapi_connection = engine.raw_connection()
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3297, in raw_connection
return self.pool.connect()
^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 449, in connect
return _ConnectionFairy._checkout(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 1264, in _checkout
fairy = _ConnectionRecord.checkout(pool)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 713, in checkout
rec = pool._do_get()
^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 179, in _do_get
with util.safe_reraise():
^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__
raise exc_value.with_traceback(exc_tb)
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 177, in _do_get
return self._create_connection()
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 390, in _create_connection
return _ConnectionRecord(self)
^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 675, in __init__
self.__connect()
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 901, in __connect
with util.safe_reraise():
^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__
raise exc_value.with_traceback(exc_tb)
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 897, in __connect
self.dbapi_connection = connection = pool._invoke_creator(self)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/create.py", line 646, in connect
return dialect.connect(*cargs, **cparams)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 625, in connect
return self.loaded_dbapi.connect(*cargs, **cparams) # type: ignore[no-any-return] # NOQA: E501
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 961, in connect
await_only(creator_fn(*arg, **kw)),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only
return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn
value = await result
^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connection.py", line 2421, in connect
return await connect_utils._connect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1075, in _connect
raise last_error or exceptions.TargetServerAttributeNotMatched(
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1049, in _connect
conn = await _connect_addr(
^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 882, in _connect_addr
return await __connect_addr(params, False, *args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 931, in __connect_addr
tr, pr = await connector
^^^^^^^^^^^^^^^
File "uvloop/loop.pyx", line 2043, in create_connection
File "uvloop/loop.pyx", line 2020, in uvloop.loop.Loop.create_connection
ConnectionRefusedError: [Errno 61] Connection refused
ERROR: Application startup failed. Exiting.
INFO: Stopping reloader process [6491]

97
surfsense_web/nohup.out Normal file
View file

@ -0,0 +1,97 @@
> surfsense_web@0.0.12 dev /Users/mac_1/Documents/GitHub/SurfSense/surfsense_web
> next dev --turbopack -p 3999
▲ Next.js 16.1.0 (Turbopack)
- Local: http://localhost:3999
- Network: http://10.56.57.248:3999
- Environments: .env
✓ Starting...
[MDX] generated files in 21.16537500000004ms
[MDX] started dev server
✓ Ready in 2.3s
GET / 200 in 1750ms (compile: 1438ms, render: 313ms)
GET / 200 in 71ms (compile: 5ms, render: 66ms)
GET /dashboard/%7Bid%7D/new-chat 200 in 1979ms (compile: 1630ms, render: 349ms)
Error: ENVIRONMENT_FALLBACK: There is no `timeZone` configured, this can lead to markup mismatches caused by environment differences. Consider adding a global default: https://next-intl.dev/docs/configuration#time-zone
at LoginContent (app/(home)/login/page.tsx:17:27)
15 |
16 | function LoginContent() {
> 17 | const t = useTranslations("auth");
| ^
18 | const tCommon = useTranslations("common");
19 | const [authType, setAuthType] = useState<string | null>(null);
20 | const [isLoading, setIsLoading] = useState(true); {
code: 'ENVIRONMENT_FALLBACK',
originalMessage: 'There is no `timeZone` configured, this can lead to markup mismatches caused by environment differences. Consider adding a global default: https://next-intl.dev/docs/configuration#time-zone'
}
GET /login 200 in 196ms (compile: 77ms, render: 119ms)
GET / 200 in 83ms (compile: 7ms, render: 76ms)
GET / 200 in 61ms (compile: 6ms, render: 55ms)
GET /login 200 in 56ms (compile: 8ms, render: 48ms)
GET / 200 in 90ms (compile: 21ms, render: 69ms)
GET /login 200 in 53ms (compile: 20ms, render: 34ms)
GET /login 200 in 79ms (compile: 8ms, render: 71ms)
GET /auth/callback?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxOTUxYzAxMC00MzZmLTQ2MzYtODljYS01ZDg2ZjU3OTUxZGYiLCJhdWQiOlsiZmFzdGFwaS11c2VyczphdXRoIl0sImV4cCI6MTc3MDg3MDY3M30.O28yYMtWQuLeYdjEn2SpHGBSEzp8gzhyCnNTY4deQF4 200 in 59ms (compile: 32ms, render: 27ms)
GET /dashboard/%7Bid%7D/new-chat 200 in 64ms (compile: 11ms, render: 53ms)
GET /dashboard/%7Bid%7D/new-chat 200 in 60ms (compile: 11ms, render: 49ms)
GET /dashboard/%7Bid%7D/crypto 200 in 568ms (compile: 544ms, render: 24ms)
GET /dashboard/%7Bid%7D/new-chat 200 in 33ms (compile: 11ms, render: 23ms)
GET /dashboard/%7Bid%7D/new-chat?query=Analyze+BULLA 200 in 25ms (compile: 7ms, render: 18ms)
GET / 200 in 75ms (compile: 5ms, render: 70ms)
GET /login 200 in 53ms (compile: 6ms, render: 47ms)
GET /auth/callback?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxOTUxYzAxMC00MzZmLTQ2MzYtODljYS01ZDg2ZjU3OTUxZGYiLCJhdWQiOlsiZmFzdGFwaS11c2VyczphdXRoIl0sImV4cCI6MTc3MDg3MTQxMn0.HscRbBjnqK86Bppg8IFq5OMgxOJppOosPXKtFJjQ2X0 200 in 28ms (compile: 6ms, render: 22ms)
GET /dashboard 200 in 233ms (compile: 28ms, render: 205ms)
GET /dashboard/7/new-chat 200 in 33ms (compile: 9ms, render: 24ms)
GET /dashboard/7/documents 200 in 784ms (compile: 757ms, render: 27ms)
GET /dashboard/7/documents 200 in 21ms (compile: 7ms, render: 15ms)
GET /dashboard/7/new-chat 200 in 61ms (compile: 11ms, render: 50ms)
GET /dashboard/7/new-chat 200 in 32ms (compile: 10ms, render: 22ms)
GET /dashboard/7/new-chat/19 200 in 29ms (compile: 8ms, render: 22ms)
GET /dashboard/7/new-chat/19 200 in 42ms (compile: 16ms, render: 27ms)
GET /dashboard/7/crypto 200 in 26ms (compile: 8ms, render: 18ms)
GET /dashboard/7/crypto 200 in 31ms (compile: 13ms, render: 18ms)
GET /dashboard/7/crypto 200 in 20ms (compile: 5ms, render: 14ms)
GET /dashboard/7/crypto 200 in 16ms (compile: 3ms, render: 13ms)
GET /dashboard/7/crypto 200 in 20ms (compile: 3ms, render: 17ms)
GET /dashboard/7/new-chat/19 200 in 65ms (compile: 13ms, render: 52ms)
GET /dashboard/7/documents 200 in 31ms (compile: 9ms, render: 22ms)
GET /dashboard/7/documents 200 in 40ms (compile: 19ms, render: 21ms)
GET /dashboard/7/crypto 200 in 28ms (compile: 8ms, render: 20ms)
GET /dashboard/7/new-chat/19 200 in 32ms (compile: 10ms, render: 21ms)
GET /dashboard/7/documents 200 in 28ms (compile: 10ms, render: 17ms)
GET /dashboard/7/crypto 200 in 35ms (compile: 12ms, render: 22ms)
GET /dashboard/7/logs 200 in 490ms (compile: 470ms, render: 20ms)
GET /dashboard/7 200 in 458ms (compile: 412ms, render: 46ms)
GET /dashboard/7/new-chat 200 in 35ms (compile: 8ms, render: 27ms)
GET /dashboard/%7Bid%7D/new-chat?query=Analyze+BULLA 200 in 115ms (compile: 33ms, render: 82ms)
GET / 200 in 76ms (compile: 7ms, render: 70ms)
GET /dashboard/7/new-chat/19 200 in 104ms (compile: 13ms, render: 91ms)
GET /login 200 in 55ms (compile: 6ms, render: 49ms)
GET /dashboard/7/new-chat 200 in 57ms (compile: 18ms, render: 39ms)
GET /login 200 in 51ms (compile: 4ms, render: 48ms)
GET /login 200 in 87ms (compile: 34ms, render: 54ms)
[MDX] closing dev server
Downloading swc package @next/swc-wasm-nodejs... to /Users/mac_1/Library/Caches/next-swc
npm warn Unknown env config "network-timeout". This will stop working in the next major version of npm.
npm warn Unknown env config "allow-build-scripts". This will stop working in the next major version of npm.
npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm.
npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm.
npm warn Unknown env config "_windsurf-registry". This will stop working in the next major version of npm.
npm warn Unknown env config "enable-pre-post-scripts". This will stop working in the next major version of npm.
npm warn Unknown env config "store-dir". This will stop working in the next major version of npm.
npm warn Unknown env config "cache-dir". This will stop working in the next major version of npm.
⚠ Attempted to load @next/swc-darwin-arm64, but an error occurred: dlopen(/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node, 0x0001): tried: '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' (code signature in <DEA08FB5-0F64-35DA-947E-EADD3218E146> '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' not valid for use in process: library load denied by system policy), '/System/Volumes/Preboot/Cryptexes/OS/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' (no such file), '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' (code signature in <DEA08FB5-0F64-35DA-947E-EADD3218E146> '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' not valid for use in process: library load denied by system policy)
⚠ TypeError: fetch failed
at ignore-listed frames {
[cause]: Error: getaddrinfo ENOTFOUND registry.npmjs.org
at ignore-listed frames {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'registry.npmjs.org'
}
}
Failed to load SWC binary for darwin/arm64, see more info here: https://nextjs.org/docs/messages/failed-loading-swc
[?25h