Skip to content

Commit bdf2bb5

Browse files
feat: Initial commit of Knowledge Engine API (Multi-Tenant RAG template)
0 parents  commit bdf2bb5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+4152
-0
lines changed

.env.example

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Application Settings
2+
APP_NAME="Knowledge Engine API"
3+
APP_VERSION="0.1.0"
4+
ENVIRONMENT="development" # development, staging, production
5+
DEBUG=true
6+
7+
# Server
8+
API_HOST="0.0.0.0"
9+
API_PORT=8000
10+
11+
# Database
12+
# For development (SQLite)
13+
DATABASE_URL="sqlite+aiosqlite:///./knowledge_engine.db"
14+
15+
# For production (PostgreSQL with full-text search)
16+
# DATABASE_URL="postgresql+asyncpg://user:password@localhost:5432/knowledge_engine"
17+
18+
# JWT Settings (Admin Authentication)
19+
JWT_SECRET_KEY="your-super-secret-jwt-key-change-this-in-production"
20+
JWT_ALGORITHM="HS256"
21+
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
22+
23+
# API Key Settings (B2B Client Authentication)
24+
API_KEY_PREFIX="keng"
25+
API_KEY_SECRET="your-api-key-signing-secret-change-this"
26+
27+
# Rate Limiting (requests per minute)
28+
FREE_TIER_LIMIT=10
29+
PREMIUM_TIER_LIMIT=100
30+
ENTERPRISE_TIER_LIMIT=1000
31+
32+
# CORS
33+
CORS_ORIGINS="http://localhost:3000,http://localhost:8000"
34+
35+
# Content Source
36+
CONTENT_SOURCE_PATH="data/notebooklm"
37+
38+
# Search Configuration
39+
SEARCH_MAX_RESULTS=100
40+
SEARCH_DEFAULT_LIMIT=20
41+
42+
# Logging
43+
LOG_LEVEL="INFO" # DEBUG, INFO, WARNING, ERROR, CRITICAL
44+
LOG_FORMAT="json" # json or text
45+
46+
# Initial Admin User (created on first run)
47+
ADMIN_EMAIL="admin@example.com"
48+
ADMIN_PASSWORD="change-this-secure-password"

.github/workflows/test.yml

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
name: Quality Assurance
2+
3+
on:
4+
pull_request:
5+
branches: [main, develop]
6+
push:
7+
branches: [main, develop]
8+
9+
jobs:
10+
# Stage 1: Linting - If this fails, tests won't run
11+
lint:
12+
name: Code Quality (Linting & Formatting)
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: "3.11"
23+
24+
- name: Install Poetry
25+
uses: snok/install-poetry@v1
26+
with:
27+
version: 1.7.1
28+
virtualenvs-create: true
29+
virtualenvs-in-project: true
30+
31+
- name: Cache dependencies
32+
uses: actions/cache@v3
33+
with:
34+
path: .venv
35+
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
36+
37+
- name: Install dependencies
38+
run: poetry install --no-interaction --no-root
39+
40+
- name: Run Black (formatting check)
41+
run: |
42+
poetry run black --check app tests
43+
if [ $? -ne 0 ]; then
44+
echo "❌ FAILED: Code is not formatted with Black"
45+
echo "Run: poetry run black app tests"
46+
exit 1
47+
fi
48+
49+
- name: Run Ruff (linting)
50+
run: |
51+
poetry run ruff check app tests
52+
if [ $? -ne 0 ]; then
53+
echo "❌ FAILED: Ruff found linting errors"
54+
echo "Run: poetry run ruff check app tests --fix"
55+
exit 1
56+
fi
57+
58+
- name: Run MyPy (type checking)
59+
run: |
60+
poetry run mypy app
61+
if [ $? -ne 0 ]; then
62+
echo "❌ FAILED: MyPy found type errors"
63+
exit 1
64+
fi
65+
66+
- name: ✅ Linting Passed
67+
run: echo "All linting checks passed!"
68+
69+
# Stage 2: Tests - Only runs if linting passes
70+
test:
71+
name: Unit & Integration Tests
72+
runs-on: ubuntu-latest
73+
needs: lint # This ensures tests only run after linting passes
74+
75+
steps:
76+
- name: Checkout code
77+
uses: actions/checkout@v4
78+
79+
- name: Set up Python
80+
uses: actions/setup-python@v5
81+
with:
82+
python-version: "3.11"
83+
84+
- name: Install Poetry
85+
uses: snok/install-poetry@v1
86+
with:
87+
version: 1.7.1
88+
virtualenvs-create: true
89+
virtualenvs-in-project: true
90+
91+
- name: Cache dependencies
92+
uses: actions/cache@v3
93+
with:
94+
path: .venv
95+
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
96+
97+
- name: Install dependencies
98+
run: poetry install --no-interaction
99+
100+
- name: Run tests with coverage
101+
run: |
102+
poetry run pytest -v --cov=app --cov-report=xml --cov-report=term-missing
103+
if [ $? -ne 0 ]; then
104+
echo "❌ FAILED: Tests did not pass"
105+
exit 1
106+
fi
107+
108+
- name: Upload coverage to Codecov
109+
uses: codecov/codecov-action@v3
110+
with:
111+
file: ./coverage.xml
112+
fail_ci_if_error: false
113+
114+
- name: Check coverage threshold
115+
run: |
116+
COVERAGE=$(poetry run coverage report | grep TOTAL | awk '{print $4}' | sed 's/%//')
117+
echo "Coverage: $COVERAGE%"
118+
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
119+
echo "❌ FAILED: Coverage is below 80% ($COVERAGE%)"
120+
exit 1
121+
fi
122+
echo "✅ Coverage meets threshold: $COVERAGE%"
123+
124+
- name: ✅ Tests Passed
125+
run: echo "All tests passed with adequate coverage!"
126+
127+
# Optional: Security scanning
128+
security:
129+
name: Security Scan
130+
runs-on: ubuntu-latest
131+
needs: [lint, test]
132+
133+
steps:
134+
- name: Checkout code
135+
uses: actions/checkout@v4
136+
137+
- name: Run Bandit (security linter)
138+
uses: tj-actions/bandit@v5.1
139+
with:
140+
targets: |
141+
app/
142+
options: "-r -ll -s B104"

.gitignore

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
*.egg-info/
20+
.installed.cfg
21+
*.egg
22+
23+
# Virtual environments
24+
venv/
25+
ENV/
26+
env/
27+
.venv
28+
29+
# Environment variables
30+
.env
31+
.env.local
32+
33+
# IDE
34+
.vscode/
35+
.idea/
36+
*.swp
37+
*.swo
38+
*~
39+
.DS_Store
40+
41+
# Testing
42+
.pytest_cache/
43+
.coverage
44+
htmlcov/
45+
.tox/
46+
*.cover
47+
48+
# Database
49+
*.db
50+
*.sqlite
51+
*.sqlite3
52+
53+
# Alembic
54+
alembic/versions/*.pyc
55+
56+
# Logs
57+
*.log
58+
logs/
59+
60+
# Content (keep private)
61+
data/
62+
63+
# MyPy
64+
.mypy_cache/
65+
.dmypy.json
66+
dmypy.json
67+
68+
# Ruff
69+
.ruff_cache/
70+
71+
# Poetry
72+
poetry.lock

.pre-commit-config.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.5.0
4+
hooks:
5+
- id: trailing-whitespace
6+
fail_fast: true
7+
- id: end-of-file-fixer
8+
fail_fast: true
9+
- id: check-yaml
10+
fail_fast: true
11+
- id: check-added-large-files
12+
fail_fast: true
13+
args: ["--maxkb=500"]
14+
- id: check-json
15+
fail_fast: true
16+
- id: check-toml
17+
fail_fast: true
18+
- id: check-merge-conflict
19+
fail_fast: true
20+
21+
- repo: https://github.com/psf/black
22+
rev: 23.12.1
23+
hooks:
24+
- id: black
25+
language_version: python3.11
26+
fail_fast: true
27+
28+
- repo: https://github.com/charliermarsh/ruff-pre-commit
29+
rev: v0.1.9
30+
hooks:
31+
- id: ruff
32+
args: [--fix, --exit-non-zero-on-fix, --select, "E,W,F,I,C,B,UP"]
33+
fail_fast: true
34+
35+
- repo: https://github.com/pre-commit/mirrors-mypy
36+
rev: v1.8.0
37+
hooks:
38+
- id: mypy
39+
additional_dependencies: [pydantic, sqlalchemy, types-passlib]
40+
args: [--strict, --no-error-summary]
41+
fail_fast: true
42+
43+
# Global configuration
44+
fail_fast: true # Stop on first failure
45+
default_stages: [commit]

Dockerfile

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
FROM python:3.11-slim as builder
2+
3+
# Set environment variables
4+
ENV PYTHONUNBUFFERED=1 \
5+
PYTHONDONTWRITEBYTECODE=1 \
6+
PIP_NO_CACHE_DIR=1 \
7+
PIP_DISABLE_PIP_VERSION_CHECK=1
8+
9+
# Install system dependencies
10+
RUN apt-get update && apt-get install -y \
11+
gcc \
12+
&& rm -rf /var/lib/apt/lists/*
13+
14+
# Install Poetry
15+
RUN pip install poetry==1.7.1
16+
17+
# Set working directory
18+
WORKDIR /app
19+
20+
# Copy dependency files
21+
COPY pyproject.toml ./
22+
23+
# Install dependencies
24+
RUN poetry config virtualenvs.create false \
25+
&& poetry install --no-interaction --no-anity --no-root --only main
26+
27+
# Production stage
28+
FROM python:3.11-slim
29+
30+
# Set environment variables
31+
ENV PYTHONUNBUFFERED=1 \
32+
PYTHONDONTWRITEBYTECODE=1
33+
34+
# Create non-root user
35+
RUN useradd -m -u 1000 appuser && \
36+
mkdir -p /app && \
37+
chown -R appuser:appuser /app
38+
39+
WORKDIR /app
40+
41+
# Copy installed packages from builder
42+
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
43+
COPY --from=builder /usr/local/bin /usr/local/bin
44+
45+
# Copy application code
46+
COPY --chown=appuser:appuser . .
47+
48+
# Switch to non-root user
49+
USER appuser
50+
51+
# Expose port
52+
EXPOSE 8000
53+
54+
# Health check
55+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
56+
CMD python -c "import requests; requests.get('http://localhost:8000/health')"
57+
58+
# Run application
59+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

0 commit comments

Comments
 (0)