Enable a single LightRAG server instance to serve multiple isolated workspaces via HTTP header-based routing. This allows multi-tenant SaaS deployments where each tenant's data is completely isolated. Key features: - Header-based workspace routing (LIGHTRAG-WORKSPACE, X-Workspace-ID fallback) - Process-local pool of LightRAG instances with LRU eviction - FastAPI dependency (get_rag) for workspace resolution per request - Full backward compatibility - existing deployments work unchanged - Strict multi-tenant mode option (LIGHTRAG_ALLOW_DEFAULT_WORKSPACE=false) - Configurable pool size (LIGHTRAG_MAX_WORKSPACES_IN_POOL) - Graceful shutdown with workspace finalization Configuration: - LIGHTRAG_DEFAULT_WORKSPACE: Default workspace (falls back to WORKSPACE) - LIGHTRAG_ALLOW_DEFAULT_WORKSPACE: Require explicit header when false - LIGHTRAG_MAX_WORKSPACES_IN_POOL: Max concurrent workspace instances (default: 50) Files: - New: lightrag/api/workspace_manager.py (core multi-workspace module) - New: tests/test_multi_workspace_server.py (17 unit tests) - New: render.yaml (Render deployment blueprint) - Modified: All route files to use get_rag dependency - Updated: README.md, env.example with documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
312 lines
13 KiB
Markdown
312 lines
13 KiB
Markdown
# Tasks: Multi-Workspace Server Support
|
|
|
|
**Input**: Design documents from `/specs/001-multi-workspace-server/`
|
|
**Prerequisites**: plan.md ✅, spec.md ✅, research.md ✅, data-model.md ✅, contracts/ ✅
|
|
|
|
**Tests**: Required per SC-007 ("All multi-workspace functionality is covered by automated tests demonstrating isolation")
|
|
|
|
**Organization**: Tasks are grouped by user story to enable independent implementation and testing.
|
|
|
|
## Format: `[ID] [P?] [Story] Description`
|
|
|
|
- **[P]**: Can run in parallel (different files, no dependencies)
|
|
- **[Story]**: Which user story this task belongs to (US1, US2, US3, US4, US5)
|
|
- Include exact file paths in descriptions
|
|
|
|
## Path Conventions
|
|
|
|
Based on plan.md structure:
|
|
- **Source**: `lightrag/api/` for API server code
|
|
- **Tests**: `tests/` at repository root
|
|
- **Config**: `lightrag/api/config.py`
|
|
|
|
---
|
|
|
|
## Phase 1: Setup
|
|
|
|
**Purpose**: Create new module and configuration infrastructure
|
|
|
|
- [x] T001 Create workspace_manager.py module skeleton in lightrag/api/workspace_manager.py
|
|
- [x] T002 [P] Add multi-workspace configuration options to lightrag/api/config.py
|
|
- [x] T003 [P] Create test file skeleton in tests/test_multi_workspace_server.py
|
|
|
|
---
|
|
|
|
## Phase 2: Foundational (Core Infrastructure)
|
|
|
|
**Purpose**: WorkspacePool and workspace resolution - MUST complete before ANY user story can be implemented
|
|
|
|
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
|
|
|
|
- [x] T004 Implement WorkspaceConfig dataclass in lightrag/api/workspace_manager.py
|
|
- [x] T005 Implement workspace identifier validation (regex, length) in lightrag/api/workspace_manager.py
|
|
- [x] T006 Implement WorkspacePool class with asyncio.Lock in lightrag/api/workspace_manager.py
|
|
- [x] T007 Implement get_lightrag_for_workspace() async helper in lightrag/api/workspace_manager.py
|
|
- [x] T008 Implement LRU tracking in WorkspacePool in lightrag/api/workspace_manager.py
|
|
- [x] T009 Implement workspace eviction logic in WorkspacePool in lightrag/api/workspace_manager.py
|
|
- [x] T010 Implement get_workspace_from_request() header extraction in lightrag/api/workspace_manager.py
|
|
- [x] T011 Implement get_rag FastAPI dependency in lightrag/api/workspace_manager.py
|
|
- [x] T012 Add workspace logging (non-sensitive) in lightrag/api/workspace_manager.py
|
|
- [x] T013 [P] Add unit tests for workspace validation in tests/test_multi_workspace_server.py
|
|
- [x] T014 [P] Add unit tests for WorkspacePool in tests/test_multi_workspace_server.py
|
|
|
|
**Checkpoint**: Foundation ready - WorkspacePool and dependency available for route integration
|
|
|
|
---
|
|
|
|
## Phase 3: User Story 1+2 - Tenant Isolation & Header Routing (Priority: P1) 🎯 MVP
|
|
|
|
**Goal**: Enable workspace isolation via HTTP headers - the core multi-tenant capability
|
|
|
|
**Independent Test**: Ingest document in Tenant A, query from Tenant B, verify isolation
|
|
|
|
> Note: US1 (isolation) and US2 (routing) are combined because routing is required to test isolation
|
|
|
|
### Tests for User Story 1+2
|
|
|
|
- [ ] T015 [P] [US1] Add isolation test: ingest in workspace A, query from workspace B returns nothing in tests/test_multi_workspace_server.py
|
|
- [ ] T016 [P] [US1] Add isolation test: query from workspace A returns own documents in tests/test_multi_workspace_server.py
|
|
- [ ] T017 [P] [US2] Add routing test: LIGHTRAG-WORKSPACE header routes correctly in tests/test_multi_workspace_server.py
|
|
- [ ] T018 [P] [US2] Add routing test: X-Workspace-ID fallback works in tests/test_multi_workspace_server.py
|
|
- [ ] T019 [P] [US2] Add routing test: LIGHTRAG-WORKSPACE takes precedence over X-Workspace-ID in tests/test_multi_workspace_server.py
|
|
|
|
### Implementation for User Story 1+2
|
|
|
|
- [x] T020 [US1] Refactor create_document_routes() to accept workspace dependency in lightrag/api/routers/document_routes.py
|
|
- [x] T021 [US1] Update document upload endpoints to use workspace-resolved RAG in lightrag/api/routers/document_routes.py
|
|
- [x] T022 [US1] Update document scan endpoints to use workspace-resolved RAG in lightrag/api/routers/document_routes.py
|
|
- [x] T023 [US2] Refactor create_query_routes() to accept workspace dependency in lightrag/api/routers/query_routes.py
|
|
- [x] T024 [US2] Update query endpoints to use workspace-resolved RAG in lightrag/api/routers/query_routes.py
|
|
- [x] T025 [US2] Update streaming query endpoint to use workspace-resolved RAG in lightrag/api/routers/query_routes.py
|
|
- [x] T026 [P] [US1] Refactor create_graph_routes() to use workspace dependency in lightrag/api/routers/graph_routes.py
|
|
- [x] T027 [P] [US2] Refactor OllamaAPI class to use workspace dependency in lightrag/api/routers/ollama_api.py
|
|
- [x] T028 [US1] Integrate workspace pool initialization in create_app() in lightrag/api/lightrag_server.py
|
|
- [x] T029 [US2] Wire workspace dependency into router registration in lightrag/api/lightrag_server.py
|
|
- [x] T030 [US1] Add workspace identifier to request logging in lightrag/api/lightrag_server.py
|
|
|
|
**Checkpoint**: Multi-workspace routing and isolation functional - MVP complete ✅
|
|
|
|
---
|
|
|
|
## Phase 4: User Story 3 - Backward Compatible Single-Workspace Mode (Priority: P2)
|
|
|
|
**Goal**: Existing deployments continue working without any configuration changes
|
|
|
|
**Independent Test**: Deploy new version with existing config, verify all functionality unchanged
|
|
|
|
### Tests for User Story 3
|
|
|
|
- [ ] T031 [P] [US3] Add backward compat test: no header uses WORKSPACE env var in tests/test_multi_workspace_server.py
|
|
- [ ] T032 [P] [US3] Add backward compat test: existing routes unchanged in tests/test_multi_workspace_server.py
|
|
- [ ] T033 [P] [US3] Add backward compat test: response formats unchanged in tests/test_multi_workspace_server.py
|
|
|
|
### Implementation for User Story 3
|
|
|
|
- [x] T034 [US3] Implement WORKSPACE env var fallback for default workspace in lightrag/api/config.py
|
|
- [x] T035 [US3] Implement LIGHTRAG_DEFAULT_WORKSPACE with WORKSPACE fallback in lightrag/api/workspace_manager.py
|
|
- [x] T036 [US3] Ensure default workspace is used when no header present in lightrag/api/workspace_manager.py
|
|
- [x] T037 [US3] Verify auth dependency runs before workspace resolution in lightrag/api/workspace_manager.py
|
|
|
|
**Checkpoint**: Existing single-workspace deployments work unchanged
|
|
|
|
---
|
|
|
|
## Phase 5: User Story 4 - Configurable Missing Header Behavior (Priority: P2)
|
|
|
|
**Goal**: Allow strict multi-tenant mode that rejects requests without workspace headers
|
|
|
|
**Independent Test**: Set LIGHTRAG_ALLOW_DEFAULT_WORKSPACE=false, send request without header, verify 400 error
|
|
|
|
### Tests for User Story 4
|
|
|
|
- [ ] T038 [P] [US4] Add strict mode test: missing header returns 400 when default disabled in tests/test_multi_workspace_server.py
|
|
- [ ] T039 [P] [US4] Add strict mode test: error message clearly indicates missing header in tests/test_multi_workspace_server.py
|
|
- [ ] T040 [P] [US4] Add permissive mode test: missing header uses default when enabled in tests/test_multi_workspace_server.py
|
|
|
|
### Implementation for User Story 4
|
|
|
|
- [x] T041 [US4] Add LIGHTRAG_ALLOW_DEFAULT_WORKSPACE config option in lightrag/api/config.py
|
|
- [x] T042 [US4] Implement missing header rejection when default disabled in lightrag/api/workspace_manager.py
|
|
- [x] T043 [US4] Return clear 400 error with message for missing workspace header in lightrag/api/workspace_manager.py
|
|
- [x] T044 [US4] Add invalid workspace identifier 400 error handling in lightrag/api/workspace_manager.py
|
|
|
|
**Checkpoint**: Strict multi-tenant mode available for security-conscious deployments
|
|
|
|
---
|
|
|
|
## Phase 6: User Story 5 - Workspace Instance Management (Priority: P3)
|
|
|
|
**Goal**: Efficient memory management with configurable pool size and LRU eviction
|
|
|
|
**Independent Test**: Configure max pool size, create more workspaces than limit, verify LRU eviction
|
|
|
|
### Tests for User Story 5
|
|
|
|
- [x] T045 [P] [US5] Add pool test: new workspace initializes on first request in tests/test_multi_workspace_server.py
|
|
- [x] T046 [P] [US5] Add pool test: LRU eviction when pool full in tests/test_multi_workspace_server.py
|
|
- [x] T047 [P] [US5] Add pool test: concurrent requests for same new workspace share initialization in tests/test_multi_workspace_server.py
|
|
- [x] T048 [P] [US5] Add pool test: LIGHTRAG_MAX_WORKSPACES_IN_POOL config respected in tests/test_multi_workspace_server.py
|
|
|
|
### Implementation for User Story 5
|
|
|
|
- [x] T049 [US5] Add LIGHTRAG_MAX_WORKSPACES_IN_POOL config option in lightrag/api/config.py
|
|
- [x] T050 [US5] Implement finalize_storages() call on eviction in lightrag/api/workspace_manager.py
|
|
- [x] T051 [US5] Add pool finalize_all() for graceful shutdown in lightrag/api/workspace_manager.py
|
|
- [x] T052 [US5] Wire pool finalize_all() into lifespan shutdown in lightrag/api/lightrag_server.py
|
|
- [x] T053 [US5] Add workspace initialization timing logs in lightrag/api/workspace_manager.py
|
|
|
|
**Checkpoint**: Memory management and pool eviction functional for large-scale deployments
|
|
|
|
---
|
|
|
|
## Phase 7: Polish & Cross-Cutting Concerns
|
|
|
|
**Purpose**: Documentation, cleanup, and validation
|
|
|
|
- [x] T054 [P] Update lightrag/api/README.md with multi-workspace section
|
|
- [x] T055 [P] Add env.example entries for new configuration options
|
|
- [x] T056 [P] Add type hints and docstrings to workspace_manager.py in lightrag/api/workspace_manager.py
|
|
- [x] T057 Run all tests and verify isolation in tests/
|
|
- [ ] T058 Run quickstart.md validation scenarios manually
|
|
- [x] T059 Update conftest.py with multi-workspace test fixtures in tests/conftest.py
|
|
|
|
---
|
|
|
|
## Dependencies & Execution Order
|
|
|
|
### Phase Dependencies
|
|
|
|
```
|
|
Phase 1: Setup
|
|
│
|
|
▼
|
|
Phase 2: Foundational ◄─── BLOCKS ALL USER STORIES
|
|
│
|
|
├─────────────────────────────────────────┐
|
|
▼ ▼
|
|
Phase 3: US1+2 (P1) Can start in parallel
|
|
│ after Phase 2
|
|
▼
|
|
Phase 4: US3 (P2) ◄─── Depends on US1+2 for route integration
|
|
│
|
|
▼
|
|
Phase 5: US4 (P2) ◄─── Depends on US3 for default workspace logic
|
|
│
|
|
▼
|
|
Phase 6: US5 (P3) ◄─── Can start after Phase 2, but sequential for pool logic
|
|
│
|
|
▼
|
|
Phase 7: Polish ◄─── After all user stories
|
|
```
|
|
|
|
### User Story Dependencies
|
|
|
|
| Story | Can Start After | Dependencies |
|
|
|-------|-----------------|--------------|
|
|
| US1+2 | Phase 2 (Foundational) | WorkspacePool, get_rag dependency |
|
|
| US3 | US1+2 | Routes must use workspace dependency |
|
|
| US4 | US3 | Default workspace logic must exist |
|
|
| US5 | Phase 2 | Pool must exist, can parallel with US1-4 |
|
|
|
|
### Within Each User Story
|
|
|
|
1. Tests written FIRST (marked [P] for parallel)
|
|
2. Verify tests FAIL before implementation
|
|
3. Implementation tasks in dependency order
|
|
4. Story complete when checkpoint passes
|
|
|
|
### Parallel Opportunities
|
|
|
|
**Phase 1 (Setup)**:
|
|
- T002 and T003 can run in parallel
|
|
|
|
**Phase 2 (Foundational)**:
|
|
- T013 and T014 (tests) can run in parallel after T004-T012
|
|
|
|
**Phase 3 (US1+2)**:
|
|
- T015-T019 (all tests) can run in parallel
|
|
- T026 and T027 (graph and ollama routes) can run in parallel
|
|
|
|
**Phase 4-6**:
|
|
- All test tasks within each phase can run in parallel
|
|
|
|
**Phase 7 (Polish)**:
|
|
- T054, T055, T056 can run in parallel
|
|
|
|
---
|
|
|
|
## Parallel Example: User Story 1+2 Tests
|
|
|
|
```bash
|
|
# Launch all US1+2 tests together:
|
|
Task: T015 - isolation test: ingest in workspace A, query from workspace B
|
|
Task: T016 - isolation test: query from workspace A returns own documents
|
|
Task: T017 - routing test: LIGHTRAG-WORKSPACE header routes correctly
|
|
Task: T018 - routing test: X-Workspace-ID fallback works
|
|
Task: T019 - routing test: LIGHTRAG-WORKSPACE takes precedence
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Strategy
|
|
|
|
### MVP First (User Stories 1+2 Only)
|
|
|
|
1. Complete Phase 1: Setup (T001-T003)
|
|
2. Complete Phase 2: Foundational (T004-T014)
|
|
3. Complete Phase 3: US1+2 (T015-T030)
|
|
4. **STOP and VALIDATE**: Test multi-workspace isolation independently
|
|
5. Deploy/demo if ready - this is the core value
|
|
|
|
### Incremental Delivery
|
|
|
|
1. Setup + Foundational → Infrastructure ready
|
|
2. Add US1+2 → Test isolation → Deploy (MVP!)
|
|
3. Add US3 → Test backward compat → Deploy
|
|
4. Add US4 → Test strict mode → Deploy
|
|
5. Add US5 → Test pool management → Deploy
|
|
6. Polish → Full release
|
|
|
|
### Recommended Order (Single Developer)
|
|
|
|
```
|
|
T001 → T002 → T003 (Setup)
|
|
T004 → T005 → T006 → T007 → T008 → T009 → T010 → T011 → T012 (Foundational)
|
|
T013 + T014 (parallel tests)
|
|
T015-T019 (parallel US1+2 tests - write first, expect failures)
|
|
T020 → T021 → T022 → T023 → T024 → T025 (routes)
|
|
T026 + T027 (parallel graph/ollama)
|
|
T028 → T029 → T030 (server integration)
|
|
[US1+2 MVP checkpoint - validate isolation]
|
|
T031-T033 (US3 tests) → T034-T037 (US3 impl)
|
|
T038-T040 (US4 tests) → T041-T044 (US4 impl)
|
|
T045-T048 (US5 tests) → T049-T053 (US5 impl)
|
|
T054-T059 (Polish)
|
|
```
|
|
|
|
---
|
|
|
|
## Task Summary
|
|
|
|
| Phase | Tasks | Parallel Tasks |
|
|
|-------|-------|----------------|
|
|
| Phase 1: Setup | 3 | 2 |
|
|
| Phase 2: Foundational | 11 | 2 |
|
|
| Phase 3: US1+2 (P1) | 16 | 7 |
|
|
| Phase 4: US3 (P2) | 7 | 3 |
|
|
| Phase 5: US4 (P2) | 7 | 3 |
|
|
| Phase 6: US5 (P3) | 9 | 4 |
|
|
| Phase 7: Polish | 6 | 3 |
|
|
| **Total** | **59** | **24** |
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- [P] tasks = different files, no dependencies on incomplete tasks
|
|
- [USx] label maps task to specific user story
|
|
- Each user story independently completable and testable
|
|
- Verify tests fail before implementing
|
|
- Commit after each task or logical group
|
|
- Stop at any checkpoint to validate story independently
|
|
- Constitution compliance verified at each phase boundary
|