Multi-tenant knowledge platform with RAG query interface and workspace collaboration. Built with FastAPI, PostgreSQL, FAISS, React, and local LLM.
backend/app/
├── api/v1/ # API endpoints
│ ├── auth.py # Authentication (register, login)
│ ├── workspace.py # Workspace management (invites, members, roles)
│ ├── ingestion.py # Document upload and ingestion
│ ├── chat.py # RAG query interface
│ ├── users.py # User management
│ └── tasks.py # Async task status
├── core/ # Config, security, logging
│ ├── config.py # Application settings
│ ├── security.py # JWT, password hashing
│ ├── dependencies.py # FastAPI dependencies (auth, tenant extraction)
│ └── logger.py # Structured JSON logging
├── db/ # Models, session
│ ├── models/ # SQLAlchemy models
│ │ ├── user.py # User model with role (ADMIN/MEMBER)
│ │ ├── tenant.py # Tenant/Workspace model with invite_code
│ │ ├── document.py # Document model with versioning
│ │ └── document_chunk.py # Chunk model for vector storage
│ └── session.py # Database session management
├── services/ # Business logic
│ ├── auth_service.py # Authentication logic
│ ├── workspace_service.py # Workspace management
│ ├── ingestion_service.py # Document processing
│ ├── rag.py # RAG query logic
│ ├── vector_store.py # FAISS operations
│ └── embedding.py # Text embedding generation
├── tasks/ # Celery async tasks
│ └── ingestion_tasks.py # Background document processing
└── schemas/ # Pydantic models for API
frontend/
├── src/
│ ├── pages/ # React pages
│ │ ├── Login.jsx
│ │ ├── Register.jsx
│ │ ├── Dashboard.jsx
│ │ ├── Documents.jsx
│ │ ├── Query.jsx
│ │ └── Workspace.jsx
│ ├── components/ # Reusable components
│ │ ├── Layout.jsx
│ │ └── ProtectedRoute.jsx
│ └── contexts/ # React context
│ └── AuthContext.jsx
HTTP Request → FastAPI Router → Dependency Injection (Auth) → Service Layer → Database/FAISS → Response
User Action → React Component → Axios API Call → Backend API → Response → State Update → UI Update
- Web framework with automatic API docs (
/docs) - Type validation via Pydantic schemas
- Dependency injection for DB sessions, auth, tenant extraction
- Middleware for metrics and logging
- ORM for PostgreSQL
- Models in
db/models/ - Migrations via Alembic
- Relationship management (User ↔ Tenant, Document ↔ Chunk)
- Vector similarity search for RAG
- Per-tenant indices stored on disk
- Efficient similarity search for document chunks
- Async task processing for document ingestion
- Background embedding generation
- Task status tracking
- Component-based UI with React Router
- Context API for authentication state
- Axios for API communication
- Tailwind CSS for styling
tenant_idextracted from JWT claims- All database queries filtered by
tenant_id - Separate FAISS indices per tenant (
{tenant_id}.index) - Redis cache keys prefixed with tenant ID
- Complete data isolation at all layers
- Tenant Creation: First user to register creates workspace (becomes ADMIN)
- Invite System: Admins generate invite codes for workspace access
- Member Roles: ADMIN (full access) and MEMBER (standard access)
- RBAC: Role-based access control enforced at API layer
- Token contains:
user_id,tenant_id,role - Token validation on every protected endpoint
- Automatic tenant extraction from token
- ADMIN: Can manage workspace (invite members, update roles, remove members)
- MEMBER: Can access workspace resources (upload docs, query, view members)
- Role enforcement via
require_admin_roledependency
- Business logic separated from API endpoints
- Services handle data access and business rules
- API endpoints are thin wrappers around services
- FastAPI
Depends()for DB sessions, auth, tenant extraction - Reusable dependencies for common operations
- Clean separation of concerns
- Services act as repositories for data access
- Database queries encapsulated in services
- Easy to test and maintain
1. User uploads document → API endpoint
2. Document saved to storage → PostgreSQL metadata
3. Async Celery task triggered
4. Document chunked → Embeddings generated → FAISS index updated
5. Task status tracked in Redis
1. User submits query → API endpoint
2. Query embedded → FAISS similarity search (tenant-scoped)
3. Top-k chunks retrieved → LLM context generation
4. LLM generates answer → Response returned
- Create Pydantic schema in
schemas/ - Create service function in
services/ - Add API endpoint in
api/v1/ - Register router in
main.py
- Create page component in
frontend/src/pages/ - Add route in
frontend/src/App.jsx - Add navigation link in
Layout.jsx
- Create SQLAlchemy model in
db/models/ - Import in
db/models/__init__.py - Create Alembic migration:
alembic revision --autogenerate -m "description" - Apply migration:
alembic upgrade head
- JWT tokens expire after 24 hours (configurable)
- Passwords hashed with bcrypt
- Tenant isolation enforced at all layers
- RBAC prevents unauthorized access
- Input validation via Pydantic schemas
- SQL injection prevented by SQLAlchemy ORM
- Async document processing prevents blocking
- FAISS provides fast vector similarity search
- Redis caching for frequently accessed data
- Database indexes on
tenant_idandemail - Connection pooling for database connections