Role-gated document Q&A: users log in with one of three roles (finance, engineering, admin), chat with a RAG system that only sees their role's documents, and admins manage users and upload new documents through a dedicated tab. Built with Gradio, ChromaDB, sentence-transformers, and OpenRouter.
Start learning at learnwithparam.com. Regional pricing available with discounts of up to 60%.
- Role-based access control applied to a RAG retrieval pipeline, not just the UI layer
- Session token auth with PBKDF2-HMAC-SHA256 hashing, salts, and account lockout
- Per-role ChromaDB collections so retrieval itself enforces the access wall
- Sliding-window rate limiting that survives restarts
- Admin operations: add users, upload docs, assign roles without dropping the session
- Swapping LLM providers cleanly (OpenRouter today, anything OpenAI-compatible tomorrow)
- Gradio - Three-tab UI (login, chat, admin) with reactive state
- ChromaDB - Persistent vector database, one collection per role
- Sentence Transformers - Local embeddings (
all-MiniLM-L6-v2), no API key needed - OpenRouter - Unified OpenAI-compatible access to open + frontier models
- PBKDF2 - Password hashing with per-user salts and 100k iterations
- Docker - Single-container deployment
- Python 3.11+
- uv (installed automatically by
make setup) - An OpenRouter API key
# One command to set up and run
make dev
# Or step by step:
make setup # Create .env and install dependencies
# Edit .env and set OPENROUTER_API_KEY
make run # Start the Gradio appThen open http://localhost:7860.
make build # Build the image
make up # Start the container
make logs # Tail logs
make down # Stop the container| Username | Password | Role |
|---|---|---|
admin |
admin123 |
admin |
finance_user |
finance123 |
finance |
engineering_user |
engineering123 |
engineering |
Change these before deploying anywhere real. They live in data/users.json after first launch; delete data/ to reseed.
Login → Session token (1h expiry, auto-extends)
↓
Query + role
↓
Sentence-Transformer embedding
↓
ChromaDB query (role-scoped collection)
↓
Top-3 docs → OpenRouter chat completion (role-aware system prompt)
↓
Response
The RBAC wall is enforced at the retrieval layer, not just the UI. A finance_user query never touches engineering docs because search_documents(role="finance", ...) only queries the finance_docs collection.
Work through these incrementally. The starting repo implements the full happy path; use these to go deeper.
- Swap OpenRouter models - Try
anthropic/claude-sonnet-4,openai/gpt-4o-mini, and a free model likeminimax/minimax-m2:free. Compare answer quality on the same finance question. - Audit log for every access - Log every chat query with
{timestamp, user, role, query, doc_ids_retrieved}todata/audit.jsonl. Display the last 50 entries in the admin tab. - Per-role rate limits - Instead of a global
10 requests / 60s, read limits from a role-specific config (e.g., admins get 100/60s, finance gets 20/60s). - Replace opaque session tokens with JWT - Sign with a secret from
.env. Carry role claim inside the token so no server-side session store is needed. - Postgres-backed persistence - Replace the JSON-file user store with a proper Postgres schema (
users,sessions,audit_log). Add Docker Compose Postgres service. - Document chunking - The current seed docs are short. Add
langchain-text-splittersto chunk long docs so retrieval top-3 returns more focused context. - Cross-role admin read - Add an admin-only "search across all roles" mode to the chat tab that combines every collection into one retrieval pass.
- OpenAPI frontend - Swap Gradio for a FastAPI + simple HTML frontend. Keep the modules (auth, vector store, rag chat, rate limiter) untouched. Good practice for the provider pattern.
make help Show all available commands
make setup Initial setup (create .env, install deps)
make dev Setup and run (one command!)
make run Start the Gradio app
make build Build Docker image
make up Start container
make down Stop container
make clean Remove venv, Chroma, seeded data
make clean-all Clean everything including Docker volumes
- Start the course: learnwithparam.com/courses/rbac-rag-chatbot
- AI Bootcamp for Software Engineers: learnwithparam.com/ai-bootcamp
- All courses: learnwithparam.com/courses