📋 BEISPIEL-REPORT — Echte Analyse des Projekts "codedictate" (4.260 LOC, 47 Findings) Eigenen Report holen
VibeCodeDoktor

Dein persönlicher Code-Guide für codedictate

Report-ID: VCD-SAMPLE-codedictate Datum: 28. Februar 2026 Codezeilen: 4,260 Sprache: Python Tech-Stack: Flask, Whisper, SQLAlchemy

codedictate ist eine Flask-basierte Diktierloesung, die OpenAI Whisper zur Spracherkennung nutzt. Das Projekt zeigt solide Grundarchitektur, hat aber erhebliche Sicherheitsluecken (hartcodierte Secrets, fehlende Authentifizierung), unzureichende Testabdeckung und mehrere tote Codepfade.

Die Abhaengigkeiten sind teilweise veraltet mit bekannten Schwachstellen.

Sieh diesen Report als Leitfaden, nicht als Zeugnis. Jeder Hinweis enthält einen konkreten nächsten Schritt — oft reicht ein einziger KI-Prompt.

Dein Fahrplan

Die drei wichtigsten nächsten Schritte

1
Unbeschraenkter Datei-Upload ohne Validierung
Sicherheit
Angreifer koennen ausfuehrbaren Code hochladen oder den Server durch ueberdimensionierte Dateien ueberlasten.
2
Tief verschachtelte Fehlerbehandlung (5 Ebenen)
Komplexität
Fehler werden auf der falschen Ebene gefangen, was zu stillen Fehlern und schwer auffindbaren Bugs fuehrt.
3
Keine Integrationstests fuer API-Endpunkte
Tests
Routing-Fehler, falsche HTTP-Statuscodes und Serialisierungsprobleme werden erst in Produktion entdeckt.

Du bist auf dem richtigen Weg. Jeder Fix macht deinen Code besser für dich und für die KI. Bleib dran!

Gefällt dir was du siehst?

Dein Code hat wahrscheinlich ähnliche Probleme. 16 KI-Agenten finden sie für dich — in 15-45 Minuten.

Report für dein Projekt holen — EUR 19

Ich habe diese Bereiche analysiert:

Überblick

21
Quick Fixes
Kleine Änderungen, oft ein einzelner KI-Prompt
24
Wichtige Verbesserungen
Brauchen etwas mehr Aufmerksamkeit, aber lohnen sich
2
Strategische Upgrades
Größere Umbauten für langfristige Stabilität

Komplexität

Warum das wichtig ist

KI-Assistenten packen alles in eine große Funktion. Das funktioniert, bis du etwas änderst — dann bricht alles zusammen. Wenn eine Funktion >50 Zeilen hat oder >3 Verschachtelungsebenen, bitte die KI, sie aufzuteilen.

MAJOR Mittel

Tief verschachtelte Fehlerbehandlung (5 Ebenen)

server/transcribe.py:128
Was passiert hier

Fuenf verschachtelte try/except-Bloecke machen den Kontrollfluss nahezu unmoeglich nachzuvollziehen.

Was passiert, wenn du es nicht behebst

Fehler werden auf der falschen Ebene gefangen, was zu stillen Fehlern und schwer auffindbaren Bugs fuehrt.

So behebst du es
  1. Jeden try/except-Block in eine eigene Funktion extrahieren
  2. Spezifische Exceptions statt generischer verwenden
  3. Early-Return-Pattern fuer Fehlerpfade nutzen
KI-Fix-Prompt

"In server/transcribe.py starting at line 128, flatten the 5 nested try/except blocks by extracting each into a separate function that raises specific exceptions."

Code
try:
    try:
        try:
            result = whisper.transcribe(chunk)
        except APIError:
            try:
                result = whisper.transcribe(chunk, model="base")
            except:
                ...
Was du dir merken solltest

Verschachtelte Fehlerbehandlung durch Funktionsextraktion abflachen. Jede Funktion behandelt eine Aufgabe und deren spezifische Fehler.

MAJOR Aufwendig

Zirkulaerer Import zwischen app.py und models.py

server/app.py:8
Was passiert hier

app.py importiert models.py, und models.py importiert app.py fuer die db-Instanz. Dies wird durch verzoegerte Imports umgangen, was den Code fragil macht.

Was passiert, wenn du es nicht behebst

Jede Umstrukturierung kann zu ImportError fuehren. Der Code ist schwer zu testen, da die Import-Reihenfolge kritisch ist.

So behebst du es
  1. Datenbankinstanz in eigenes Modul (db.py) auslagern
  2. Beide Module importieren aus db.py statt voneinander
  3. Flask Application Factory Pattern einfuehren
KI-Fix-Prompt

"Create server/db.py exporting the SQLAlchemy db instance. Update server/app.py and server/models.py to import from server/db.py instead of each other."

Code
# server/app.py
from server.models import User, Transcription

# server/models.py
from server.app import db  # circular!
Was du dir merken solltest

Zirkulaere Imports deuten auf schlechte Modulgrenzen hin. Gemeinsame Abhaengigkeiten in ein separates Modul extrahieren.

MAJOR Mittel

Konfiguration ueber 6 Dateien verstreut

server/config.py:1
Was passiert hier

Konfigurationswerte sind ueber config.py, app.py, models.py, transcribe.py, whisper_api.py und setup.py verteilt, mit teilweise widersprüchlichen Defaults.

Was passiert, wenn du es nicht behebst

Inkonsistente Konfiguration fuehrt zu schwer reproduzierbaren Bugs, besonders zwischen Entwicklung und Produktion.

So behebst du es
  1. Alle Konfiguration in config.py zentralisieren
  2. Umgebungsabhaengige Config-Klassen verwenden (Development, Production, Testing)
  3. Andere Module importieren aus config.py
KI-Fix-Prompt

"Consolidate all configuration into server/config.py with Development/Production/Testing classes. Update all other files to import from config."

Code
# config.py: WHISPER_MODEL = "medium"
# transcribe.py: MODEL = os.getenv("MODEL", "small")  # conflicts!
# whisper_api.py: DEFAULT_MODEL = "base"  # another conflict!
Was du dir merken solltest

Konfiguration sollte an einem Ort leben. Eine einzige Wahrheitsquelle eliminiert Konfigurationsdrift.

MINOR Aufwendig

Ueberkomplexer Audio-Chunking-Algorithmus

server/audio.py:89
Was passiert hier

Der Chunking-Algorithmus implementiert Silence-Detection, Overlap-Handling und dynamische Chunk-Groesse in einer 120-Zeilen-Funktion mit 8 lokalen Variablen.

Was passiert, wenn du es nicht behebst

Schwer zu debuggen wenn Audioqualitaet variiert. Kleinste Aenderungen koennen das Transcription-Ergebnis dramatisch verschlechtern.

So behebst du es
  1. pydub oder librosa fuer Silence-Detection verwenden
  2. Algorithmus in klar benannte Teilschritte zerlegen
  3. Konfigurierbare Schwellenwerte statt Magic Numbers verwenden
KI-Fix-Prompt

"Refactor chunk_audio() in server/audio.py to use pydub.silence.split_on_silence() instead of the custom implementation. Extract constants to config."

Code
def chunk_audio(audio_data, sr=16000):
    threshold = 0.015  # magic number
    min_silence = int(sr * 0.3)  # magic number
    # ... 120 lines of sliding window logic
Was du dir merken solltest

Fuer gaengige Audio-Verarbeitungsaufgaben gut getestete Bibliotheken (pydub, librosa) statt eigener Implementierungen bevorzugen.

MINOR Mittel

UI-Modul hat vermischte Verantwortlichkeiten

client/ui.py:1
Was passiert hier

client/ui.py enthaelt sowohl GUI-Rendering als auch Geschaeftslogik (Dateiauswahl, API-Aufrufe, Fehlerbehandlung) in einer 450-Zeilen-Datei.

Was passiert, wenn du es nicht behebst

Aenderungen am Layout koennen Geschaeftslogik brechen und umgekehrt. Unit-Tests sind praktisch unmoeglich.

So behebst du es
  1. API-Aufrufe in separates client/api.py Modul extrahieren
  2. Geschaeftslogik in client/controller.py auslagern
  3. UI-Modul nur fuer Rendering und Event-Binding verwenden
KI-Fix-Prompt

"Split client/ui.py into three modules: client/ui.py (rendering only), client/api.py (API calls), client/controller.py (business logic coordination)."

Code
class MainWindow:
    def on_record_click(self):
        # 80 lines mixing UI updates, API calls, and error handling
        self.status_label.config(text="Recording...")
        audio = self.recorder.record()
        response = requests.post(API_URL + "/upload", ...)
Was du dir merken solltest

Darstellung von Logik trennen. MVC oder aehnliche Muster machen Code testbar und wartbar.

CRITICAL Grosser Aufwand

Gott-Funktion: transcribe_and_process (380 Zeilen)

server/transcribe.py:45
Was passiert hier

Eine einzelne Funktion behandelt Audio-Dekodierung, Chunking, Whisper-API-Aufrufe, Postprocessing, Interpunktion und Datenbankschreiben — alles in 380 Zeilen.

Was passiert, wenn du es nicht behebst

Praktisch nicht testbar, extrem fehleranfaellig bei Aenderungen. Jeder Bug-Fix kann unbeabsichtigte Seiteneffekte haben.

So behebst du es
  1. Funktion in eigenstaendige Schritte aufteilen: decode_audio, chunk_audio, call_whisper, postprocess, save_result
  2. Jeden Schritt separat testbar machen
  3. Pipeline-Pattern (Schritt fuer Schritt) implementieren
KI-Fix-Prompt

"Refactor transcribe_and_process() in server/transcribe.py into 5 smaller functions: decode_audio(), chunk_audio(), call_whisper(), postprocess_text(), save_transcription(). Wire them together in a pipeline function."

Code
def transcribe_and_process(audio_file, user_id, language="de"):
    # ... 380 lines of nested logic
    # audio decoding, chunking, API calls, text cleanup, DB writes
Was du dir merken solltest

Funktionen ueber 50 Zeilen sind ein Warnsignal. Ueber 100 ist gefaehrlich. Ueber 300 ist ein Wartungsalptraum. An Verantwortlichkeitsgrenzen aufteilen.

INFO Aufwendig

Zyklomatische Komplexitaet von 28 im Request-Handler

server/app.py:45
Was passiert hier

Der /transcribe-Endpunkt hat 28 verschiedene Entscheidungspfade durch verschachtelte Bedingungen und Fehlerbehandlung.

Was passiert, wenn du es nicht behebst

Bei jeder Aenderung muessen theoretisch 28 Pfade getestet werden. Das erhoehte Regressionsrisiko verlangsamt die Entwicklung.

So behebst du es
  1. Handler in Middleware-Chain aufteilen
  2. Validierung, Verarbeitung und Antwort in separate Funktionen extrahieren
  3. Guard-Clauses statt tiefer Verschachtelung verwenden
KI-Fix-Prompt

"Refactor the /transcribe endpoint in server/app.py to use guard clauses for early returns and extract validation, processing, and response formatting into separate functions."

Code
@app.route("/transcribe", methods=["POST"])
def transcribe():
    if request.content_type:
        if "multipart" in request.content_type:
            if "audio" in request.files:
                # ... 15 more levels of nesting
Was du dir merken solltest

Zyklomatische Komplexitaet unter 10 anstreben. Guard-Clauses (fruehe Returns) verwenden, um verschachtelte Bedingungen abzuflachen.

Tests

Warum das wichtig ist

Beim Vibe Coding ist Testen die einzige Garantie. Jeder neue Prompt kann alten Code brechen. Goldene Regel: Schreibe einen Test, der den aktuellen Stand beweist, BEVOR du die KI um Änderungen bittest.

MAJOR Aufwendig

Keine Integrationstests fuer API-Endpunkte

server/app.py:1
Was passiert hier

Kein einziger API-Endpunkt wird mit HTTP-Anfragen getestet. Weder Upload noch Transkription noch Admin-Routen haben Integrationstests.

Was passiert, wenn du es nicht behebst

Routing-Fehler, falsche HTTP-Statuscodes und Serialisierungsprobleme werden erst in Produktion entdeckt.

So behebst du es
  1. Flask Test Client (app.test_client()) verwenden
  2. Happy Path + Fehlerfaelle fuer jeden Endpunkt testen
  3. Request/Response-Format und Statuscodes validieren
KI-Fix-Prompt

"Create tests/test_api.py using Flask test client. Test all routes: GET /health, POST /upload, POST /transcribe, GET /transcriptions, /admin/* with both valid and invalid inputs."

Code
# No integration tests exist. Example of what should be:
# def test_upload_invalid_file(client):
#     response = client.post("/upload", data={"audio": (BytesIO(b"not audio"), "test.exe")})
#     assert response.status_code == 400
Was du dir merken solltest

Jeder API-Endpunkt braucht mindestens einen Happy-Path- und einen Fehlerfall-Integrationstest mit dem Framework-Test-Client.

MAJOR Mittel

Keine Test-Fixtures oder Factories

tests/test_transcribe.py:1
Was passiert hier

Testdaten werden inline erstellt ohne wiederverwendbare Fixtures. Jeder neue Test muss seinen eigenen Setup-Code schreiben.

Was passiert, wenn du es nicht behebst

Duplizierter Setup-Code fuehrt zu inkonsistenten Testdaten und macht Tests schwer wartbar.

So behebst du es
  1. pytest Fixtures in conftest.py erstellen
  2. Factory-Funktionen fuer haeufig benoetigte Testobjekte
  3. Fixtures fuer App-Instanz, DB-Session, Test-Client bereitstellen
KI-Fix-Prompt

"Create tests/conftest.py with fixtures: app (Flask test app), client (test client), db_session (test database), sample_audio (test audio file). Create tests/factories.py for User and Transcription factories."

Code
# Current: no fixtures, each test duplicates setup
def test_something():
    app = create_app()  # duplicated
    db.create_all()  # duplicated
    user = User(email="test@test.com")  # duplicated
Was du dir merken solltest

Gute Test-Infrastruktur (Fixtures, Factories, Helper) zahlt sich innerhalb von Wochen aus, indem sie Tests einfach zu schreiben und zu warten macht.

MINOR Quick Fix

Gemockte Tests stimmen nicht mit echter API ueberein

tests/test_transcribe.py:12
Was passiert hier

Der einzige Mock fuer die Whisper-API gibt ein vereinfachtes Objekt zurueck, das nicht dem tatsaechlichen API-Antwortformat entspricht.

Was passiert, wenn du es nicht behebst

Tests bestehen, obwohl der Code mit der echten API fehlschlagen wuerde. Falsche Sicherheit.

So behebst du es
  1. Mock-Antworten an echte API-Responses anpassen
  2. Fixture mit aufgezeichneter echter API-Antwort verwenden
  3. Contract-Test gegen die API-Dokumentation schreiben
KI-Fix-Prompt

"In tests/test_transcribe.py, update the Whisper API mock to return the actual response format including segments, language, and duration fields."

Code
# Mock returns simplified format:
mock_whisper.return_value = {"text": "hello world"}
# Real API returns: {"text": "...", "segments": [...], "language": "de", "duration": 12.5}
Was du dir merken solltest

Mocks muessen der realen Schnittstelle entsprechen. Echte Antworten aufzeichnen und als Fixtures verwenden, um Drift zu verhindern.

CRITICAL Grosser Aufwand

Nur 8% Testabdeckung (2 Tests fuer 4260 LOC)

tests/test_transcribe.py:1
Was passiert hier

Das gesamte Projekt hat nur 2 Tests in einer einzigen Testdatei. Kernfunktionalitaet wie Upload, Transkription und Authentifizierung ist nicht getestet.

Was passiert, wenn du es nicht behebst

Jede Aenderung kann unbemerkt bestehende Funktionalitaet zerstoeren. Refactoring wird zum Gluecksspiel.

So behebst du es
  1. Test-Framework einrichten (pytest, pytest-flask)
  2. Mindestens jeden API-Endpunkt testen
  3. Kritische Geschaeftslogik mit Unit-Tests abdecken
  4. CI-Pipeline mit Testausfuehrung aufsetzen
KI-Fix-Prompt

"Set up pytest with pytest-flask. Create test files: tests/test_api.py (endpoint tests), tests/test_transcribe.py (transcription logic), tests/test_models.py (database operations). Target 60% coverage minimum."

Code
# tests/test_transcribe.py — ENTIRE test suite:
def test_whisper_returns_text():
    assert transcribe("hello.wav") != ""

def test_empty_audio():
    assert transcribe("empty.wav") == ""
Was du dir merken solltest

Testabdeckung unter 40% bedeutet Blindflug. Kritische Pfade priorisieren: Auth, Zahlung, Datenpersistenz.

CRITICAL Mittel

Tests verwenden Produktionsdatenbank

tests/test_transcribe.py:5
Was passiert hier

Die vorhandenen Tests verbinden sich mit der gleichen Datenbank wie die Produktion, da keine Test-Konfiguration existiert.

Was passiert, wenn du es nicht behebst

Tests koennen Produktionsdaten veraendern oder loeschen. Ein versehentlicher Testlauf kann echte Benutzerdaten zerstoeren.

So behebst du es
  1. Separate Test-Datenbankverbindung in conftest.py konfigurieren
  2. SQLite In-Memory fuer schnelle Unit-Tests verwenden
  3. Fixtures fuer Testdaten-Setup und Teardown erstellen
KI-Fix-Prompt

"Create tests/conftest.py with a test database fixture using SQLite in-memory. Update tests to use the fixture instead of importing from server.config directly."

Code
# tests/test_transcribe.py
from server.config import DATABASE_URL  # same as production!
from server.models import db

def test_save_transcription():
    db.session.add(...)  # writes to production DB!
Was du dir merken solltest

Tests duerfen niemals Produktionsdatenbanken beruehren. Separate Testdatenbanken, Fixtures und Cleanup verwenden.

INFO Mittel

Keine CI/CD-Pipeline-Konfiguration

setup.py:1
Was passiert hier

Es gibt weder GitHub Actions, GitLab CI noch andere CI/CD-Konfiguration. Tests muessen manuell ausgefuehrt werden.

Was passiert, wenn du es nicht behebst

Ohne automatisierte Testausfuehrung werden Tests vergessen und die Codequalitaet erodiert schleichend.

So behebst du es
  1. GitHub Actions Workflow fuer Tests erstellen
  2. Lint-Check (flake8/ruff) und Tests bei jedem Push ausfuehren
  3. Branch-Protection-Rules aktivieren
KI-Fix-Prompt

"Create .github/workflows/test.yml that runs pytest on every push and PR. Include ruff linting. Add a badge to README.md."

Code
# No CI/CD configuration files found:
# No .github/workflows/*.yml
# No .gitlab-ci.yml
# No Jenkinsfile
Was du dir merken solltest

CI/CD ist nicht verhandelbar fuer jedes Team-Projekt. Linting und Tests ab Tag eins automatisieren.

Toter Code

Warum das wichtig ist

Toter Code sammelt sich in KI-Sessions an — alte Ansätze, die zurückbleiben. Er verwirrt sowohl dich als auch zukünftige KI-Prompts. Halte den Code sauber: was nicht gebraucht wird, wird gelöscht.

MAJOR Quick Fix

Gesamtes Modul server/whisper_api.py ist unbenutzt

server/whisper_api.py:1
Was passiert hier

server/whisper_api.py wird von keinem anderen Modul importiert. Die Whisper-Integration erfolgt direkt in transcribe.py.

Was passiert, wenn du es nicht behebst

Totes Modul verwirrt neue Entwickler und wird bei Refactoring-Aufgaben versehentlich mitgeaendert.

So behebst du es
  1. Modul loeschen, da es nirgends verwendet wird
  2. Falls gewuenscht: transcribe.py refactoren, um whisper_api.py tatsaechlich zu nutzen
KI-Fix-Prompt

"Delete server/whisper_api.py — it is not imported anywhere. Run grep -r "whisper_api" to confirm no references exist."

Code
# server/whisper_api.py — 180 lines, imported by nobody
class WhisperClient:
    def __init__(self, api_key, model="medium"):
        ...
    def transcribe(self, audio_path, language="de"):
        ...
Was du dir merken solltest

Toter Code ist nicht kostenlos. Er kostet Aufmerksamkeit, erzeugt Verwirrung und kann Bugs verursachen, wenn er versehentlich geaendert wird.

MAJOR Quick Fix

14 unbenutzte Imports in 5 Dateien

server/app.py:3
Was passiert hier

14 importierte Module oder Funktionen werden nie verwendet: json, sys, re in app.py, hashlib und hmac in auth.py, u.a.

Was passiert, wenn du es nicht behebst

Unbenutzte Imports verlangsamen den Start, erhoehen den Memory-Footprint und verschleiern echte Abhaengigkeiten.

So behebst du es
  1. ruff oder autoflake verwenden, um unbenutzte Imports automatisch zu entfernen
  2. isort fuer konsistente Import-Sortierung einrichten
  3. Pre-commit Hook fuer Import-Checks einrichten
KI-Fix-Prompt

"Run ruff check --select F401 --fix server/ to auto-remove all unused imports. Then run ruff check --select I --fix server/ to sort remaining imports."

Code
import json  # unused
import sys  # unused
import re  # unused
from flask import Flask, request, jsonify, redirect  # redirect unused
Was du dir merken solltest

Einen Auto-Formatter (ruff, autoflake) verwenden, um unbenutzte Imports zu finden. Als Pre-commit Hook konfigurieren, um Anhaeufung zu verhindern.

MINOR Quick Fix

Auskommentiertes Feature: WebSocket-Streaming

server/app.py:245
Was passiert hier

65 Zeilen auskommentierter WebSocket-Code fuer Echtzeit-Streaming blockieren die Lesbarkeit ohne Nutzen.

Was passiert, wenn du es nicht behebst

Auskommentierter Code wird nie wieder aktiviert, verwirrt aber Entwickler und erschwert Code-Reviews.

So behebst du es
  1. Auskommentierten Code loeschen
  2. Falls das Feature geplant ist: als Issue/Ticket dokumentieren
  3. Git-History bewahrt den Code ohnehin
KI-Fix-Prompt

"Delete the commented-out WebSocket streaming code at server/app.py lines 245-310. Create a GitHub issue "Implement real-time WebSocket streaming" if the feature is still planned."

Code
# TODO: WebSocket streaming (v2)
# @socketio.on("audio_stream")
# def handle_stream(data):
#     chunk = data["chunk"]
#     # ... 60 more commented lines
Was du dir merken solltest

Auskommentierten Code loeschen. Git bewahrt die History. Tote Kommentare sind Rauschen, keine Dokumentation.

MINOR Quick Fix

Unerreichbarer Code nach fruehzeitigem Return

server/transcribe.py:290
Was passiert hier

Nach einem return-Statement in Zeile 288 folgen 12 Zeilen Code, die niemals ausgefuehrt werden.

Was passiert, wenn du es nicht behebst

Entwickler koennten annehmen, dass dieser Code ausgefuehrt wird, und Bugs auf Basis falscher Annahmen einbauen.

So behebst du es
  1. Unerreichbaren Code loeschen
  2. Pruefen, ob der fruehe Return korrekt ist oder ob der Code erreichbar sein sollte
KI-Fix-Prompt

"Delete the unreachable code at server/transcribe.py lines 290-302 (after the return at line 288). Verify the return at 288 is intentional."

Code
    return result  # line 288

    # Dead code below — never executes:
    logger.info("Post-processing complete")
    stats.record_transcription(len(result))
    cache.set(cache_key, result)
Was du dir merken solltest

Unerreichbarer Code nach Return-Statements ist ein haeufiger Fehler. Eine Linter-Regel verwenden, um ihn automatisch zu erkennen.

INFO Quick Fix

Veraltetes Datenbank-Migrationsskript noch vorhanden

server/utils.py:78
Was passiert hier

Eine Funktion migrate_v1_to_v2() in utils.py wurde fuer eine einmalige Datenmigration geschrieben und wird nie wieder aufgerufen.

Was passiert, wenn du es nicht behebst

Minimales Risiko, aber erhoeht die kognitive Last beim Lesen von utils.py.

So behebst du es
  1. Funktion loeschen oder in ein separates Migrations-Verzeichnis verschieben
KI-Fix-Prompt

"Delete the migrate_v1_to_v2() function at server/utils.py lines 78-120. It was a one-time migration and is no longer called."

Code
def migrate_v1_to_v2():
    """One-time migration from v1 schema to v2. Run once, then delete."""
    # ... 40 lines of migration logic
    # Last run: 2024-08-15
Was du dir merken solltest

Einmalige Skripte sollten in einem separaten Verzeichnis (z.B. migrations/) leben oder nach Ausfuehrung geloescht werden.

Code-Qualität

Warum das wichtig ist

KI wiederholt sich zwischen Prompts. Inkonsistente Benennung, doppelte Funktionen. Jedes Problem ist klein, aber zusammen wird Code unwartbar. Prüfe regelmäßig.

MAJOR Quick Fix

Blankes except faengt SystemExit und KeyboardInterrupt

server/transcribe.py:198
Was passiert hier

except: ohne spezifische Exception faengt alles ein, einschliesslich SystemExit, KeyboardInterrupt und MemoryError.

Was passiert, wenn du es nicht behebst

Prozess kann nicht sauber beendet werden. Schwerwiegende Systemfehler werden verschluckt und bleiben unbemerkt.

So behebst du es
  1. except: durch except Exception: ersetzen
  2. Noch besser: spezifische Exceptions fangen (requests.Timeout, openai.APIError)
  3. Logging fuer gefangene Exceptions hinzufuegen
KI-Fix-Prompt

"In server/transcribe.py, replace all bare except: clauses with except Exception as e: and add logging.exception("...") calls."

Code
try:
    result = process_audio(chunk)
except:  # catches EVERYTHING
    result = ""  # silently returns empty string
Was du dir merken solltest

Niemals blankes except: verwenden. Immer spezifische Exceptions fangen oder mindestens except Exception.

MAJOR Aufwendig

Globaler veraenderbarer Zustand auf Modulebene

server/transcribe.py:12
Was passiert hier

Mehrere veraenderbare globale Variablen (active_jobs, cache_dict, stats_counter) werden ohne Synchronisation zwischen Requests geteilt.

Was passiert, wenn du es nicht behebst

Race Conditions unter Last koennen zu Datenverlust, korrupten Zaehlerstaenden oder Cache-Inkonsistenzen fuehren.

So behebst du es
  1. Globale Variablen durch thread-sichere Alternativen ersetzen (threading.Lock)
  2. Redis fuer geteilten Zustand verwenden
  3. Flask-Kontext oder Dependency Injection nutzen
KI-Fix-Prompt

"Replace global mutable state in server/transcribe.py with thread-safe alternatives: use threading.Lock for active_jobs, use Flask-Caching for cache_dict, use Redis or atomic operations for stats_counter."

Code
active_jobs = {}  # mutable global, shared across threads
cache_dict = {}  # mutable global, no TTL, no size limit
stats_counter = {"total": 0, "errors": 0}  # race condition!
Was du dir merken solltest

Globaler veraenderbarer Zustand ist der Feind von nebenlaeufigem Code. Thread-sichere Strukturen oder externe State-Stores verwenden.

MINOR Quick Fix

Magische Zahlen in der Audio-Verarbeitung

server/audio.py:34
Was passiert hier

Zahlenwerte wie 16000, 0.015, 0.3, 512 werden direkt im Code verwendet ohne erklaerende Konstanten.

Was passiert, wenn du es nicht behebst

Schwer zu verstehen was die Zahlen bedeuten. Aenderungen erfordern Suchen-und-Ersetzen ueber mehrere Dateien.

So behebst du es
  1. Benannte Konstanten definieren (SAMPLE_RATE, SILENCE_THRESHOLD, MIN_SILENCE_DURATION)
  2. Konstanten in config.py zentralisieren
KI-Fix-Prompt

"Extract magic numbers in server/audio.py to named constants: SAMPLE_RATE = 16000, SILENCE_THRESHOLD = 0.015, MIN_SILENCE_SECONDS = 0.3, FFT_SIZE = 512."

Code
audio = audio.set_frame_rate(16000)  # what is 16000?
if amplitude < 0.015:  # what threshold?
    if silence_frames > int(16000 * 0.3):  # ??
Was du dir merken solltest

Jede magische Zahl benennen. SAMPLE_RATE = 16000 ist selbstdokumentierend; 16000 allein nicht.

MINOR Mittel

Inkonsistentes Fehler-Antwortformat

server/app.py:45
Was passiert hier

Verschiedene Endpunkte geben Fehler in unterschiedlichen Formaten zurueck: mal {"error": "..."}, mal {"message": "..."}, mal Klartext.

Was passiert, wenn du es nicht behebst

Clients muessen verschiedene Fehlerformate behandeln, was zu unzuverlaessiger Fehleranzeige fuehrt.

So behebst du es
  1. Einheitlichen Error-Handler mit Flask errorhandler() erstellen
  2. Konsistentes Format definieren: {"error": {"code": "...", "message": "..."}}
  3. Alle Endpunkte auf einheitliches Format umstellen
KI-Fix-Prompt

"Create an error handler in server/app.py using @app.errorhandler that returns {"error": {"code": status_code, "message": str(error)}} for all error responses."

Code
# Endpoint A:
return jsonify({"error": "File too large"}), 400
# Endpoint B:
return jsonify({"message": "Invalid format"}), 422
# Endpoint C:
return "Server error", 500
Was du dir merken solltest

Fehlerantworten in der API standardisieren. Clients sollten Fehler ueberall gleich parsen koennen.

MINOR Quick Fix

Keine Eingabelaengen-Validierung bei Textfeldern

server/models.py:23
Was passiert hier

Textfelder wie title und notes akzeptieren beliebig lange Strings ohne Laengenbeschraenkung auf Anwendungsebene.

Was passiert, wenn du es nicht behebst

Extrem lange Eingaben koennen die Datenbank belasten und UI-Elemente brechen.

So behebst du es
  1. Maximale Laenge auf Modell-Ebene mit String(255) definieren
  2. Validierung vor dem Speichern durchfuehren
  3. Client-seitig maxlength-Attribut setzen
KI-Fix-Prompt

"Add length constraints to server/models.py: title = Column(String(200), nullable=False), notes = Column(String(5000)). Add validation in the route handlers."

Code
class Transcription(db.Model):
    title = db.Column(db.String)  # no length limit
    notes = db.Column(db.Text)  # no length limit
Was du dir merken solltest

Immer maximale Laengen fuer benutzerbereitgestellte Textfelder definieren. Unbegrenzte Eingaben sind ein Sicherheits- und Stabilitaetsrisiko.

CRITICAL Mittel

Keine Fehlerbehandlung bei Whisper-API-Aufrufen

server/transcribe.py:156
Was passiert hier

API-Aufrufe an den Whisper-Service haben keinen Timeout, kein Retry und keine spezifische Fehlerbehandlung. Ein 500er oder Timeout fuehrt zum Absturz des gesamten Request-Handlers.

Was passiert, wenn du es nicht behebst

Transiente API-Fehler fuehren zu komplettem Fehlschlag der Transkription. Benutzer verlieren ihre Aufnahme ohne Fehlermeldung.

So behebst du es
  1. Timeout fuer API-Aufrufe setzen (z.B. 30 Sekunden)
  2. Retry-Logik mit exponentiellem Backoff implementieren
  3. Spezifische Fehler abfangen und benutzerfreundliche Meldungen zurueckgeben
KI-Fix-Prompt

"Wrap Whisper API calls in server/transcribe.py with tenacity retry decorator: @retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=10)). Add timeout=30 to requests."

Code
response = openai.audio.transcriptions.create(
    model=WHISPER_MODEL,
    file=audio_chunk,
    language=language
)  # no timeout, no retry, no error handling
Was du dir merken solltest

Alle externen API-Aufrufe brauchen Timeout, Retry und Fehlerbehandlung. Davon ausgehen, dass das Netzwerk ausfallen wird.

INFO Mittel

Logging verwendet print() statt logging-Modul

server/transcribe.py:42
Was passiert hier

Das gesamte Projekt verwendet print() fuer Ausgaben statt des Python logging-Moduls. 47 print()-Aufrufe verteilt auf 6 Dateien.

Was passiert, wenn du es nicht behebst

Keine Log-Levels, keine strukturierte Ausgabe, keine Moeglichkeit Logs in Produktion zu filtern oder an Log-Aggregatoren zu senden.

So behebst du es
  1. Python logging-Modul konfigurieren
  2. print() durch logger.info/warning/error ersetzen
  3. Strukturiertes Logging (JSON) fuer Produktion einrichten
KI-Fix-Prompt

"Replace all print() calls with proper logging: import logging; logger = logging.getLogger(__name__); replace print("Error:...") with logger.error("..."), print("Processing...") with logger.info("...")."

Code
print(f"Processing file: {filename}")  # should be logger.info
print(f"ERROR: {str(e)}")  # should be logger.error
print(f"Transcription complete in {elapsed}s")  # should be logger.info
Was du dir merken solltest

Das logging-Modul von Tag eins verwenden. Strukturierte Logs mit Levels sind essentiell fuer Produktion-Debugging.

Dokumentation

Warum das wichtig ist

Dokumentation ist die Brücke zwischen dir und deinem zukünftigen Ich (und der KI). Fehlende Docs = häufigster Grund, warum KI-Projekte aufgegeben werden. Die KI kann sie schreiben — du musst nur fragen.

MAJOR Mittel

README enthaelt nur den Projekttitel

README.md:1
Was passiert hier

Die README.md enthaelt nur "# codedictate" und eine einzeilige Beschreibung. Installation, Nutzung, API-Dokumentation und Architektur fehlen.

Was passiert, wenn du es nicht behebst

Neue Entwickler koennen das Projekt nicht aufsetzen oder verstehen, ohne den Code zu lesen.

So behebst du es
  1. Abschnitte hinzufuegen: Installation, Quickstart, API-Dokumentation, Architektur
  2. Systemvoraussetzungen dokumentieren (Python-Version, FFmpeg, etc.)
  3. Beispiel-Befehle fuer Setup und Start bereitstellen
KI-Fix-Prompt

"Expand README.md with sections: ## Features, ## Requirements (Python 3.10+, FFmpeg, OpenAI API key), ## Installation, ## Quick Start, ## API Endpoints, ## Configuration, ## Testing."

Code
# codedictate
Voice-to-text dictation tool.
Was du dir merken solltest

Eine gute README ist die kosteneffektivste Dokumentation. Sie spart Stunden an Einarbeitungszeit pro Entwickler.

MINOR Aufwendig

Keine API-Dokumentation oder Schema

server/app.py:1
Was passiert hier

Keiner der 8 API-Endpunkte hat Dokumentation. Weder OpenAPI/Swagger noch inline Docstrings beschreiben Request/Response-Formate.

Was passiert, wenn du es nicht behebst

Frontend-Entwickler muessen den Backend-Code lesen, um die API zu verstehen. Integration wird zum Ratespiel.

So behebst du es
  1. flask-openapi3 oder flasgger fuer automatische API-Doku installieren
  2. Mindestens Docstrings mit Input/Output-Beschreibung pro Route
  3. OpenAPI-Spec als YAML pflegen
KI-Fix-Prompt

"Add docstrings to all route handlers in server/app.py with format: Args (JSON body fields), Returns (response format), Raises (error cases). Consider adding flask-openapi3."

Code
@app.route("/transcribe", methods=["POST"])
def transcribe():
    # No docstring, no type hints, no documentation
    file = request.files["audio"]
    ...
Was du dir merken solltest

API mindestens mit Docstrings dokumentieren. Fuer oeffentliche APIs OpenAPI/Swagger fuer interaktive Dokumentation verwenden.

MINOR Mittel

Fehlende Docstrings bei 23 von 28 Funktionen

server/transcribe.py:1
Was passiert hier

82% der Funktionen im Projekt haben keinen Docstring. Nur 5 der 28 Funktionen beschreiben was sie tun, was sie erwarten und was sie zurueckgeben.

Was passiert, wenn du es nicht behebst

Entwickler muessen die Implementierung lesen, um die Schnittstelle zu verstehen. Erhoeht die Einarbeitungszeit erheblich.

So behebst du es
  1. Docstrings fuer alle oeffentlichen Funktionen ergaenzen
  2. Format: Kurzbeschreibung, Args, Returns, Raises
  3. Am wichtigsten: oeffentliche API-Funktionen und komplexe Logik
KI-Fix-Prompt

"Add Google-style docstrings to all public functions in server/transcribe.py, server/audio.py, and server/models.py. Include Args, Returns, and Raises sections."

Code
def chunk_audio(audio_data, sr=16000):
    # No docstring — what does it return? What format is audio_data?
    ...

def postprocess(text, language):
    # No docstring — what postprocessing? What languages supported?
    ...
Was du dir merken solltest

Docstrings sind der Vertrag zwischen Funktionen. Sie sollten beantworten: was tut sie, was braucht sie, was gibt sie zurueck.

MINOR Quick Fix

Keine Dokumentation der Umgebungsvariablen

server/config.py:1
Was passiert hier

Es gibt weder eine .env.example noch Dokumentation welche Umgebungsvariablen benoetigt werden.

Was passiert, wenn du es nicht behebst

Neue Entwickler oder Deployments scheitern, weil benoetigte Variablen nicht gesetzt sind.

So behebst du es
  1. .env.example erstellen mit allen benoetigten Variablen
  2. Kommentare mit Beschreibung und Beispielwerten
  3. In README auf .env.example verweisen
KI-Fix-Prompt

"Create .env.example with all environment variables used in server/config.py: OPENAI_API_KEY, DATABASE_URL, FLASK_SECRET_KEY, FLASK_DEBUG, WHISPER_MODEL. Add descriptions as comments."

Code
# config.py uses these but nobody documents them:
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")  # required but undocumented
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///local.db")
SECRET_KEY = os.getenv("FLASK_SECRET_KEY", "dev-key-change-me")
Was du dir merken solltest

Eine .env.example-Datei ist eine guenstige Versicherung. Sie dokumentiert Anforderungen und verhindert Deployment-Fehler.

INFO Mittel

Keine Architektur-Entscheidungsaufzeichnungen

README.md:1
Was passiert hier

Keine Dokumentation darueber, warum bestimmte Technologie-Entscheidungen getroffen wurden (Whisper-Modellwahl, SQLite vs. PostgreSQL, Client-Architektur).

Was passiert, wenn du es nicht behebst

Zukuenftige Entwickler wiederholen Evaluierungen oder aendern Entscheidungen ohne den Kontext zu kennen.

So behebst du es
  1. docs/adr/ Verzeichnis erstellen
  2. ADR fuer jede wesentliche Entscheidung schreiben (Lightweight-Format)
  3. Kontext, Entscheidung, Konsequenzen dokumentieren
KI-Fix-Prompt

"Create docs/adr/001-whisper-model-selection.md and docs/adr/002-sqlite-for-development.md using the lightweight ADR template (Context, Decision, Consequences)."

Code
# No architecture documentation found.
# Questions that remain unanswered:
# - Why Whisper medium model instead of large?
# - Why SQLite instead of PostgreSQL?
# - Why desktop client instead of web-only?
Was du dir merken solltest

Architecture Decision Records (ADRs) verhindern das Wiederholen vergangener Diskussionen. Selbst Ein-Absatz-ADRs sparen zukuenftig Zeit.

Best Practices

Warum das wichtig ist

KI kennt Muster, folgt ihnen aber nicht immer. Sie mischt async/await mit .then(), ignoriert Konventionen. Sage der KI, welche Muster dein Projekt verwendet — sie wird sich daran halten.

MAJOR Quick Fix

Keine .gitignore-Eintraege fuer sensible Dateien

.gitignore:1
Was passiert hier

Die .gitignore-Datei enthaelt keine Eintraege fuer .env, *.pem, *.key oder Upload-Verzeichnisse. Sensible Dateien koennten versehentlich committed werden.

Was passiert, wenn du es nicht behebst

Ein versehentliches git add . committet API-Schluessel, Zertifikate und Benutzerdaten ins Repository.

So behebst du es
  1. .env, *.pem, *.key, uploads/, *.sqlite zu .gitignore hinzufuegen
  2. gitignore.io Template fuer Python/Flask verwenden
  3. git-secrets als Pre-commit Hook installieren
KI-Fix-Prompt

"Update .gitignore to include: .env, .env.*, *.pem, *.key, uploads/, *.sqlite, *.db, __pycache__/, .pytest_cache/, htmlcov/."

Code
# .gitignore (incomplete):
__pycache__/
*.pyc
# Missing: .env, *.pem, *.key, uploads/, *.sqlite
Was du dir merken solltest

Jedes Projekt mit einer umfassenden .gitignore beginnen. gitignore.io oder GitHub-Templates als Basis verwenden.

MAJOR Quick Fix

Keine Virtual-Environment-Konfiguration

setup.py:1
Was passiert hier

Keine Dokumentation oder Konfiguration fuer Virtual Environments. Entwickler installieren Abhaengigkeiten moeglicherweise global.

Was passiert, wenn du es nicht behebst

Globale Installationen fuehren zu Versionskonflikten zwischen Projekten und machen Builds nicht reproduzierbar.

So behebst du es
  1. Makefile oder setup.sh mit venv-Erstellung bereitstellen
  2. In README dokumentieren: python -m venv .venv && source .venv/bin/activate
  3. .venv/ zu .gitignore hinzufuegen
KI-Fix-Prompt

"Create a Makefile with: setup target (creates venv, installs deps), run target (starts server), test target (runs tests). Add .venv/ to .gitignore."

Code
# No Makefile, no setup script, no venv documentation
# Developers are expected to... guess?
# pip install -r requirements.txt  # global? venv? who knows!
Was du dir merken solltest

Immer Virtual Environments verwenden. Den Setup-Prozess dokumentieren. Auf einen Befehl reduzieren.

MINOR Quick Fix

Kein Health-Check-Endpunkt

server/app.py:1
Was passiert hier

Kein /health oder /readiness Endpunkt fuer Monitoring, Load Balancer oder Container-Orchestrierung.

Was passiert, wenn du es nicht behebst

Load Balancer und Monitoring-Tools koennen den Zustand der Anwendung nicht pruefen.

So behebst du es
  1. GET /health Endpunkt hinzufuegen, der DB-Verbindung und API-Erreichbarkeit prueft
  2. HTTP 200 wenn gesund, 503 wenn nicht
  3. In Docker HEALTHCHECK-Direktive verwenden
KI-Fix-Prompt

"Add a /health endpoint to server/app.py that checks: database connectivity (SELECT 1), returns {"status": "healthy", "db": "ok"} or 503 with details."

Code
# No health check endpoint exists.
# Docker and monitoring have no way to check if the app is running correctly.
Was du dir merken solltest

Health-Check-Endpunkte sind essentiell fuer Produktion. Sie ermoeglichen automatisierte Wiederherstellung und Monitoring.

CRITICAL Quick Fix

Geheimer Schluessel verwendet vorhersagbaren Standard

server/config.py:8
Was passiert hier

Der Flask SECRET_KEY hat einen hartcodierten Fallback "dev-key-change-me", der in Produktion verwendet wird, wenn die Umgebungsvariable nicht gesetzt ist.

Was passiert, wenn du es nicht behebst

Mit bekanntem Secret Key koennen Angreifer Session-Cookies signieren und Admin-Zugriff erlangen.

So behebst du es
  1. Fallback entfernen — Anwendung sollte ohne SECRET_KEY nicht starten
  2. secrets.token_hex(32) fuer Produktion verwenden
  3. Startup-Check hinzufuegen der bei fehlendem Key abbricht
KI-Fix-Prompt

"In server/config.py, change SECRET_KEY to raise an error if not set: SECRET_KEY = os.environ["FLASK_SECRET_KEY"] # no fallback, must be set."

Code
SECRET_KEY = os.getenv("FLASK_SECRET_KEY", "dev-key-change-me")  # predictable!
Was du dir merken solltest

Niemals Standardwerte fuer sicherheitskritische Konfiguration bereitstellen. Laut fehlschlagen statt unsicher laufen.

INFO Quick Fix

Keine automatisierte Code-Formatierung

setup.py:1
Was passiert hier

Kein Code-Formatter (Black, Ruff) konfiguriert. Der Code hat inkonsistente Einrueckung, Zeilenlaengen und String-Quoting.

Was passiert, wenn du es nicht behebst

Inkonsistenter Stil erzeugt unnoetige Diff-Noise in Code-Reviews und verlangsamt das Lesen.

So behebst du es
  1. ruff format konfigurieren (pyproject.toml)
  2. Pre-commit Hook fuer automatische Formatierung einrichten
  3. Einmalig auf gesamtes Projekt ausfuehren
KI-Fix-Prompt

"Add ruff configuration to pyproject.toml: [tool.ruff] line-length = 100. Create .pre-commit-config.yaml with ruff check and ruff format hooks. Run ruff format . on the entire project."

Code
# Inconsistent style throughout:
some_var="no spaces"  # line 12
other_var = "with spaces"  # line 13
very_long_function_call(argument1, argument2, argument3, argument4, argument5)  # 120+ chars
Was du dir merken solltest

Einen Formatter waehlen (ruff, black), einmal konfigurieren, nie wieder ueber Stil diskutieren.

Abhängigkeiten

Warum das wichtig ist

KI liebt es, Pakete hinzuzufügen — manchmal unnötig. Jede Abhängigkeit ist ein Risiko. Frage immer, ob eine native Lösung existiert. Weniger Abhängigkeiten = weniger Angriffsfläche.

MAJOR Mittel

Nicht-gepinnte transitive Abhaengigkeiten

requirements.txt:1
Was passiert hier

Nur 8 direkte Abhaengigkeiten sind gepinnt, aber deren transitive Abhaengigkeiten nicht. pip install kann unterschiedliche Versionen auf verschiedenen Maschinen installieren.

Was passiert, wenn du es nicht behebst

Builds sind nicht reproduzierbar. "Works on my machine" wird zum Standard-Problem.

So behebst du es
  1. pip-compile (pip-tools) verwenden, um eine vollstaendige requirements.txt zu generieren
  2. Oder: Poetry/PDM mit Lock-Datei verwenden
  3. requirements.txt und Lock-Datei in Git einchecken
KI-Fix-Prompt

"Install pip-tools (pip install pip-tools). Create requirements.in with direct deps. Run pip-compile requirements.in to generate a fully pinned requirements.txt with hashes."

Code
# requirements.txt — only direct deps pinned:
Flask==2.2.3
openai==1.6.1
SQLAlchemy==2.0.25
# But what version of Jinja2? Markupsafe? Click? Unknown!
Was du dir merken solltest

Immer alle Abhaengigkeiten einschliesslich transitiver pinnen. pip-compile, Poetry oder PDM fuer reproduzierbare Builds verwenden.

MINOR Quick Fix

Kein Lizenz-Audit der Abhaengigkeiten

requirements.txt:1
Was passiert hier

Keine Pruefung ob die Lizenzen der 8 Abhaengigkeiten mit dem geplanten Lizenzmodell kompatibel sind.

Was passiert, wenn du es nicht behebst

Falls das Projekt kommerziell vertrieben wird, koennten GPL-lizenzierte Abhaengigkeiten rechtliche Probleme verursachen.

So behebst du es
  1. pip-licenses installieren und ausfuehren
  2. Kompatibilitaet mit geplantem Lizenzmodell pruefen
  3. Ergebnis in LICENSES.md dokumentieren
KI-Fix-Prompt

"Run pip-licenses --format=table to audit all dependency licenses. Create LICENSES.md documenting the findings."

Code
# Unknown licenses in dependency tree:
# Flask — BSD-3-Clause (OK)
# openai — Apache-2.0 (OK)
# But what about transitive deps?
Was du dir merken solltest

Abhaengigkeitslizenzen frueh pruefen, besonders bei geplanter kommerzieller Verbreitung.

CRITICAL Mittel

Flask 2.2.3 hat bekannte Sicherheitsluecke (CVE-2023-30861)

requirements.txt:1
Was passiert hier

Flask 2.2.3 ist anfaellig fuer Session-Cookie-Manipulation (CVE-2023-30861). Die aktuelle Version ist 3.1.x.

Was passiert, wenn du es nicht behebst

Angreifer koennen Session-Cookies manipulieren und sich als andere Benutzer ausgeben.

So behebst du es
  1. Flask auf >= 3.0.0 aktualisieren
  2. Breaking Changes in Flask 3.0 Migration Guide pruefen
  3. Nach Update alle Tests ausfuehren
KI-Fix-Prompt

"In requirements.txt, update Flask from 2.2.3 to 3.1.0. Review the Flask 3.0 migration guide for breaking changes. Run tests after update."

Code
# requirements.txt
Flask==2.2.3  # CVE-2023-30861: session cookie vulnerability
Werkzeug==2.2.3  # also outdated, update together
Was du dir merken solltest

pip-audit oder safety check regelmaessig ausfuehren. Gepinnte Versionen erfordern aktive Wartung, um sicher zu bleiben.

INFO Quick Fix

setup.py verwendet veraltete Praktiken

setup.py:1
Was passiert hier

Das Projekt verwendet setup.py statt pyproject.toml. setup.py wird von PEP 517/518 zugunsten von pyproject.toml abgeloest.

Was passiert, wenn du es nicht behebst

Minimales Risiko kurzfristig, aber zukuenftiges Tooling wird pyproject.toml voraussetzen.

So behebst du es
  1. setup.py zu pyproject.toml migrieren
  2. Build-System auf setuptools mit pyproject.toml umstellen
KI-Fix-Prompt

"Convert setup.py to pyproject.toml following PEP 621. Use [build-system] requires = ["setuptools>=68.0"]. Move all metadata to [project] table."

Code
# setup.py (deprecated pattern):
from setuptools import setup
setup(
    name="codedictate",
    version="0.1.0",
    install_requires=[...]
)
Was du dir merken solltest

pyproject.toml fuer neue Python-Projekte verwenden. Es ist der moderne Standard gemaess PEP 517/518/621.

Sicherheit

Warum das wichtig ist

KI-generierter Code enthält oft Sicherheitslücken — hartcodierte Schlüssel, fehlende Validierung, SQL-Verkettung. Diese sind unsichtbar: der Code „funktioniert“, ist aber wie eine offene Haustür. Prüfe bei jedem KI-generierten Code die Eingabevalidierung und ob Geheimnisse im Code stehen.

MAJOR Mittel

Unbeschraenkter Datei-Upload ohne Validierung

server/app.py:67
Was passiert hier

Der Audio-Upload-Endpunkt akzeptiert jede Datei ohne Pruefung des Dateityps, der Groesse oder des Inhalts.

Was passiert, wenn du es nicht behebst

Angreifer koennen ausfuehrbaren Code hochladen oder den Server durch ueberdimensionierte Dateien ueberlasten.

So behebst du es
  1. Erlaubte Dateitypen (WAV, MP3, FLAC, OGG) validieren
  2. Maximale Dateigrösse (z.B. 50 MB) durchsetzen
  3. MIME-Typ und Magic Bytes pruefen
KI-Fix-Prompt

"Add file validation to the /upload endpoint in server/app.py: check file extension against ALLOWED_EXTENSIONS, enforce MAX_CONTENT_LENGTH, and verify magic bytes."

Code
@app.route("/upload", methods=["POST"])
def upload_audio():
    file = request.files["audio"]
    file.save(os.path.join(UPLOAD_DIR, file.filename))
Was du dir merken solltest

Datei-Uploads immer validieren: Typ, Groesse und Inhalt pruefen. Dem vom Client bereitgestellten Dateinamen niemals vertrauen.

MAJOR Quick Fix

Path-Traversal durch benutzergesteuerten Dateinamen

server/app.py:71
Was passiert hier

Der Dateiname wird direkt vom Benutzer uebernommen, ohne secure_filename() oder aehnliche Bereinigung.

Was passiert, wenn du es nicht behebst

Angreifer koennen Dateien in beliebige Verzeichnisse schreiben (z.B. ../../etc/crontab).

So behebst du es
  1. werkzeug.utils.secure_filename() verwenden
  2. Eigene UUIDs als Dateinamen generieren
  3. Upload-Verzeichnis mit Berechtigungen absichern
KI-Fix-Prompt

"In server/app.py line 71, replace file.filename with secure_filename(file.filename) from werkzeug.utils, or better yet, generate a UUID filename."

Code
file.save(os.path.join(UPLOAD_DIR, file.filename))
Was du dir merken solltest

Vom Benutzer bereitgestellte Dateinamen niemals direkt verwenden. secure_filename() nutzen oder eindeutige Namen serverseitig generieren.

MINOR Quick Fix

CORS erlaubt alle Urspruenge

server/app.py:18
Was passiert hier

CORS ist mit origins="*" konfiguriert, was Anfragen von jeder beliebigen Domain erlaubt.

Was passiert, wenn du es nicht behebst

Fremde Websites koennen API-Anfragen im Namen authentifizierter Benutzer stellen.

So behebst du es
  1. Erlaubte Origins auf die eigene Domain beschraenken
  2. In Entwicklung localhost erlauben, in Produktion nur die eigene Domain
KI-Fix-Prompt

"In server/app.py line 18, replace CORS(app, origins="*") with CORS(app, origins=os.environ.get("ALLOWED_ORIGINS", "http://localhost:3000").split(","))."

Code
CORS(app, origins="*")
Was du dir merken solltest

CORS auf die minimal notwendigen Urspruenge beschraenken. Wildcard-Origins umgehen die Same-Origin-Policy vollstaendig.

CRITICAL Quick Fix

Hartcodierter API-Schluessel im Quellcode

server/config.py:14
Was passiert hier

Der OpenAI API-Schluessel ist direkt im Quellcode hinterlegt und wird bei jedem Commit ins Repository uebertragen.

Was passiert, wenn du es nicht behebst

Angreifer koennen den API-Schluessel aus dem Git-Verlauf extrahieren und auf Ihre Kosten API-Aufrufe durchfuehren.

So behebst du es
  1. API-Schluessel in Umgebungsvariablen auslagern
  2. .env-Datei erstellen und in .gitignore aufnehmen
  3. Vorhandenen Schluessel sofort rotieren
KI-Fix-Prompt

"Replace the hardcoded OPENAI_API_KEY in server/config.py with os.environ.get("OPENAI_API_KEY") and add a .env.example file."

Code
OPENAI_API_KEY = "sk-proj-abc123def456ghi789"
Was du dir merken solltest

API-Schluessel und Secrets niemals in die Versionskontrolle committen. Umgebungsvariablen oder einen Secrets-Manager verwenden.

CRITICAL Mittel

SQL-Injection durch Roh-Abfrage

server/models.py:87
Was passiert hier

Benutzereingaben werden direkt in eine SQL-Abfrage eingesetzt, ohne Parametrisierung oder Escaping.

Was passiert, wenn du es nicht behebst

Angreifer koennen beliebige SQL-Befehle ausfuehren, Daten stehlen oder die gesamte Datenbank loeschen.

So behebst du es
  1. String-Interpolation durch parametrisierte Abfragen ersetzen
  2. SQLAlchemy ORM-Methoden statt Raw SQL verwenden
  3. Eingabevalidierung als zusaetzliche Schutzschicht hinzufuegen
KI-Fix-Prompt

"In server/models.py line 87, replace the f-string SQL query with a parameterized SQLAlchemy query using bindparams or ORM methods."

Code
db.execute(f"SELECT * FROM transcriptions WHERE user_id = '{user_id}' AND title LIKE '%{search}%'")
Was du dir merken solltest

Immer parametrisierte Abfragen verwenden. Benutzereingaben niemals direkt in SQL-Strings einsetzen.

CRITICAL Aufwendig

Fehlende Authentifizierung bei Admin-Endpunkten

server/app.py:203
Was passiert hier

Die Admin-Routen (/admin/users, /admin/stats) sind ohne jegliche Authentifizierung zugaenglich.

Was passiert, wenn du es nicht behebst

Jeder kann Benutzerdaten einsehen, Konten loeschen und Systemeinstellungen aendern.

So behebst du es
  1. Authentifizierungs-Middleware implementieren
  2. JWT- oder Session-basierte Auth fuer Admin-Routen hinzufuegen
  3. Rollen-basierte Zugriffskontrolle (RBAC) einfuehren
KI-Fix-Prompt

"Add a @require_admin decorator to all /admin/* routes in server/app.py. Implement JWT-based authentication in server/auth.py."

Code
@app.route("/admin/users")
def admin_users():
    users = User.query.all()
    return jsonify([u.to_dict() for u in users])
Was du dir merken solltest

Jeder Admin-Endpunkt muss Authentifizierung und Autorisierung erfordern. Verteidigung in der Tiefe bedeutet Pruefung auf jeder Ebene.

CRITICAL Quick Fix

Flask Debug-Modus in Produktionskonfiguration aktiviert

server/app.py:312
Was passiert hier

Die Anwendung wird mit debug=True gestartet, was den interaktiven Debugger und Code-Reload in der Produktion aktiviert.

Was passiert, wenn du es nicht behebst

Der Werkzeug-Debugger erlaubt Remote Code Execution. Angreifer koennen beliebigen Python-Code auf dem Server ausfuehren.

So behebst du es
  1. debug=True durch Umgebungsvariable steuern
  2. In Produktion FLASK_DEBUG=0 setzen
  3. Gunicorn oder uWSGI als Produktions-WSGI-Server verwenden
KI-Fix-Prompt

"In server/app.py line 312, replace app.run(debug=True) with app.run(debug=os.environ.get("FLASK_DEBUG", "0") == "1")."

Code
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
Was du dir merken solltest

Debug-Modus niemals in Produktion aktivieren. Er offenbart einen interaktiven Debugger, der beliebige Code-Ausfuehrung ermoeglicht.

INFO Mittel

Kein Rate-Limiting auf API-Endpunkten

server/app.py:1
Was passiert hier

Keiner der API-Endpunkte hat Rate-Limiting implementiert, weder fuer Authentifizierung noch fuer ressourcenintensive Operationen.

Was passiert, wenn du es nicht behebst

Angreifer koennen Brute-Force-Angriffe durchfuehren oder den Server durch Massenanfragen ueberlasten.

So behebst du es
  1. Flask-Limiter installieren und konfigurieren
  2. Strenge Limits fuer Auth-Endpunkte setzen (z.B. 5/Minute)
  3. Moderate Limits fuer Upload-Endpunkte (z.B. 10/Stunde)
KI-Fix-Prompt

"Add Flask-Limiter to server/app.py. Apply @limiter.limit("5/minute") to auth endpoints and @limiter.limit("10/hour") to /upload."

Code
# No rate limiting configuration found anywhere in the project
Was du dir merken solltest

Rate-Limiting ist fuer alle oeffentlich zugaenglichen APIs unverzichtbar, besonders fuer Auth- und Upload-Endpunkte.

Bereit für deinen eigenen Report?

47 Findings in diesem Projekt. Wie viele hat deins?

Code analysieren — EUR 19 Zurück zur Startseite

Einmalig EUR 19 inkl. MwSt. · Kein Abo · Report in 15-45 Min. per E-Mail