feat: REST API Migration for Stateless Operations#390
Merged
Conversation
- Create Hono middleware that resolves :vaultId path parameter to VaultInfo - Validate vault ID format to prevent path traversal (REQ-NF-6) - Return 404 JSON error for unknown vaults (REQ-F-55) - Export helper functions for downstream route handlers - Add comprehensive test suite (25 tests) Implements: REQ-F-3, REQ-F-55, REQ-NF-6 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create error handler that maps FileBrowserError to HTTP status codes
- Return consistent { error: { code, message } } JSON format (REQ-NF-3)
- Map: PATH_TRAVERSAL→403, FILE/DIR_NOT_FOUND→404, VALIDATION→400
- Unknown errors return 500 with safe message (no stack traces)
- Log errors server-side with method, path, and context
- Add comprehensive test suite (21 tests)
Implements: REQ-F-55, REQ-F-56, REQ-F-57, REQ-F-58, REQ-F-59, REQ-NF-3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create route index with vault-scoped Hono router - Apply vault resolution middleware to /api/vaults/:vaultId/* routes - Register global error handler with app.onError() - CORS inherited from existing /api/* configuration - Add integration tests (15 tests) verifying middleware and error handling Implements: REQ-F-3, REQ-F-4 Depends on: TASK-001, TASK-002 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enhance meeting-store.ts with diagnostic/testing functions: - getAllActiveMeetings() for debugging visibility - clearAllMeetings() for test cleanup Add comprehensive unit tests covering: - Basic store operations (get, set, clear, has) - Entry count incrementing - Single meeting per vault enforcement - Meeting lifecycle scenarios - WebSocket reconnection simulation - Edge cases 31 tests passing, 65 assertions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create search-cache.ts module for REST API search efficiency: - Map<vaultId, CacheEntry> for vault-scoped caching - getOrCreateIndex(vaultId, vaultPath) with lazy initialization - LRU eviction when >10 vaults cached (configurable) - TTL-based invalidation (default 5 minutes) - Cache stats for monitoring Add REST-compatible search functions to search-handlers.ts: - searchFilesRest() for file name search - searchContentRest() for content search - getSnippetsRest() for context snippets - SearchResultWithTiming<T> interface 29 tests passing, 73 assertions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create frontend REST API infrastructure:
frontend/src/api/types.ts:
- ApiErrorResponse matching { error: { code, message } } format
- ApiError class with typed accessors and helper methods
- isApiErrorResponse() type guard
- ApiResult<T>, ApiRequestOptions, ApiClientConfig interfaces
frontend/src/api/client.ts:
- createApiClient() factory with dependency injection for fetch
- Methods: get(), post(), put(), patch(), delete(), request()
- Status code to ErrorCode mapping (404→FILE_NOT_FOUND, etc.)
- vaultPath() helper for building vault-scoped endpoints
- Handles AbortSignal for request cancellation
39 tests passing, 78 assertions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create REST endpoints for search operations: - GET /api/vaults/:vaultId/search/files?q= - File name search - GET /api/vaults/:vaultId/search/content?q= - Content search - GET /api/vaults/:vaultId/search/snippets?path=&q= - Context snippets Uses search-cache.ts for cached SearchIndexManager instances. 30 tests passing, 97 assertions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create REST endpoints for file browser operations: - GET /files?path= - Directory listing - POST /files - Create file - GET/PUT/PATCH/DELETE /files/:path - File operations - POST/DELETE /directories - Directory operations - GET /directories/:path/contents - Directory contents preview - POST /archive/:path/archive - Archive file/directory 51 tests passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create REST endpoints for note capture: - POST /capture - Capture text to daily note - GET /recent-notes - Get recent captured notes - GET /recent-activity - Get combined recent activity 26 tests passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create REST endpoints for home dashboard: - GET /goals - Get vault goals - GET /inspiration - Get inspiration (contextual + quote) - GET /tasks - Get all tasks - PATCH /tasks - Toggle task completion 25 tests passing (2 skipped - require SDK). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create REST endpoints for meeting management: - POST /meetings - Start a meeting - DELETE /meetings/current - Stop current meeting - GET /meetings/current - Get meeting state Uses meeting-store.ts for state persistence across requests. 20 tests passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create REST endpoints for vault configuration: - GET/PUT /pinned-assets - Manage pinned assets - PATCH /config - Update vault config - POST /setup - Setup vault - DELETE /health-issues/:issueId - Dismiss health issue 25 tests passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create REST endpoints for memory and session management: - GET/PUT /memory - Memory file operations - DELETE /sessions/:sessionId - Delete session Includes bug fix for memory file path resolution. 20 tests passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Import and mount all domain route modules: - File browser (files, directories, archive) - Capture and recent activity - Home dashboard (goals, inspiration, tasks) - Meetings - Search - Config - Memory and sessions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1 and Phase 2 complete (13 of 18 tasks, 72%) 357 tests across all REST API components Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create useFileBrowser hook for file operations via REST API: - listDirectory, readFile, writeFile, deleteFile - createFile, createDirectory, deleteDirectory - renameFile, moveFile Hook uses dependency injection for fetch (testable without mock.module). 42 tests cover all operations, error handling, and loading states. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create three React hooks for REST API operations: useCapture: captureNote, getRecentNotes, getRecentActivity useHome: getGoals, getInspiration, getTasks, toggleTask useSearch: searchFiles, searchContent, getSnippets All hooks use dependency injection for testable fetch. Reuses shared types from @memory-loop/shared. 61 tests across the three hooks. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 3 Frontend Migration complete: - TASK-014: File Browser Hooks (42 tests) - TASK-015: Domain Hooks (61 tests) 15 of 18 tasks complete (83%). 460 total tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove handlers for operations now served by REST: - File browser: list_directory, read_file, write_file, etc. - Capture: capture_note, get_recent_notes, get_recent_activity - Home: get_goals, get_inspiration, get_tasks, toggle_task - Search: search_files, search_content, get_snippets - Config: get_pinned_assets, set_pinned_assets, etc. - Memory: get_memory, save_memory - Session: delete_session, Meeting operations WebSocket now only handles: - Session establishment (select_vault, new_session, resume_session) - AI streaming (discussion_message, response_*, tool_*) - Interactive prompts (tool_permission_*, ask_user_question_*) - Pair writing (quick_action, advisory_action) - Extraction prompt operations - ping/pong keepalive Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comprehensive integration tests validating REST-only operation: - File browser without WebSocket (read, write, navigate) - Capture without WebSocket (POST note, verify response) - Search without WebSocket (files, content, snippets) - Error handling (404, 400, 403 responses) - Performance (<200ms file ops, <500ms search) - No select_vault bug (direct vault access works) - REQ-F-64: REST uses same business logic as WebSocket 29 tests, 138 assertions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove WebSocket message types now handled by REST API: - File browser: list_directory, read_file, write_file, etc. - Capture: capture_note, get_recent_notes, get_recent_activity - Home: get_goals, get_inspiration, get_tasks, toggle_task - Search: search_files, search_content, get_snippets - Config: get_pinned_assets, set_pinned_assets, etc. - Memory: get_memory, save_memory - Session: delete_session - Meeting: start_meeting, stop_meeting, get_meeting_state WebSocket protocol now only handles: - Session establishment (select_vault, new_session, resume_session) - AI streaming (discussion_message, response_*, tool_*) - Interactive prompts (tool_permission_*, ask_user_question_*) - Pair writing, extraction prompt operations - Health reports, ping/pong Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Additional hooks to complete the REST API migration: - useConfig: pinned assets, vault config, setup, health issues - useMeetings: start, stop, get meeting state - useMemory: get/save memory - useSessions: delete session Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update all components to use REST hooks instead of WebSocket: - App.tsx: useMeetings, useConfig hooks - BrowseMode.tsx: useFileBrowser, useSearch, useHome, useConfig - HomeView.tsx: useCapture, useHome, useSessions - MemoryEditor.tsx: useMemory hook - NoteCapture.tsx: useCapture, useMeetings - MoveDialog.tsx: useFileBrowser - VaultSelect.tsx: direct API calls for setup/config SessionContext simplified: removed handlers for migrated operations. useWebSocket: removed search methods (now REST-based). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Delete tests for WebSocket patterns that no longer exist: - BrowseMode test files (8 files) - MemoryEditor.test.tsx - NoteCapture.test.tsx - VaultSelect.test.tsx These tests relied on WebSocket message mocking which is no longer applicable after REST migration. New tests use REST hooks with dependency injection for fetch. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Delete handler files now replaced by REST routes: - browser-handlers.ts (replaced by routes/files.ts) - home-handlers.ts (replaced by routes/home.ts) - meeting-handlers.ts (replaced by routes/meetings.ts) Update handlers/index.ts to remove deleted exports. Update memory-handlers.ts and search-handlers.ts for REST usage. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All 18 tasks complete (100%). 489 total tests. Migration includes: - 30+ message types moved from WebSocket to REST - 8 REST hooks for frontend - 9 route files for backend - Protocol schemas cleaned up - Obsolete handlers and tests removed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
REST API calls should not wait for WebSocket connection - that was the whole point of the migration. Now data loads immediately when vault is available. Also properly resets data loading state when vault changes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Simplified the data loading effect to trigger on vault.id change. Added console logs for debugging. Removed ref-based tracking that was causing issues. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When options.fetch is undefined, spreading { fetch: undefined }
overwrites the default fetch with undefined, causing "n.fetch is not
a function" errors in production.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The effects were depending on the entire hook objects (fileBrowser, homeApi, configApi) which are new objects on every render. This caused infinite loops when effects triggered state changes. Fixed by destructuring the specific functions needed and using those in the dependency arrays instead. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The effect that fetches pinned assets was calling getPinnedAssets() but discarding the result. Now actually calls setPinnedAssets(paths) to populate the pinned files in the Recall tab. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete the REST API migration by removing WebSocket connections from components that no longer need them: - HomeView: Remove useWebSocket, select_vault effect (loads via REST) - NoteCapture: Remove useWebSocket, select_vault effect (submits via REST) - BrowseMode: Remove hasSessionReady gating, session_ready handler - File tree, pinned assets, and tasks now load immediately - WebSocket kept only for PairWritingMode passthrough Achieves spec criterion: "WebSocket is only required when entering Discussion mode." Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…VaultSelect Add 100 new tests covering key behaviors: - MemoryEditor: loading, size limits, save/reset, accessibility - NoteCapture: drafts, meeting mode, keyboard shortcuts - VaultSelect: vault list, selection, error states, session resume - BrowseMode: view modes, tree collapse, mobile overlay Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…seMode, NoteCapture, and VaultSelect components
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates 36 stateless WebSocket operations to REST API endpoints, resolving the
select_vaultrace condition and improving frontend testability.backend/src/routes/with vault resolution middleware and consistent error handlingChanges
Backend Routes Created
/api/vaults/:vaultId/files/*- File browser operations/api/vaults/:vaultId/capture- Note capture/api/vaults/:vaultId/goals,/inspiration,/tasks- Home dashboard/api/vaults/:vaultId/search/*- File and content search/api/vaults/:vaultId/meetings/*- Meeting management/api/vaults/:vaultId/config/*- Configuration/api/vaults/:vaultId/memory- Memory operations/api/vaults/:vaultId/sessions/:sessionId- Session managementFrontend Hooks Created
useFileBrowser- Directory listing, file CRUD, rename/moveuseCapture- Note capture, recent notes/activityuseHome- Goals, inspiration, tasksuseSearch- File search, content search, snippetsuseConfig- Pinned assets, vault config, health issuesuseMeetings- Meeting lifecycleuseMemory- Memory get/saveuseSessions- Session deletionProtocol Cleanup
Test plan
Closes #375
🤖 Generated with Claude Code