# Claude Code Projektregeln — FastAPI/Python Backend

**Projekt:** `<Projektname eintragen>`
**Stack:** FastAPI 0.100+, Python 3.10+, SQLAlchemy, PostgreSQL
**Zuletzt aktualisiert:** `<Datum eintragen>`

---

## 🎯 Verhaltens-Leitplanken (über allem)

Diese 4 Prinzipien verhindern Over-Engineering, stille Annahmen und fehlende Verifikation.

### 1. Denken vor Coden
```
✅ Annahmen EXPLIZIT aussprechen, nicht still voraussetzen
✅ Bei Mehrdeutigkeit: mehrere Interpretationen zeigen, nicht raten
✅ Bei Unklarheit: STOPPEN und fragen — keine Vermutungen
❌ NIEMALS still eine Interpretation wählen und loscoden
```

### 2. Einfachheit zuerst
```
✅ Minimaler Code der das Problem löst — nichts mehr
✅ Keine spekulativen Features für "könnte später nützlich sein"
✅ Keine Abstraktionen für Single-Use-Code
❌ NIEMALS ungefragte Flexibilität einbauen
```

### 3. Chirurgische Änderungen
```
✅ Nur anfassen was wirklich geändert werden muss
✅ Existierenden Stil matchen, nicht "verbessern"
❌ NIEMALS angrenzenden funktionierenden Code refactorn
```

### 4. Ziel-getriebene Ausführung
```
✅ Request in verifizierbare Erfolgskriterien umwandeln
❌ NIEMALS "sollte funktionieren" ohne Verifikation
```

---

## 📐 FastAPI/Python Coding-Regeln

### REGEL 01 — Kein Stub-Code
```python
# ❌ VERBOTEN
def process_data(input: dict): pass  # TODO

# ✅ KORREKT — vollständig oder gar nicht
async def process_data(input: InputModel, db: AsyncSession) -> OutputModel:
    validated = service.validate(input)
    result = await service.process(db, validated)
    return OutputModel.from_orm(result)
```

### REGEL 02 — Jeder Endpoint: Pydantic + Auth + Error-Handling
```python
@router.post("/items", response_model=ItemResponse, status_code=201)
async def create_item(
    data: ItemCreateRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user)
) -> ItemResponse:
    try:
        result = await item_service.create(db, data, current_user.id)
        return ItemResponse.model_validate(result)
    except NotFoundError:
        raise HTTPException(status_code=404, detail="Not found")
    except PermissionError:
        raise HTTPException(status_code=403, detail="Access denied")
    except Exception as e:
        logger.error(f"create_item failed: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail="Internal error")
```

### REGEL 03 — DB-Zugriff mit Auth + Ownership
```python
# Jeder DB-Zugriff prüft Besitzrechte
item = await db.get(Item, item_id)
if not item:
    raise HTTPException(status_code=404, detail="Not found")
if item.user_id != current_user.id:
    raise HTTPException(status_code=403, detail="Access denied")
```

### REGEL 04 — Kein `print()` in Produktion
```python
# ❌ print(user)
# ✅ logger.info("User created", extra={"user_id": user.id})
```

### REGEL 05 — UTC für alle Timestamps
```python
# ❌ datetime.now()
# ✅ datetime.now(timezone.utc)
```

### REGEL 06 — async/await für I/O
```python
# ✅ DB/API-Calls immer async
async def get_items(db: AsyncSession) -> list[Item]:
    result = await db.execute(select(Item))
    return result.scalars().all()
```

### REGEL 07 — Migrations mit upgrade() UND downgrade()
```python
def upgrade() -> None:
    op.create_table("items", ...)

def downgrade() -> None:
    op.drop_table("items")  # NIEMALS leer lassen
```

### REGEL 08 — Secrets nie committen
```bash
# .gitignore muss enthalten
.env
.env.*
*.pem
```

### REGEL 09 — Rate-Limiting
```python
from slowapi import Limiter
limiter = Limiter(key_func=get_remote_address)

@app.post("/auth/login")
@limiter.limit("5/minute")  # Auth-Endpoints strenger
async def login(...): ...
```

### REGEL 10 — CORS nie Wildcard
```python
# ❌ allow_origins=["*"]
# ✅ allow_origins=settings.ALLOWED_ORIGINS  # aus .env
```

---

## ✅ Definition of Done — API Endpoint

Ein Endpoint ist NICHT fertig bis:

```
[ ] Pydantic Request + Response Schema definiert
[ ] Auth-Check (Depends(get_current_user))
[ ] Ownership-Check bei User-Daten
[ ] Alle HTTP-Codes korrekt (400/401/403/404/422/500)
[ ] Rate-Limiting konfiguriert
[ ] Logging — kein print()
[ ] Tests: happy path + 401 + 403 + 422 + 404 + 500
[ ] pytest → alle Tests grün (Ausgabe zeigen)
[ ] curl → Response zeigen
[ ] In /docs sichtbar und korrekt dokumentiert
```

---

## ✅ Definition of Done — Datenbank-Migration

```
[ ] upgrade() vollständig implementiert
[ ] downgrade() vollständig implementiert (nie leer!)
[ ] Auf leerer Test-DB getestet: alembic upgrade head → kein Fehler
[ ] Rollback getestet: alembic downgrade -1 → kein Fehler
[ ] Keine Datenverluste möglich bei rollback
```

---

## 🚨 Kritische Verbote — IMMER gültig

```
❌ NIEMALS `/init` ausführen (überschreibt CLAUDE.md)
❌ NIEMALS diese CLAUDE.md ohne explizite Anweisung ändern
❌ NIEMALS mehrere Features gleichzeitig implementieren
❌ NIEMALS weitermachen wenn pytest rot ist
❌ NIEMALS paid API-Calls nach Fehler ohne Bestätigung wiederholen
❌ NIEMALS pass, ..., oder # TODO in produktivem Code
❌ NIEMALS .env committen
❌ NIEMALS Code ohne vorherigen Test-Plan schreiben
❌ NIEMALS "es funktioniert" sagen ohne Beweis
❌ NIEMALS zur nächsten Aufgabe ohne Status-Update
```

---

## 🔬 Proof-Protokoll (Pflicht vor "fertig")

Beweis ist NICHT optional. Vor jedem "fertig" zeigen:

```bash
# 1. Tests
pytest tests/ -v
# Ausgabe: X passed, 0 failed

# 2. Lint
ruff check .
# Ausgabe: 0 Errors

# 3. TypeCheck (wenn mypy/pyright genutzt)
mypy app/
# Ausgabe: Success

# 4. Manual-Test
curl -X POST http://localhost:8000/api/items \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"test"}'
# → Response zeigen

# 5. Docs-Check
# http://localhost:8000/docs → Screenshot oder Beschreibung
```

---

## 🔐 Security-Basics

```
[ ] Alle Inputs validieren (Pydantic)
[ ] Auth-Check auf allen geschützten Endpoints
[ ] Ownership-Check bei User-Daten
[ ] Rate-Limiting auf Auth/Heavy-Endpoints
[ ] CORS nicht wildcard in Produktion
[ ] Secrets aus .env, nie hardcoded
[ ] Keine PII in Logs (E-Mails, Tokens, Passwörter)
[ ] SQL-Injection: nur ORM, kein raw SQL mit User-Input
[ ] Passwörter mit bcrypt (rounds=12)
```

---

## 📝 Arbeitsprotokoll — Kurzform

### Vor der Implementierung
1. Aufgabe in kleinste Einheit zerlegen (1 Endpoint, 1 Service, 1 Migration)
2. Betroffene Dateien identifizieren
3. Test-Plan: Was ist Success? Was sind Fehlerfälle?
4. Bei Unklarheit: FRAGEN

### Implementierung
1. Eine Einheit auf einmal
2. Zuerst Test (wenn möglich), dann Code
3. Nach jeder Datei: mentaler DoD-Check

### Nach der Implementierung
1. pytest → Ausgabe zeigen
2. Lint/TypeCheck → Ausgabe zeigen
3. curl-Test → Response zeigen
4. ERST DANN "fertig" melden

---

## 📦 Standard-Befehle

```bash
# Installation
pip install -r requirements.txt
# oder: poetry install

# Tests
pytest tests/ -v
pytest --cov=app --cov-report=term-missing

# Lint
ruff check .
ruff format .

# TypeCheck (wenn genutzt)
mypy app/

# Migrations
alembic revision --autogenerate -m "description"
alembic upgrade head
alembic downgrade -1

# Server
uvicorn app.main:app --reload  # Dev
uvicorn app.main:app --host 0.0.0.0 --port 8000  # Prod
```

---

## 🎓 Self-Check vor jeder Antwort

```
[ ] Habe ich still eine Annahme getroffen? → Explizit machen
[ ] Baue ich mehr als gefragt? → Zurückschneiden
[ ] Ändere ich Code der nicht geändert werden muss? → Zurückdrehen
[ ] Kann ich verifizieren ob es funktioniert? → Kriterium definieren
[ ] Habe ich Beweis-Ausgaben gezeigt? → Nicht nur "sollte klappen"
```

---

**Anpassung erwünscht** — diese Vorlage ist ein Starter, kein Dogma.
Ergänze projekt-spezifische Regeln (z.B. Celery-Tasks, Redis-Caching, etc.).
