# OSINT Lagemonitor > Lokale Arbeitskopie für das OSINT-Monitor-Projekt auf Server `alt` ## Übersicht ```yaml projekt: osint-monitor url: https://osint.intelsight.de beschreibung: "OSINT-basiertes Lagemonitoring mit Claude-KI-Agenten" server: alt (91.99.192.14, User: claude-dev) pfad_server: /home/claude-dev/osint-monitor pfad_lokal: C:\Users\Administrator\Desktop\OSINT-monitor status: aktiv (systemd service läuft) ``` ## Technologie-Stack ```yaml backend: framework: FastAPI (Python 3, venv /home/claude-dev/.venvs/osint/) datenbank: SQLite (WAL-Modus, aiosqlite) @ /mnt/gitea/osint-data/osint.db auth: JWT (HS256, bcrypt, 24h Ablauf) scheduler: APScheduler (Auto-Refresh jede Minute + Cleanup stündlich) websocket: FastAPI native ki_agenten: Claude CLI (WebSearch + WebFetch Tools) port: 8891 (localhost, Nginx Reverse Proxy) frontend: typ: Vanilla JS (kein Framework) design: AegisSight Dark Theme (Navy/Gold) fonts: Poppins (Titel), Inter (Body) echtzeit: WebSocket mit Auto-Reconnect ``` ## Projektstruktur ```yaml osint-monitor/: CLAUDE.md: "Projektdokumentation" requirements.txt: "Python-Abhängigkeiten" setup_users.py: "Nutzer-Initialisierung (rac00n, ch33tah)" data/: "Symlink -> /mnt/gitea/osint-data/ (SQLite DB)" logs/: "Anwendungs-Logs" src/: main.py: "FastAPI App, WebSocket-Manager, Scheduler, Lifespan" config.py: "Konfiguration (JWT, Claude CLI, RSS-Feeds, Excluded Sources)" auth.py: "JWT-Authentifizierung (bcrypt, HTTPBearer)" database.py: "SQLite Schema + Migrationen (8 Tabellen: users, incidents, articles, fact_checks, refresh_log, incident_snapshots, sources, notifications)" models.py: "Pydantic Request/Response-Schemas (inkl. Source CRUD + Notifications)" source_rules.py: "Dynamische Quellen-Regeln aus DB (RSS-Feeds + Blacklist)" routers/: auth.py: "POST /api/auth/login, GET /api/auth/me" incidents.py: "CRUD /api/incidents, /api/incidents/{id}/articles|factchecks|refresh" sources.py: "CRUD /api/sources, /api/sources/stats, /api/sources/refresh-counts" notifications.py: "GET /api/notifications, GET /api/notifications/unread-count, PUT /api/notifications/mark-read" feedback.py: "POST /api/feedback (Rate-Limited, HTML-E-Mail an feedback@aegis-sight.de)" agents/: claude_client.py: "Shared Claude CLI Client mit JSON-Output + Usage-Tracking (ClaudeUsage, UsageAccumulator)" orchestrator.py: "AsyncQueue, koordiniert Agenten-Pipeline sequentiell, Token-Akkumulation + Snapshots + DB-Notifications" researcher.py: "Claude WebSearch Agent (Ad-hoc + Deep Research Modus)" analyzer.py: "Analyse-Agent (Zusammenfassung + Briefing-Format)" factchecker.py: "Faktencheck-Agent (quellengebunden)" feeds/: rss_parser.py: "RSS-Feed Aggregation (dynamisch aus DB, Fallback auf config.py)" static/: index.html: "Login-Seite" dashboard.html: "Hauptdashboard" css/style.css: "AegisSight Design System" js/: "api.js, app.js, components.js, ws.js" ``` ## Architektur ```yaml agenten_pipeline: 1_rss: "RSS-Feeds durchsuchen (nur Ad-hoc-Lagen)" 2_claude_recherche: "Claude CLI WebSearch (Ad-hoc oder Deep Research)" 3_analyse: "Zusammenfassung/Briefing mit Inline-Zitaten [1][2] + sources_json" 4_faktencheck: "Claims gegen unabhängige Quellen prüfen" orchestrierung: "Sequentielle Queue (1 Auftrag gleichzeitig)" incident_typen: adhoc: "Breaking News -> RSS + WebSearch -> Plaintext-Summary mit Quellenreferenzen" research: "Hintergrundrecherche -> Nur Deep Research -> Markdown-Briefing mit Quellenverzeichnis" internationale_quellen: toggle: "Pro Lage konfigurierbar (Checkbox beim Anlegen/Bearbeiten)" international_true: "DE + internationale Feeds (Reuters, BBC, Al Jazeera) + mehrsprachige Claude-Recherche" international_false: "Nur deutschsprachige Quellen (DE, AT, CH), internationale RSS-Kategorie übersprungen" db_feld: "international_sources INTEGER DEFAULT 1" betroffene_agenten: "RSSParser (Kategorien-Filter), ResearcherAgent (Sprach-Prompts), Orchestrator (Weiterleitung)" quellenanzeige: inline_zitate: "Klickbare [1][2] Verweise im Lagebild → Quellenverzeichnis" quellenverzeichnis: "Am Ende des Lagebilds, nummeriert mit Links" quellenübersicht: "Aggregierte Ansicht aller Quellen pro Lage mit Sprach-Statistik" timeline_expand: "Artikel klickbar → Inhaltsvorschau + Link zum Original" sprach_badges: "EN/FR etc. Badge bei fremdsprachigen Artikeln" evidence_text: "Faktencheck zeigt erklärenden Text + Quellen-Chips" deduplizierung: "URL-Normalisierung + Headline-Ähnlichkeit (www, trailing slash, query params)" benachrichtigungen: persistenz: "DB-Tabelle notifications (pro Nutzer, 7 Tage Aufbewahrung)" erzeugung: "Orchestrator schreibt nach refresh_summary in DB (öffentlich=alle Nutzer, privat=nur Ersteller)" frontend: "NotificationCenter lädt aus DB beim Init, optimistisches UI bei WebSocket-Events, Debounced DB-Sync" gelesen: "Als gelesen markieren (is_read=1) → visuell abgeblendet, nicht gelöscht" tab_badge: "document.title = '(N) IntelSight...' bei ungelesenen Notifications" cleanup: "Stündlicher Job löscht Notifications älter als 7 Tage" quellenverwaltung: db_tabelle: "sources (id, name, url, domain, source_type, category, status, notes, added_by, article_count, last_seen_at, created_at)" source_types: "rss_feed | web_source | excluded" kategorien: "nachrichtenagentur, oeffentlich-rechtlich, qualitaetszeitung, behoerde, fachmedien, think-tank, international, regional, sonstige" seeding: "Beim Start aus config.py RSS_FEEDS + EXCLUDED_SOURCES (wenn Tabelle leer)" dynamisch: "source_rules.py liest aktive Quellen aus DB, Fallback auf config.py" frontend: "Modal mit Filter, Suche, Inline-Formular; Sidebar: 'Quellen verwalten' Button + Mini-Stats" deployment: workflow: "scp Dateien -> ssh alt -> systemctl restart osint-monitor" ```