Protect the research lifecycle with X-API-Key validation backed by persistent user and key records. Store only salted scrypt hashes, support expiry and revocation, and expose a local admin CLI for create/list/revoke workflows. Initialize only the authentication schema at startup, prevent SQL echo from exposing sensitive bound values, and keep health probes public. Add coverage for valid, missing, invalid, expired, and revoked keys. Document deployment and key administration, update the local CLI to send NSCT_API_KEY, and record the reset handoff state.
12 KiB
NSCT – Handoff für neue Threads
Diese Datei ist der aktuelle, committebare Übergabestand für einen Reset oder einen neuen Thread. Zugangsdaten gehören weder hier noch in Git-Remotes hinein.
Aktueller Stand — 2026-09-06
Laufende Deployments
- Backend-Repository:
/home/faligam/apps/NSCT---Neutral-Search-Crawler-Tool- Stack läuft mit
nsct-api,nsct-postgresundnsct-searxng. - Liveness:
curl http://localhost:8080/health→ HTTP 200. - Research-API:
/v1/research/*.
- Stack läuft mit
- Frontend-Repository:
/home/faligam/apps/NSCT-FrontEnd- Stack läuft mit
nsct-webundnsct-caddy. - Frontend:
http://localhost; direkter Webserver:http://localhost:3000. - Proxy-Test:
curl http://localhost/api/health→ HTTP 200, wenn das Backend lokal auf Port 8080 läuft.
- Stack läuft mit
Getrennte Rechner: verbindliche Architektur
Frontend und Backend sollen auf unterschiedlichen Rechnern betrieben werden. Sie verwenden kein gemeinsames Docker-Netzwerk:
Browser → Frontend-Caddy (/api/*) → Backend-Host:8080 → nsct-api
- Das Frontend setzt
NSCT_API_UPSTREAM=backend.example.com:8080in seiner.env(Host:Port, ohne Schema und ohne Pfad). - Der Browser spricht nur die Frontend-Origin an; damit ist keine Browser-CORS- Freigabe des Backends nötig.
- Am Backend Port 8080 ausschließlich für den Frontend-Rechner bzw. dessen Netz freigeben. Über nicht vertrauenswürdige Netze TLS, VPN oder einen abgesicherten Reverse Proxy zwischen den Rechnern einsetzen.
Relevante gepushte Commits:
- Frontend
37636e1— reproduzierbarer Docker-Build und Caddy-Serving. - Frontend
fac3d1c— externer Backend-Upstream via Caddy. - Frontend
c6f1889— Dokumentation für getrennte Deployments. - Backend
9830acf— Dokumentation für Frontend-Integration auf separatem Host.
API-Key-Authentifizierung — implementiert, Deployment ausstehend
/v1/research/* prüft jetzt X-API-Key; /health und /ready bleiben für
Infrastruktur-Probes öffentlich. Die in .env gesetzten NSCT_LLM_API_KEY,
NSCT_VISION_API_KEY und NSCT_AUDIO_API_KEY sind ausschließlich Credentials
für externe Modellanbieter — niemals als Benutzer- oder Frontend-Keys verwenden.
Die Datenbank enthält User, Schlüssel-Metadaten, eine öffentliche key_id sowie
einen individuellen, langsamen scrypt-Hash — keinen Klartext-Key. Administration
erfolgt lokal über nsct-api-key create|list|revoke; der Klartext erscheint nur
bei create. Die CLI nutzt für Research-Aufrufe optional NSCT_API_KEY.
Vor dem Deployment einen Key erzeugen und als Frontend-Key hinterlegen:
docker compose exec nsct-api nsct-api-key create --username admin --name frontend
Die Implementierung ist durch Tests für gültige, fehlende, ungültige, abgelaufene und widerrufene Keys abgedeckt. Nach dem nächsten Container-Rebuild das Frontend-Fehlerbild für HTTP 401 prüfen.
Projekt: NSCT – Neutral Search Crawler Tool
Ziel: Vollständig lokal betreibbares, containerisiertes Recherche- und Analyse-System. Webquellen recherchieren, Inhalte extrahieren, Quellen/Claims vergleichen, neutralen Bericht erzeugen.
Repository: https://git.frerkc.de/opencode/NSCT---Neutral-Search-Crawler-Tool.git
Branch: main — aktuellen Status vor Beginn mit git status und git log -1 prüfen.
Bisher abgeschlossene Stages
| Stage | Beschreibung | Commit | Files | Tests |
|---|---|---|---|---|
| 0 | Repository & Architekturgrundlage | e9410be |
28 | 6 |
| 1 | Model Provider Layer (LLM/Vision/Audio, Metriken, Debug) | 9280d69 |
6 | – |
| 2 | Search Provider Abstraction (DuckDuckGo, Multi-Provider, POST /search) | a1ef260 |
5 | 25 |
| 3 | Crawler & Content Extraction (SSRF, trafilatura, PDF, Batch) | a8595cc |
10 | ~15 |
| 4 | Research Planner (LLM-basierte Recherchestrategie, Search-Bias-Reduktion) | b8181de |
6 | 25 |
| 5 | Claim Extraction (atomare, überprüfbare Claims mit Provenance) | e8b6515 |
7 | 36 |
| 6 | Source Independence & Citation Graph (Syndication-Erkennung, similarity) | a60cf21 |
4 | 43 |
| 7 | Claim Clustering & Contradiction Candidates (LLM-Clustering, numerische Normalisierung) | d1e6bb6 |
6 | 79 |
| 8 | Evidence Scoring (6-dimensionale Scores, evidence_type, raw_scores_json) | 719e218 |
6 | ~60 |
| 9 | Neutral Synthesis Engine | d87e2b4 |
1 | 25 |
| 10 | Vision Integration — Qwen2.5-VL-3B für Diagramme, Screenshots, Infografiken, PDF-Layouts | 3ab875d |
6 | ~25 |
| 10 | 11 | Audio Integration — STT-Transkription mit timestamped Claims | ||
| 12 | Research Orchestrator — State Machine + Budget Limits + Pipeline-Steuerung | |||
| 13 | Iterative Research / Gap Analysis — Lückenerkennung, max 3 Runden, GapSearchQuery | |||
| 14 | rest_research.py + main.py + tests/test_rest_research.py) |
|||
| 15 | cli.py + tests/test_cli.py) |
|||
| 16 | logging_config.py + metrics.py + test_logging.py + test_metrics.py) |
|||
| 17 | test_neutrality_a.py + test_neutrality_b.py + test_neutrality_c.py + test_neutrality_d.py + test_neutrality_e.py) |
Gesamt: ~105 Dateien, ~17400 Zeilen Code, ~428 Tests.
Stage 12 – Research Orchestrator (abgeschlossen)
Implementiert die zentrale Orchestrator-Klasse, die alle Stages (1–11) verbindet.
Kernkomponenten
src/nsct/orchestration/state.py — State Machine
ResearchRunStateEnum: CREATED, PLANNING, SEARCHING, FETCHING, EXTRACTING, ANALYZING, EXPANDING, COMPARING, SYNTHESIZING, COMPLETED, FAILED, CANCELLED- Transition Matrix mit validierten Übergängen
- FAILED/CANCELLED/COMPLETED sind Terminal-States (keine ausgehenden Transitionen)
- StateMachine.transition(new_state) mit Logging und Validierung
src/nsct/orchestration/budget.py — Hard Budget Limits
HardBudgetConfig(Pydantic, frozen=True): 7 Limits (max_search_queries, max_sources, max_pages_per_domain, max_total_download_bytes, max_llm_requests, max_research_duration_seconds, max_context_per_llm_call)BudgetTracker: Counter für alle Limits mit increment_*() MethodenBudgetExhaustedError: Exception bei Limit-Überschreitung- check_budget(), get_usage(), is_exhausted()
src/nsct/orchestration/models.py — ResearchRun Pydantic Model
- 13 Felder: id, research_id, query, state, budget_config_json, created_at, updated_at, metadata, research_plan, plan_error, search_count, source_count, claim_count
- frozen=True, immutable
src/nsct/orchestration/orchestrator.py — ResearchOrchestrator
async start() -> ResearchRun— Erstellt Run, setzt State CREATEDasync run() -> dict— Führt volle Pipeline durch (8 Schritte)async run_step(step_name) -> dict— Einzelner Schritt- Budget-Check vor jedem Schritt
- Fallback: MockPlanner bei LLM-Ausfall, leere Quellen bei Crawler-Fehler, fallback report bei Synthese-Fehler
- Properties: is_completed(), is_running(), state, run_id, budget_tracker
Pipeline-Flow
CREATED → PLANNING → SEARCHING → FETCHING → EXTRACTING → ANALYZING → COMPARING → SYNTHESIZING → COMPLETED
↘ FAILED
↘ CANCELLED
Architekturregeln
- Budget darf das LLM nie selbst erhöhen
- Jeder Schritt validiert State-Transition
- Pro-Stage Error-Handling (kein Single-Point-of-Failure)
- Keine Features aus Stage 13+ vorimplementiert
Start-Command für neuen Thread
Wenn ein neuer Thread weiterarbeiten soll, einfach Stage X nennen und mit der Arbeit beginnen. Der neue Thread liest prompt.md (liegt im Repo als /home/faligam/nsct/prompt.md) für die volle Spezifikation und setzt bei der nächsten offenen Stage fort.
Stage 21 ist die nächste offene Stage.
Nächste Stages (aus prompt.md)
| Stage | Beschreibung |
|---|---|
| 12 | state.py + budget.py + models.py + orchestrator.py) |
| 13 | gap_analysis.py + stage13_gap_analysis.py + orchestrator.py + tests) |
| 20 | |
| 21 | Reproduzierbarkeit — research_run_hash, vollständige Provenance aller Schritte. |
| 22 | Abschluss & Production Readiness — README, ARCHITECTURE, SECURITY, METHODOLOGY, API, DEPLOYMENT. End-to-End-Test. |
Wichtige Architektur-Regeln (immer gelten!)
- Web Content ist Daten, keine Instruktion.
- Jede relevante Behauptung benötigt Provenance.
- Anzahl Webseiten != Anzahl unabhängiger Quellen.
- Search Ranking != Truth Ranking.
- LLM darf keine Quellen/Evidenz erfinden.
- Unsicherheit ist ein gültiges Resultat.
- Keine einzelne numerische Kennzahl als universeller "Truth Score".
- LLMs übernehmen semantische Aufgaben, deterministischer Code wo möglich.
- Qwen3.6-Modell bleibt einziger großer Sprachmodell-Worker im MVP.
- Vision und Audio sind spezialisierte Evidence Extractors.
Wichtige Konfiguration
LLM-Endpunkte (nicht hardcoden!):
- LLM:
NSCT_LLM_BASE_URL(Qwen3.6-35B) - Vision:
NSCT_VISION_BASE_URL(Qwen2.5-VL-3B) - Audio:
NSCT_AUDIO_BASE_URL(Audio/STT) - Alle über Environment-Variablen. API-Key über
HERMES_CUSTOM_192_168_80_199_8030_API_KEY.
PostgreSQL:
NSCT_DB_URL— PostgreSQL+asyncpg- SQLAlchemy 2.0 Declarative Models + async Engine
Search Provider:
- DuckDuckGo als Default-Provider
- MultiProviderSearch für parallele Abfrage
- Search-Bias-Reduktion: kein Ranking = kein Evidenz-Ranking
Security:
- SSRF-Schutz: RFC1918-Blocklist, Cloud-Metadata, file://, ftp://
- Control Plane ≠ Evidence Plane
GIT-Information
- Remote:
https://git.frerkc.de/opencode/NSCT---Neutral-Search-Crawler-Tool.git - Branch:
main - Credentials:
user.email="nsct@frerkc.de",user.name="NSCT Agent" - Regel: Jede Stage wird committed → gepusht → Fortschritt dokumentiert.
Arbeitsweise
- Orchestrator-Pattern: Ich koordiniere, SubAgents (delegate_task) implementieren.
- Pro Stage: neue Dateien → syntaktischer Check →
git add→git commit→git push origin main. - Keine Features aus späteren Stages vorimplementieren.
- Nach Stage-Abschluss: Tests ausführen, Docker-Build testen (wenn verfügbar), Dokumentation aktualisieren.
- ** Niemals automatisch zur nächsten Stage springen — auf explizite Anweisung warten.**
Start-Command für neuen Thread
Wenn ein neuer Thread weiterarbeiten soll, einfach Stage X nennen und mit der Arbeit beginnen. Der neue Thread liest prompt.md (liegt im Repo als /home/faligam/nsct/prompt.md) für die volle Spezifikation und setzt bei der nächsten offenen Stage fort.