Skip to content

Conversation

@TimInTech
Copy link
Owner

@TimInTech TimInTech commented Oct 3, 2025

Summary by Sourcery

Entferne übrig gebliebene Konfliktmarker und führe eine umfassende Bereinigung im gesamten Repository durch: überarbeite das Installer-Skript, optimiere die FastAPI-App und Pydantic-Schemas, räume die Test-Suite und freigegebenen Module auf und überarbeite die README-Dokumentation.

Enhancements:

  • Refactor install.sh, um Protokollierung, Fehlerbehandlung und Dienstkonfiguration zu vereinfachen.
  • Bereinige start_suite.py, shared/db, shared/shared_config und Skripte durch Entfernen von Legacy-Code und Duplikaten.
  • Optimiere die API-Implementierung in api/main und verbessere Pydantic-Validatoren in Schemas.

Documentation:

  • Überarbeite README.md mit strukturiertem Quickstart, Architekturdiagramm, API-Referenz und Sicherheitshinweisen.

Tests:

  • Konsolidiere und vereinfache Tests in test_api.py durch Entfernen von Duplikaten und Standardisieren von Fixtures.

Chores:

  • Entferne Merge-Konfliktmarker und auskommentierten Code im gesamten Codebasis für Konsistenz und Klarheit.
Original summary in English

Summary by Sourcery

Remove leftover conflict markers and perform a broad cleanup across the repository: refactor the installer script, streamline FastAPI app and pydantic schemas, tidy test suite and shared modules, and overhaul the README documentation.

Enhancements:

  • Refactor install.sh to simplify logging, error handling, and service setup.
  • Clean up start_suite.py, shared/db, shared/shared_config, and scripts by removing legacy code and duplicates.
  • Streamline API implementation in api/main and improve pydantic validators in schemas.

Documentation:

  • Revamp README.md with structured quickstart, architecture diagram, API reference, and security notes.

Tests:

  • Consolidate and simplify tests in test_api.py by removing duplicates and standardizing fixtures.

Chores:

  • Remove merge conflict markers and commented-out code throughout the codebase for consistency and clarity.

@TimInTech TimInTech merged commit 553c185 into main Oct 3, 2025
1 check failed
@sourcery-ai
Copy link

sourcery-ai bot commented Oct 3, 2025

Leitfaden für Reviewer

Dieser PR entfernt verbleibende Konfliktmarker und redundanten Code, refaktoriert den One-Click-Installer für Konsistenz und Einfachheit, überarbeitet die README mit strukturiertem Markdown und optimiert API, Schema, gemeinsam genutzte Module und Tests durch die Eliminierung von Duplikaten sowie die Verbesserung von Validatoren und Formatierung.

Änderungen auf Dateiebene

Änderung Details Dateien
Refaktorierung und Vereinheitlichung des install.sh-Skripts
  • Entfernung von Merge-Konfliktmarkern und alten doppelten Blöcken
  • Konsolidierung von Umgebungsvariablen, Logging-Helfern und Fehlerbehandlung
  • Vereinfachung von Systemprüfungen, Portprüfungen, Paketinstallation und Dienstkonfiguration
  • Optimierung von Health Checks und Zusammenfassungs-Ausgabe
install.sh
Überarbeitung der README-Dokumentation
  • Entfernung von Diff-Artefakten und Merge-Resten
  • Einführung von Badges, Quickstart, Architekturdiagramm und detaillierten Abschnitten
  • Neuformatierung der Feature-Liste, API-Referenz und Fehlerbehebungsanleitungen
README.md
Bereinigung und Konsolidierung der Test-Suite
  • Zusammenführung doppelter Fixtures und Entfernung redundanter Imports
  • Standardisierung der Test-Client- und Header-Konfiguration
  • Vereinfachung von Endpoint-Assertions und Entfernung veralteter Tests
tests/test_api.py
Optimierung des FastAPI-Anwendungscodes
  • Entfernung doppelter Docstrings und ungenutzter Imports
  • Standardisierung von Endpoint-Definitionen und Dependency Injection
  • Sicherstellung konsistenter Formatierung und nachgestellter Kommas
api/main.py
Konsolidierung von Pydantic-Schemas
  • Entfernung doppelter Modelldefinitionen
  • Aktualisierung der Validatoren für IP- und MAC-Felder auf den Pydantic v2-Stil
  • Entfernung veralteter Kommentare
api/schemas.py
Entfernung veralteter DB- und Konfigurationsgerüste
  • Entfernung der Legacy-Schema-Initialisierung und hartcodierter Pfade
  • Entfernung redundanter shared_config-Einträge und mkdir-Logik
  • Beibehaltung nur der wesentlichen Connection Factory
shared/db.py
shared/shared_config.py
Vereinfachung des Startup-Skripts
  • Eliminierung doppelten Thread-Launcher-Codes
  • Vereinheitlichung der Host-/Port-Konfiguration über Umgebungsvariablen
  • Bereinigung der Logging- und Asyncio-Serverstart-Logik
start_suite.py

Tipps und Befehle

Interaktion mit Sourcery

  • Neuen Review auslösen: Kommentieren Sie @sourcery-ai review im Pull Request.
  • Diskussionen fortsetzen: Antworten Sie direkt auf Sourcerys Review-Kommentare.
  • GitHub Issue aus einem Review-Kommentar generieren: Bitten Sie Sourcery, ein Issue aus einem Review-Kommentar zu erstellen, indem Sie darauf antworten. Sie können auch mit @sourcery-ai issue auf einen Review-Kommentar antworten, um ein Issue daraus zu erstellen.
  • Pull Request Titel generieren: Schreiben Sie @sourcery-ai an beliebiger Stelle im Pull Request Titel, um jederzeit einen Titel zu generieren. Sie können auch @sourcery-ai title im Pull Request kommentieren, um den Titel jederzeit (neu) zu generieren.
  • Pull Request Zusammenfassung generieren: Schreiben Sie @sourcery-ai summary an beliebiger Stelle im Pull Request Body, um jederzeit eine PR-Zusammenfassung genau dort zu generieren, wo Sie sie haben möchten. Sie können auch @sourcery-ai summary im Pull Request kommentieren, um die Zusammenfassung jederzeit (neu) zu generieren.
  • Reviewer-Leitfaden generieren: Kommentieren Sie @sourcery-ai guide im Pull Request, um den Reviewer-Leitfaden jederzeit (neu) zu generieren.
  • Alle Sourcery-Kommentare auflösen: Kommentieren Sie @sourcery-ai resolve im Pull Request, um alle Sourcery-Kommentare aufzulösen. Nützlich, wenn Sie alle Kommentare bereits behoben haben und sie nicht mehr sehen möchten.
  • Alle Sourcery-Reviews verwerfen: Kommentieren Sie @sourcery-ai dismiss im Pull Request, um alle bestehenden Sourcery-Reviews zu verwerfen. Besonders nützlich, wenn Sie mit einem neuen Review von vorne beginnen möchten – vergessen Sie nicht, @sourcery-ai review zu kommentieren, um einen neuen Review auszulösen!

Anpassung Ihrer Erfahrung

Greifen Sie auf Ihr Dashboard zu, um:

  • Review-Funktionen wie die von Sourcery generierte Pull-Request-Zusammenfassung, den Reviewer-Leitfaden und andere zu aktivieren oder zu deaktivieren.
  • Die Review-Sprache zu ändern.
  • Benutzerdefinierte Review-Anweisungen hinzuzufügen, zu entfernen oder zu bearbeiten.
  • Andere Review-Einstellungen anzupassen.

Hilfe erhalten

Original review guide in English

Reviewer's Guide

This PR removes residual conflict markers and redundant code, refactors the one-click installer for consistency and simplicity, overhauls the README with structured markdown, and streamlines API, schema, shared modules, and tests by eliminating duplicates and improving validators and formatting.

File-Level Changes

Change Details Files
Refactor and unify install.sh script
  • Removed merge conflict markers and old duplicate blocks
  • Consolidated environment variables, logging helpers, and error handling
  • Simplified system checks, port checks, package installation, and service setup
  • Streamlined health checks and summary output
install.sh
Overhaul README documentation
  • Removed diff artifacts and merge remnants
  • Introduced badges, quickstart, architecture diagram, and detailed sections
  • Reformatted feature list, API reference, and troubleshooting guides
README.md
Clean up and consolidate test suite
  • Merged duplicated fixtures and removed redundant imports
  • Standardized test client and header setup
  • Simplified endpoint assertions and removed obsolete tests
tests/test_api.py
Streamline FastAPI application code
  • Removed duplicate docstrings and unused imports
  • Standardized endpoint definitions and dependency injection
  • Ensured consistent formatting and trailing commas
api/main.py
Consolidate Pydantic schemas
  • Removed duplicate model definitions
  • Updated validators for IP and MAC fields to Pydantic v2 style
  • Trimmed obsolete comments
api/schemas.py
Remove outdated DB and config scaffolding
  • Stripped legacy schema initialization and hardcoded paths
  • Removed redundant shared_config entries and mkdir logic
  • Kept only essential connection factory
shared/db.py
shared/shared_config.py
Simplify startup script
  • Eliminated duplicate thread launcher code
  • Unified host/port configuration via environment variables
  • Cleaned logging and asyncio server launch logic
start_suite.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hallo zusammen – ich habe eure Änderungen geprüft – hier ist etwas Feedback:

Blockierende Probleme:

  • Ein potenzielles Autorisierungstoken wurde in einem Curl-Befehlsheader entdeckt, was die über Curl aufgerufene Ressource kompromittieren könnte. (Link)

Allgemeine Kommentare:

  • Entfernt den verbleibenden Konfliktmarker '->>>>>> main' am Anfang von README.md, um Merge-Konflikte vollständig zu beheben.
  • Überprüft, ob shared/db.py das Datenbankschema beim ersten Start immer noch initialisiert, da der SCHEMA-Ausführungsblock entfernt wurde.
  • In install.sh solltet ihr in Betracht ziehen, die Unbound-Root-Hints nur dann neu herunterzuladen, wenn sie älter als ein Schwellenwert sind (z.B. 30 Tage), um unnötige Downloads bei jedem Lauf zu vermeiden.
Prompt für KI-Agenten
Please address the comments from this code review:

## Overall Comments
- Remove the leftover conflict marker '->>>>>> main' at the top of README.md to fully clear merge conflicts.
- Verify that shared/db.py still initializes the database schema on first run, since the SCHEMA execution block was removed.
- In install.sh, consider only redownloading the Unbound root hints if they're older than a threshold (e.g. 30 days) to avoid unnecessary downloads on every run.

## Individual Comments

### Comment 1
<location> `install.sh:102-104` </location>
<code_context>
-EOF
-        
-        # Run Pi-hole installer
+    if ! command -v pihole >/dev/null; then
         curl -sSL https://install.pi-hole.net | bash /dev/stdin --unattended
     fi
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Die Pi-hole-Installation überprüft nicht den erfolgreichen Abschluss, bevor fortgefahren wird.

Überprüft den Exit-Status des Installers, bevor ihr mit der Konfiguration fortfahrt, um Fehler zu vermeiden, falls die Installation fehlschlägt.

```suggestion
    if ! command -v pihole >/dev/null; then
        curl -sSL https://install.pi-hole.net | bash /dev/stdin --unattended
        installer_status=$?
        if [ $installer_status -ne 0 ]; then
            error "Pi-hole installation failed (exit code $installer_status). Aborting."
            exit 1
        fi
    fi
```
</issue_to_address>

### Comment 2
<location> `install.sh:131-133` </location>
<code_context>
-    fi
-    
-    # Install Python dependencies
+    [[ -d .venv ]] || sudo -u "$INSTALL_USER" python3 -m venv .venv
     sudo -u "$INSTALL_USER" .venv/bin/pip install -U pip
     sudo -u "$INSTALL_USER" .venv/bin/pip install -r requirements.txt
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Die Erstellung der Virtualenv prüft nicht auf Fehler oder Python-Versionskompatibilität.

Überprüft den Exit-Status nach dem Versuch, die virtuelle Umgebung zu erstellen, und zeigt eine informative Fehlermeldung an, falls dies fehlschlägt.

```suggestion
    if [[ ! -d .venv ]]; then
        sudo -u "$INSTALL_USER" python3 -m venv .venv
        if [[ $? -ne 0 ]]; then
            echo "ERROR: Failed to create Python virtual environment (.venv)."
            echo "Please ensure Python 3 is installed and supports venv."
            exit 1
        fi
    fi
    sudo -u "$INSTALL_USER" .venv/bin/pip install -U pip
    sudo -u "$INSTALL_USER" .venv/bin/pip install -r requirements.txt
```
</issue_to_address>

### Comment 3
<location> `install.sh:162` </location>
<code_context>
-    
-    # Enable and start the service
+
+    cat > .env <<ENV
+SUITE_API_KEY=$SUITE_API_KEY
+SUITE_PORT=$PYTHON_SUITE_PORT
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Die Umgebungsdatei wird bedingungslos überschrieben, was Benutzeränderungen löschen könnte.

Bitte überprüft, ob .env existiert, bevor ihr sie überschreibt, und erwägt, den Benutzer aufzufordern oder die Datei zu sichern, um den Verlust benutzerdefinierter Einstellungen zu verhindern.
</issue_to_address>

### Comment 4
<location> `api/main.py:52` </location>
<code_context>
     return os.getenv("SUITE_API_KEY", "")


 def get_db() -> Generator[sqlite3.Connection, None, None]:
-    """Database dependency."""
+    """FastAPI dependency to provide a DB connection."""
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Die Datenbankverbindung wird nach Gebrauch nicht geschlossen, was zu Ressourcenlecks führen kann.

Bitte aktualisiert get_db, um sicherzustellen, dass die Datenbankverbindung nach Gebrauch ordnungsgemäß geschlossen wird, z.B. durch die Verwendung eines Kontextmanagers.
</issue_to_address>

### Comment 5
<location> `api/schemas.py:60` </location>
<code_context>
-    
-    @field_validator('mac_address')
+
+    @field_validator("mac_address")
     @classmethod
-    def validate_mac_address(cls, v):
</code_context>

<issue_to_address>
**suggestion:** Die MAC-Adressvalidierung ist zu vereinfacht und könnte gültige Formate ablehnen.

Der aktuelle Validator unterstützt keine MAC-Adressen mit Bindestrichen oder Großbuchstaben. Die Verwendung eines Regex oder einer speziellen Bibliothek würde die Kompatibilität verbessern.
</issue_to_address>

### Comment 6
<location> `tests/test_api.py:84-90` </location>
<code_context>
+    assert isinstance(resp.json(), list)


 def test_stats_endpoint(client, api_headers):
-    """Test statistics endpoint."""
-    response = client.get("/stats", headers=api_headers)
-    assert response.status_code == 200
-    data = response.json()
+    resp = client.get("/stats", headers=api_headers)
+    assert resp.status_code == 200
+    data = resp.json()
     assert "total_dns_logs" in data
     assert "total_devices" in data
     assert "recent_queries" in data
-    assert isinstance(data["total_dns_logs"], int)
-    assert isinstance(data["total_devices"], int)
</code_context>

<issue_to_address>
**suggestion (testing):** Der Test könnte Typen und Werte für die Felder der Statistikantwort überprüfen.

Das Wiederherstellen der Typzusicherungen für diese Felder hilft, die Konsistenz des Antwortschemas zu überprüfen.
</issue_to_address>

### Comment 7
<location> `README.md:96` </location>
<code_context>
your-api-key
</code_context>

<issue_to_address>
**security (curl-auth-header):** Ein potenzielles Autorisierungstoken wurde in einem Curl-Befehlsheader entdeckt, was die über Curl aufgerufene Ressource kompromittieren könnte.

*Quelle: gitleaks*
</issue_to_address>

### Comment 8
<location> `api/schemas.py:66` </location>
<code_context>
    @field_validator("mac_address")
    @classmethod
    def validate_mac_address(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        # Simple MAC address validation (XX:XX:XX:XX:XX:XX)
        if not (len(v) == 17 and v.count(":") == 5):
            raise ValueError("Invalid MAC address format")
        return v.lower()

</code_context>

<issue_to_address>
**suggestion (code-quality):** Vereinfacht den logischen Ausdruck unter Verwendung der De Morgan'schen Gesetze ([`de-morgan`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/de-morgan/))

```suggestion
        if len(v) != 17 or v.count(":") != 5:
```
</issue_to_address>

### Comment 9
<location> `start_suite.py:71` </location>
<code_context>
def main() -> None:
    """Main application entry point."""
    logger.info("Starting Pi-hole Suite...")

    # Verify API key
    api_key = os.environ.get("SUITE_API_KEY")
    if not api_key:
        logger.error("SUITE_API_KEY environment variable must be set")
        logger.info("Generate one with: openssl rand -hex 16")
        sys.exit(1)

    # Initialize database
    try:
        conn = init_db()
        logger.info("Database initialized successfully")
    except Exception as e:
        logger.error(f"Failed to initialize database: {e}")
        sys.exit(1)

    # Start core DNS monitoring
    try:
        dns_thread = threading.Thread(
            target=dns_start,
            args=(conn,),
            daemon=True,
            name="DNSMonitor",
        )
        dns_thread.start()
        logger.info("DNS monitor started")
    except Exception as e:
        logger.error(f"Failed to start DNS monitor: {e}")

    # Start optional demo allocator if enabled
    if ENABLE_PYALLOC_DEMO:
        try:
            alloc_thread = threading.Thread(
                target=alloc_start,
                args=(conn,),
                daemon=True,
                name="AllocDemo",
            )
            alloc_thread.start()
            logger.info("PyAlloc demo component started")
        except Exception as e:
            logger.warning(f"Failed to start PyAlloc demo: {e}")

    logger.info(f"API Key: {api_key[:8]}...")
    logger.info("Starting API server...")

    try:
        asyncio.run(run_api())
    except KeyboardInterrupt:
        logger.info("Shutting down...")
    except Exception as e:
        logger.error(f"Application error: {e}")
        sys.exit(1)

</code_context>

<issue_to_address>
**issue (code-quality):** Duplizierten Code in eine Funktion extrahieren ([`extract-duplicate-method`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/de-morgan/))
</issue_to_address>

Sourcery ist kostenlos für Open Source – wenn euch unsere Reviews gefallen, teilt sie gerne ✨
Helft mir, nützlicher zu sein! Bitte klickt 👍 oder 👎 bei jedem Kommentar, und ich werde das Feedback nutzen, um eure Reviews zu verbessern.
Original comment in English

Hey there - I've reviewed your changes - here's some feedback:

Blocking issues:

  • Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource. (link)

General comments:

  • Remove the leftover conflict marker '->>>>>> main' at the top of README.md to fully clear merge conflicts.
  • Verify that shared/db.py still initializes the database schema on first run, since the SCHEMA execution block was removed.
  • In install.sh, consider only redownloading the Unbound root hints if they're older than a threshold (e.g. 30 days) to avoid unnecessary downloads on every run.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Remove the leftover conflict marker '->>>>>> main' at the top of README.md to fully clear merge conflicts.
- Verify that shared/db.py still initializes the database schema on first run, since the SCHEMA execution block was removed.
- In install.sh, consider only redownloading the Unbound root hints if they're older than a threshold (e.g. 30 days) to avoid unnecessary downloads on every run.

## Individual Comments

### Comment 1
<location> `install.sh:102-104` </location>
<code_context>
-EOF
-        
-        # Run Pi-hole installer
+    if ! command -v pihole >/dev/null; then
         curl -sSL https://install.pi-hole.net | bash /dev/stdin --unattended
     fi
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Pi-hole installation does not verify successful install before proceeding.

Check the installer’s exit status before proceeding to configuration to prevent errors if installation fails.

```suggestion
    if ! command -v pihole >/dev/null; then
        curl -sSL https://install.pi-hole.net | bash /dev/stdin --unattended
        installer_status=$?
        if [ $installer_status -ne 0 ]; then
            error "Pi-hole installation failed (exit code $installer_status). Aborting."
            exit 1
        fi
    fi
```
</issue_to_address>

### Comment 2
<location> `install.sh:131-133` </location>
<code_context>
-    fi
-    
-    # Install Python dependencies
+    [[ -d .venv ]] || sudo -u "$INSTALL_USER" python3 -m venv .venv
     sudo -u "$INSTALL_USER" .venv/bin/pip install -U pip
     sudo -u "$INSTALL_USER" .venv/bin/pip install -r requirements.txt
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Virtualenv creation does not check for errors or Python version compatibility.

Check the exit status after attempting to create the virtual environment and display an informative error if it fails.

```suggestion
    if [[ ! -d .venv ]]; then
        sudo -u "$INSTALL_USER" python3 -m venv .venv
        if [[ $? -ne 0 ]]; then
            echo "ERROR: Failed to create Python virtual environment (.venv)."
            echo "Please ensure Python 3 is installed and supports venv."
            exit 1
        fi
    fi
    sudo -u "$INSTALL_USER" .venv/bin/pip install -U pip
    sudo -u "$INSTALL_USER" .venv/bin/pip install -r requirements.txt
```
</issue_to_address>

### Comment 3
<location> `install.sh:162` </location>
<code_context>
-    
-    # Enable and start the service
+
+    cat > .env <<ENV
+SUITE_API_KEY=$SUITE_API_KEY
+SUITE_PORT=$PYTHON_SUITE_PORT
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Environment file is overwritten unconditionally, which may erase user changes.

Please check if .env exists before overwriting, and consider prompting the user or backing up the file to prevent loss of custom settings.
</issue_to_address>

### Comment 4
<location> `api/main.py:52` </location>
<code_context>
     return os.getenv("SUITE_API_KEY", "")


 def get_db() -> Generator[sqlite3.Connection, None, None]:
-    """Database dependency."""
+    """FastAPI dependency to provide a DB connection."""
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Database connection is not closed after use, which may lead to resource leaks.

Please update get_db to ensure the database connection is properly closed after use, such as by using a context manager.
</issue_to_address>

### Comment 5
<location> `api/schemas.py:60` </location>
<code_context>
-    
-    @field_validator('mac_address')
+
+    @field_validator("mac_address")
     @classmethod
-    def validate_mac_address(cls, v):
</code_context>

<issue_to_address>
**suggestion:** MAC address validation is simplistic and may reject valid formats.

The current validator does not support MAC addresses with dashes or uppercase letters. Using a regex or a dedicated library would improve compatibility.
</issue_to_address>

### Comment 6
<location> `tests/test_api.py:84-90` </location>
<code_context>
+    assert isinstance(resp.json(), list)


 def test_stats_endpoint(client, api_headers):
-    """Test statistics endpoint."""
-    response = client.get("/stats", headers=api_headers)
-    assert response.status_code == 200
-    data = response.json()
+    resp = client.get("/stats", headers=api_headers)
+    assert resp.status_code == 200
+    data = resp.json()
     assert "total_dns_logs" in data
     assert "total_devices" in data
     assert "recent_queries" in data
-    assert isinstance(data["total_dns_logs"], int)
-    assert isinstance(data["total_devices"], int)
</code_context>

<issue_to_address>
**suggestion (testing):** Test could assert types and values for stats response fields.

Restoring the type assertions for these fields will help verify the response schema remains consistent.
</issue_to_address>

### Comment 7
<location> `README.md:96` </location>
<code_context>
your-api-key
</code_context>

<issue_to_address>
**security (curl-auth-header):** Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.

*Source: gitleaks*
</issue_to_address>

### Comment 8
<location> `api/schemas.py:66` </location>
<code_context>
    @field_validator("mac_address")
    @classmethod
    def validate_mac_address(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        # Simple MAC address validation (XX:XX:XX:XX:XX:XX)
        if not (len(v) == 17 and v.count(":") == 5):
            raise ValueError("Invalid MAC address format")
        return v.lower()

</code_context>

<issue_to_address>
**suggestion (code-quality):** Simplify logical expression using De Morgan identities ([`de-morgan`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/de-morgan/))

```suggestion
        if len(v) != 17 or v.count(":") != 5:
```
</issue_to_address>

### Comment 9
<location> `start_suite.py:71` </location>
<code_context>
def main() -> None:
    """Main application entry point."""
    logger.info("Starting Pi-hole Suite...")

    # Verify API key
    api_key = os.environ.get("SUITE_API_KEY")
    if not api_key:
        logger.error("SUITE_API_KEY environment variable must be set")
        logger.info("Generate one with: openssl rand -hex 16")
        sys.exit(1)

    # Initialize database
    try:
        conn = init_db()
        logger.info("Database initialized successfully")
    except Exception as e:
        logger.error(f"Failed to initialize database: {e}")
        sys.exit(1)

    # Start core DNS monitoring
    try:
        dns_thread = threading.Thread(
            target=dns_start,
            args=(conn,),
            daemon=True,
            name="DNSMonitor",
        )
        dns_thread.start()
        logger.info("DNS monitor started")
    except Exception as e:
        logger.error(f"Failed to start DNS monitor: {e}")

    # Start optional demo allocator if enabled
    if ENABLE_PYALLOC_DEMO:
        try:
            alloc_thread = threading.Thread(
                target=alloc_start,
                args=(conn,),
                daemon=True,
                name="AllocDemo",
            )
            alloc_thread.start()
            logger.info("PyAlloc demo component started")
        except Exception as e:
            logger.warning(f"Failed to start PyAlloc demo: {e}")

    logger.info(f"API Key: {api_key[:8]}...")
    logger.info("Starting API server...")

    try:
        asyncio.run(run_api())
    except KeyboardInterrupt:
        logger.info("Shutting down...")
    except Exception as e:
        logger.error(f"Application error: {e}")
        sys.exit(1)

</code_context>

<issue_to_address>
**issue (code-quality):** Extract duplicate code into function ([`extract-duplicate-method`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/extract-duplicate-method/))
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

# Enable and start the service

cat > .env <<ENV
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Die Umgebungsdatei wird bedingungslos überschrieben, was Benutzeränderungen löschen könnte.

Bitte überprüft, ob .env existiert, bevor ihr sie überschreibt, und erwägt, den Benutzer aufzufordern oder die Datei zu sichern, um den Verlust benutzerdefinierter Einstellungen zu verhindern.

Original comment in English

suggestion (bug_risk): Environment file is overwritten unconditionally, which may erase user changes.

Please check if .env exists before overwriting, and consider prompting the user or backing up the file to prevent loss of custom settings.

return os.getenv("SUITE_API_KEY", "")


def get_db() -> Generator[sqlite3.Connection, None, None]:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Die Datenbankverbindung wird nach Gebrauch nicht geschlossen, was zu Ressourcenlecks führen kann.

Bitte aktualisiert get_db, um sicherzustellen, dass die Datenbankverbindung nach Gebrauch ordnungsgemäß geschlossen wird, z.B. durch die Verwendung eines Kontextmanagers.

Original comment in English

suggestion (bug_risk): Database connection is not closed after use, which may lead to resource leaks.

Please update get_db to ensure the database connection is properly closed after use, such as by using a context manager.

All endpoints require the `X-API-Key` header:
```bash
curl -H "X-API-Key: your-api-key" http://127.0.0.1:8090/endpoint
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security (curl-auth-header): Ein potenzielles Autorisierungstoken wurde in einem Curl-Befehlsheader entdeckt, was die über Curl aufgerufene Ressource kompromittieren könnte.

Quelle: gitleaks

Original comment in English

security (curl-auth-header): Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.

Source: gitleaks

if not (len(v) == 17 and v.count(':') == 5):
raise ValueError('Invalid MAC address format')
# Simple MAC address validation (XX:XX:XX:XX:XX:XX)
if not (len(v) == 17 and v.count(":") == 5):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Vereinfacht den logischen Ausdruck unter Verwendung der De Morgan'schen Gesetze (de-morgan)

Suggested change
if not (len(v) == 17 and v.count(":") == 5):
if len(v) != 17 or v.count(":") != 5:
Original comment in English

suggestion (code-quality): Simplify logical expression using De Morgan identities (de-morgan)

Suggested change
if not (len(v) == 17 and v.count(":") == 5):
if len(v) != 17 or v.count(":") != 5:


# Start core DNS monitoring
try:
dns_thread = threading.Thread(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (code-quality): Duplizierten Code in eine Funktion extrahieren (extract-duplicate-method)

Original comment in English

issue (code-quality): Extract duplicate code into function (extract-duplicate-method)

@TimInTech TimInTech deleted the fix/remove-conflict-markers branch October 3, 2025 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants