Ferndiagnose (MCP): Verbindungscode + abgesicherter Fernzugriff + stdio-Bridge
Neue Funktion, um Diagnose eines laufenden Servers aus der Ferne zu ermoeglichen:
Hilfe -> Remote-Support -> "Ferndiagnose (MCP)". Erzeugt einen Verbindungscode,
den der Assistent nutzt, um Status, Logs, Fehler und Accounts read-only zu lesen.
App-Seite:
- Live (re)startbarer Debug-Server ohne App-Neustart (restartDebugServer wartet auf
'close' + closeAllConnections, behandelt EADDRINUSE).
- IP-Allowlist (debug_allowlist.txt, exakte IP + CIDR), erzwungen VOR der Auth.
Fail-closed: Netzwerk-Bind (0.0.0.0) ohne Allowlist akzeptiert nur Loopback.
- One-Click Aktivieren/Aktualisieren/Deaktivieren + Token-Rotation (alter Code sofort
ungueltig). Sichtbarkeit waehlbar: "Nur lokal" (Tunnel-Empfehlung) vs "Im Netzwerk".
- Verbindungscode rddiag:v1:base64url({v,h,p,t,n?,fp?,s?}); oeffentlicher Host frei
waehlbar, Netzwerk-IPs als Schnellauswahl.
- Neue IPC: get/enable/disable/rotate Remote-Diagnostics; Controller-Methoden; Typen.
Bridge (tools/rd-diagnostics-mcp, standalone, KEINE App-Dependency):
- stdio MCP-Server (@modelcontextprotocol/sdk) mit 14 Tools, proxyt die bestehende
HTTP-Debug-API. Multi-Server ueber code/server/RDDIAG_CODE/RDDIAG_SERVERS.
- TLS-Fingerprint-Pinning auf secureConnect (vor Token-Versand), falls https genutzt.
- test/harness.mjs: faehrt einen Fake-Debug-Server hoch und treibt die Bridge als
echten stdio-Child per JSON-RPC -> voller Protokollpfad gruen.
Sicherheit (Audit): keine persistenten Secrets in den Logs der Debug-API (Passwoerter
redigiert, keine Debrid-Keys/aufgeloesten Download-URLs geloggt; settings/accounts
redigiert). Empfohlener Transport: Loopback + privater Tunnel; Direkt-Bind nur mit
Allowlist in vertrauenswuerdigen Netzen.
Tests: connection-code-Cross-Check (App-Encoder <-> Bridge-Decoder), Allowlist-Matrix
(Loopback, exakt, CIDR, fail-closed, Live-Restart). Volle Suite 905 gruen, tsc=6.
This commit is contained in:
+32
-31
@@ -1,37 +1,38 @@
|
||||
# Massives Conversion-Logging (v1.7.213) + Failover-Fix
|
||||
# MCP-Ferndiagnose (Goal, ultracode) — v1.7.223
|
||||
|
||||
## Problem (live belegt, 2026-06-17)
|
||||
- Links haengen mit "Unrestrict Timeout nach 60s", R53/R64, halten Download-Slot → Stop-and-Go.
|
||||
- Web-first: 1 globaler 60s-Timeout um die GANZE Provider-Kette → Web frisst das Budget,
|
||||
API-Failover wird NIE versucht (debrid.ts 3801 `signal.aborted` → throw). Retry startet wieder bei Web.
|
||||
- API-first laeuft "um einiges fluessiger" (User bestaetigt: API resolved UND downloaded auf dem Server).
|
||||
- ABER: API-Token-Fehler ("Token error, please log-in") + "Login oder Unrestrict fehlgeschlagen"
|
||||
→ beide Accounts kriegen Cooldown → Doom-Loop. connectApi single-flightet Logins schon (pendingConnects),
|
||||
also ist die Token-Ursache NICHT trivial → braucht Token-Lifecycle-Logging.
|
||||
## Ziel (Nutzer)
|
||||
"Baue massive Diagnose-Funktionen ein (MCP), so dass ich MCP auf nem Windows-Server aktivieren kann und du
|
||||
auf den Server zugreifst und WIRKLICH ALLES siehst (State, Fehler, Logs, Probleme). 5-6 Server, ueber
|
||||
Verbindungscode. Du verbindest dich → liest alles → behebst Probleme direkt."
|
||||
|
||||
## Kern-Blindstelle
|
||||
Bestehende Logs (account-rotation.log) zeigen `elapsedMs` aber NICHT:
|
||||
- queue-wait vs aktive Arbeit (war der 60s-Timeout Warten in der Queue oder echtes Arbeiten?)
|
||||
- Token-Lifecycle (cacheHit/freshLogin/invalidation) → woher "Token error"?
|
||||
- Provider-Ketten-Entscheidung pro Item (welche Provider, welches Budget, warum Stopp)
|
||||
- Was war in-flight als der Caller-60s-Timeout feuerte (Provider/Account/Phase) + Slot-Belegung
|
||||
## Architektur (Advisor-bestaetigt v1)
|
||||
- Standalone **stdio MCP-Bridge** auf MEINER (Claude-Code-)Maschine, proxyt zur bestehenden HTTP `debug-server.ts`
|
||||
jedes Servers via **Verbindungscode**. Eine Bridge bedient alle 5-6 Server.
|
||||
- KEIN eingebettetes MCP-over-HTTP (verworfen: hand-rolled Protokoll auf Internet-Oberflaeche = mehr Risiko).
|
||||
- Bridge-Code identisch fuer Direkt-IP vs spaeterer Tunnel (proxyt host:port).
|
||||
- Verbindungscode: `rddiag:v1:<base64url(JSON {v,h:host,p:port,t:token,n?:name,fp?:certFp})>`. Nutzer liefert
|
||||
oeffentlichen Host (nicht auto-detecten).
|
||||
|
||||
## Plan (Release 213 = NUR Logging, bewusst KEINE Verhaltensaenderung — damit das naechste Bundle das ECHTE aktuelle Verhalten zeigt)
|
||||
- [x] `src/main/conversion-trace.ts`: AsyncLocalStorage-Trace + dedizierte `conversion.log`. EIN strukturierter Block pro Unrestrict-Versuch.
|
||||
- [x] Wiring: init in app-controller, shutdown, support-bundle.
|
||||
- [x] Instrumentiert (nur tracePhase-Calls, additiv, no-op ohne aktiven Trace):
|
||||
- download-manager unrestrict-Boundary: runWithConversionTrace + Caller-Timeout-Attribution + describeSlotOccupancy.
|
||||
- debrid.ts Provider-Kette: chain-try/chain-ok/chain-failed/chain-aborted (zeigt ob Failover feuert).
|
||||
- debrid.ts Mega-Rotation: mega-account workMs + outcome (ok/failed/fatal/aborted) + cooldown.
|
||||
- MegaDebridClient connectApi/doConnectApi/unrestrictViaApi: token cached/pending-join/fresh-login + connectMs + getLink response_code/text (DAS klaert "Token error").
|
||||
- mega-web-fallback runExclusive: web-queue queueWaitMs + workMs (DAS klaert ob 60s = Warten oder Arbeit).
|
||||
- [x] Test: conversion-trace.test.ts (Formatter + ALS-Kontext). tsc unveraendert 6.
|
||||
- [ ] Build + Suite gruen. Release 213 (Gitea + Mirror).
|
||||
## Sicherheitsmodell (Advisor, first-class)
|
||||
Plain HTTP + Bearer ueber Internet = sniffbares Token mit Lesezugriff auf sensible Logs. Mitigations:
|
||||
- App-seitige IP-Allowlist (extractDebugClientIp existiert schon).
|
||||
- `/trace/config` MUTIERT → "read-only"-Claim auditieren: Writes von Remote-Oberflaeche gaten oder umlabeln.
|
||||
- Opt-in + sofort widerrufbar (Token-Rotation killt Zugang).
|
||||
- debug_token.txt in userData bestaetigen (ueberlebt Auto-Update).
|
||||
- Optional self-signed Cert + Fingerprint im Code gepinnt (NICHT v1-blockierend).
|
||||
|
||||
## DEFERRED auf 214 (erst NACH Logs, kein Blind-Fix mehr)
|
||||
- 60s global → per-Provider-Budget (Failover feuert) — proven, aber erst messen: tritt der 60s ueberhaupt bei API-first auf, und ist es Queue oder Arbeit?
|
||||
- API Token-Error Doom-Loop ("Token error, please log-in") — Mechanismus per conversion.log verifizieren, DANN fixen (evtl. per-Account-Serialisierung fuer API wie bei Web).
|
||||
- Config-Realitaet an User: 2. Account (xe) lief abgelaufen/deaktiviert → 212-Parallelitaet griff nicht; API-first ist der schnelle Pfad.
|
||||
## Phasen
|
||||
- [x] **P0 Vertical Slice (Diskriminator) — ERLEDIGT, harness ALL PASS:** Bridge → debug-server via stdio JSON-RPC, echte Daten zurueck.
|
||||
- [x] MCP SDK API holen (context7) → @modelcontextprotocol/sdk 1.29.0, registerTool(name,{inputSchema:zodShape},cb)
|
||||
- [x] Bridge in `tools/rd-diagnostics-mcp/` (eigenes package.json, NICHT in App-Bundle): code.mjs/http.mjs/bridge.mjs/gen-code.mjs
|
||||
- [x] 14 Tools: rd_servers/rd_ping/rd_diagnostics/rd_status/rd_items/rd_packages/rd_errors/rd_logs/rd_history/rd_accounts/rd_host/rd_self_check/rd_get + Multi-Server (code|server|RDDIAG_CODE|RDDIAG_SERVERS)
|
||||
- [x] Verbindungscode-Codec rddiag:v1:base64url({v,h,p,t,n?,fp?,s?})
|
||||
- [x] Test-Harness (test/harness.mjs): fake debug-server (auth+routes+query-echo) + Bridge als stdio-Child → 19 Checks gruen (handshake, tools/list, ping, diagnostics+query-passthrough, logs-mapping, errors, escape-hatch, 401, missing-code, unreachable+hint)
|
||||
- [ ] **P1 Security-Hardening debug-server:** IP-Allowlist app-seitig; /trace/config-Mutation gaten/umlabeln; opt-in+revoke; userData-Pfad verifizieren.
|
||||
- [ ] **P2 One-Click-Enable + Code (App):** debug-server live (re)startbar ohne App-Neustart; IPC + flache UI (Anti-KI-Taste); Verbindungscode mit Copy + Revoke.
|
||||
- [ ] **P3 Diagnose-Luecken:** Provider-Cooldown/Rotation Live-State, "Was ist JETZT kaputt"-Triage, evtl. Live-Log-Tail.
|
||||
- [ ] **P4 Verify:** Tests gruen + tsc=6, Bridge end-to-end, Security-Review, Release v1.7.223 (Gitea+Mirror, 4 .exe). Bridge zu Claude Code (claude mcp add).
|
||||
- [ ] **P5 Reachability-Acceptance (Nutzer):** debug-server auf 1 Server an → curl von Claude-Maschine. Direkt-IP vs Tunnel-Entscheid.
|
||||
|
||||
## Review
|
||||
Logging-Release: pure Diagnose, null Verhaltensrisiko. Naechster Schritt: User reproduziert, schickt Bundle, conversion.log zeigt Queue-vs-Arbeit + Token-Lifecycle eindeutig → praeziser Fix in 214.
|
||||
(folgt)
|
||||
|
||||
Reference in New Issue
Block a user