Privacy-first RAG workbench for technical teams — Supabase + pgvector, OpenAI, and Sentry
CSBrainAI is a privacy-first RAG workbench for technical teams that need internal knowledge assistants. User queries are never stored in raw form — only HMAC-SHA256 hashes and lengths are logged, ensuring complete privacy while maintaining full observability. Answers come with citations and similarity scores, backed by an automated eval harness and operational guardrails.
- 🔒 Privacy-First: HMAC-SHA256 hashed queries (no raw PII in logs)
- 🚀 RAG Pipeline: Supabase + pgvector for semantic search
- 🤖 OpenAI Integration: text-embedding-3-small + gpt-4o-mini
- 🛡️ Security: CSP, rate limiting (10 req/min), HSTS
- 📊 Observability: Sentry L5 tool with PII scrubbing
- 🧪 Nightly Evals: Automated quality testing via GitHub Actions
- ⚡ Production-Ready: Type-safe, tested, documented
┌─────────────┐
│ User │
└──────┬──────┘
│ query
▼
┌─────────────────────────┐
│ Next.js App Router │
│ - Rate Limiting │
│ - Security Headers │
│ - PII Scrubbing │
└──────┬──────────────────┘
│
▼
┌─────────────────────────┐
│ /api/answer │
│ 1. Hash query (HMAC) │
│ 2. Embed query (OpenAI)│
│ 3. Vector search │
│ 4. LLM generation │
└──────┬──────────────────┘
│
▼
┌─────────────────────────┐
│ Supabase + pgvector │
│ - IVFFlat index │
│ - Cosine similarity │
│ - RLS policies │
└─────────────────────────┘
| Component | Technology | Purpose |
|---|---|---|
| Framework | Next.js 16 (App Router) | Full-stack React framework |
| Language | TypeScript 5 | Type safety |
| Database | Supabase (PostgreSQL) | Vector storage with pgvector |
| Embeddings | OpenAI text-embedding-3-small | 1536-dim vectors |
| LLM | OpenAI gpt-4o-mini | Answer generation |
| Observability | Sentry | Error tracking (L5 tool) |
| Rate Limiting | Upstash Redis / Token Bucket | API protection |
| Security | Next.js Proxy | CSP, HSTS, headers |
| CI/CD | GitHub Actions | Nightly evaluations |
Prerequisites:
- Node.js 20+
- Supabase account (for vector storage)
- OpenAI API key
- Sentry account (optional but recommended)
Run the demo:
# 1. Install dependencies
npm install
# 2. Set up environment variables
cp .env.example .env
# Edit .env with your SUPABASE_URL, SUPABASE_ANON_KEY, OPENAI_API_KEY
# 3. Run database migration (in Supabase SQL Editor)
# Copy contents of supabase/migrations/001_rag_schema.sql and execute
# 4. Ingest sample knowledge
npm run ingest
# 5. Start development server
npm run dev
# 6. Test the API (in another terminal)
curl -X POST http://localhost:3000/api/answer \
-H "Content-Type: application/json" \
-d '{"query":"What is RAG?"}'Expected Output:
{
"answer": "RAG (Retrieval Augmented Generation) is an AI architecture...",
"citations": [
{
"source_url": "file://sample-1.md#chunk-0",
"content": "RAG (Retrieval Augmented Generation) is...",
"similarity": 0.87
}
],
"q_hash": "a3f2b9c1d4e5f6a7b8c9d0e1f2a3b4c5...",
"q_len": 12,
"tokensUsed": 456
}What this proves:
- Privacy-first RAG system (queries are hashed, never stored raw)
- Vector search with Supabase + pgvector
- Structured citations with similarity scores
- Operational guardrails (rate limiting, PII scrubbing, hashed-query telemetry) fit for internal knowledge assistants
Alternative demo (no setup needed):
# Run unit tests to see functionality
npm testNext Steps:
- See
docs/ANSWER-FLOW.mdfor API architecture - See
TEST_NOTES.mdfor manual test scenarios
- Node.js 20+
- Supabase account
- OpenAI API key
- Sentry account (optional but recommended)
git clone https://github.com/RazonIn4K/csbrainai.git
cd csbrainai
npm installcp .env.example .envEdit .env with your credentials:
# OpenAI
OPENAI_API_KEY=sk-...
# Supabase
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE=eyJ... # For ingestion only
# Security
HASH_SALT=$(openssl rand -hex 32)
# Sentry
SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx
NEXT_PUBLIC_SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx
# Optional: Upstash Redis (for distributed rate limiting)
UPSTASH_REDIS_REST_URL=https://xxx.upstash.io
UPSTASH_REDIS_REST_TOKEN=xxxRun the migration in Supabase SQL Editor or via CLI:
# Copy contents of supabase/migrations/001_rag_schema.sql
# and execute in Supabase SQL EditorOr using Supabase CLI:
supabase link --project-ref <your-project-ref>
supabase db pushAdd your knowledge files to data/knowledge/:
# Example structure:
data/knowledge/
├── faq.md
├── product-docs.md
└── technical-guide.mdRun ingestion:
npm run ingestExpected output:
🚀 Starting RAG ingestion...
📚 Found 3 knowledge file(s)
...
✅ Ingestion complete!
📊 Summary:
├─ Total chunks: 42
├─ Processed: 42
├─ Skipped (duplicates): 0
└─ Errors: 0
npm run devOpen http://localhost:3000 and try asking a question!
npm run evalsComprehensive docs in the docs/ directory:
- SCHEMA.md - Database schema and indexes
- INGEST.md - Ingestion process and chunking
- ANSWER-FLOW.md - Answer API architecture
- PRIVACY.md - Privacy guarantees and PII protection
- GO-LIVE-GATE.md - Production readiness checklist
✅ What we store:
- Query hash (HMAC-SHA256)
- Query length
- Metadata (timestamps, token usage)
❌ What we NEVER store:
- Raw query text
- User identifiers (beyond IP for rate limiting)
- PII of any kind
- Rate Limiting: 10 requests/min/IP
- Security Headers: CSP, HSTS, X-Frame-Options
- PII Scrubbing: Automatic Sentry
beforeSendhooks - Input Validation: Max query length, type checking
- HTTPS Only: Enforced via HSTS
See PRIVACY.md for full details.
Automated quality testing runs nightly at 2 AM UTC:
# .github/workflows/nightly-evals.yml
- Skips scheduled runs when required evaluation secrets are not configured
- Fails manual dispatches when required evaluation secrets are missing
- Loads 20 test questions from data/evals/test-questions.jsonl
- Calls /api/answer for each question
- Validates response quality, citations, latency
- Uploads results as GitHub Actions artifact
- Fails only on severe regressions (< 50% quality)Run manually:
npm run evalscurl -X POST http://localhost:3000/api/answer \
-H "Content-Type: application/json" \
-d '{"query": "What is RAG?"}'Generate an answer using RAG.
Request:
{
"query": "What is RAG and how does it work?"
}Response (200):
{
"answer": "RAG (Retrieval Augmented Generation) is an AI architecture...",
"citations": [
{
"source_url": "file://sample-1.md#chunk-0",
"content": "RAG (Retrieval Augmented Generation) is...",
"similarity": 0.87
}
],
"q_hash": "a3f2b9c1d4e5f6a7b8c9d0e1f2a3b4c5...",
"q_len": 35,
"tokensUsed": 456
}Error (429):
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Please try again later."
}See ANSWER-FLOW.md for complete API docs.
npm run dev # Start dev server
npm run build # Production build
npm run start # Start production server
npm run lint # Run ESLint
npm run type-check # TypeScript type checking
npm run ingest # Run ingestion script
npm run evals # Run evaluation suitecsbrainai/
├── app/
│ ├── api/answer/route.ts # Answer endpoint
│ ├── layout.tsx # Root layout
│ └── page.tsx # Home page
├── components/
│ └── AnswerDemo.tsx # Demo UI
├── data/
│ ├── evals/ # Evaluation questions
│ └── knowledge/ # Knowledge base files
├── docs/ # Documentation
├── lib/
│ ├── crypto-utils.ts # HMAC hashing
│ ├── openai.ts # OpenAI client
│ ├── rate-limiter.ts # Rate limiting
│ ├── sentry-utils.ts # PII scrubbing
│ └── supabase.ts # Database client
├── scripts/
│ ├── evals-runner.ts # Evaluation script
│ └── ingest.ts # Ingestion script
├── supabase/migrations/ # Database migrations
├── middleware.ts # Security & rate limiting
├── sentry.client.config.ts # Sentry client
└── sentry.server.config.ts # Sentry server
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel --prodSet all variables from .env.example in Vercel dashboard:
- Project Settings → Environment Variables
- Run database migration in Supabase
- Run ingestion:
npm run ingest(local or CI) - Verify Sentry integration
- Test API endpoint
- Check nightly evals workflow
See GO-LIVE-GATE.md for production checklist.
Monitor in production:
- Error rate (target: < 1%)
- Performance (p95 < 3s)
- Rate limit violations
- PII scrubbing effectiveness
- Latency: Median, p95, p99 response times
- Quality: Nightly eval scores
- Cost: OpenAI token usage
- Errors: 4xx/5xx rates
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE for details.
- Supabase for pgvector support
- OpenAI for embeddings and LLM APIs
- Sentry for observability
- Next.js for the framework
- Upstash for serverless Redis
- Documentation: docs/
- Issues: GitHub Issues
- Security: Report vulnerabilities through GitHub Security Advisories for this repository.
Built by David Ortiz.