Files

4.7 KiB

Gateway Secret Caching — Debugging Session 12.07.2026

Zusammenfassung

Problem: Beide Webhooks (A→B und B→A) lieferten {"error": "Invalid signature"} obwohl Health-Checks, SSH, Ping und UFW alle grün waren.

Root Cause: Hermes Gateway cached Webhook-Secrets ausschließlich beim Start. hermes webhook subscribe --secret X schreibt X in die Datenbank, aber der laufende Gateway-Prozess ignoriert das und verwendet weiter das Secret vom Startzeitpunkt.

Chronologie der Fehlersuche

Phase 1: Startup-Check (erfolgreich)

  • ZeroTier: ONLINE (Node adccde5dd6)
  • Ping B (172.24.34.142): 20ms ✅
  • SSH zu B: OK ✅
  • Health B: 200 ✅
  • UFW: ALLOW 172.24.0.0/16 ✅

Phase 2: Erstkontakt scheitert

  • A→B mit Secret JB5WeE62... (aus collaboration-secrets.md, Stand 18.07.): Invalid signature ❌
  • B's Webhook-Abo war inzwischen veraltet/neu erstellt → Secret hatte sich geändert

Phase 3: Neu-Subscribe auf B

  • collab-from-a auf B gelöscht und neu subscribet → neues Secret: Cjig8scE...
  • A→B damit: accepted ✅
  • Aber B→A immer noch: Invalid signature ❌

Phase 4: Neu-Subscribe auf A

  • collab-from-b auf A gelöscht und neu subscribet → neues Secret: 3t-z7Oif...
  • B→A damit: Invalid signature ❌ (obwohl frisch subscribet!)

Phase 5: --secret mesh-secret-2026 — scheitert

  • BEIDE Webhooks mit --secret mesh-secret-2026 neu erstellt
  • A→B: funktionierte KURZ (1-2 Minuten), dann wieder Invalid signature
  • B→A: NIE funktioniert mit mesh-secret-2026

Phase 6: Erleuchtung — Gateway cached!

  • Gateway auf A läuft seit 17.07. ununterbrochen
  • Gateway cached Secrets beim Start → ignoriert alle DB-Änderungen danach
  • --secret ist wirkungslos ohne Gateway-Neustart
  • Gateway-Neustart von innen UNMÖGLICH (Hermes blockt alles)

Phase 7: Original-Secrets verwendet — ERFOLG

  • A's collab-from-b: zurück auf xyvNK6G1nDjHMOgn8oPcjVQkK2cQpguWqc8Od1jnbx4 (Gateway-Start 17.07.)
  • B's collab-from-a: zurück auf JB5WeE62GYxE6PpJo-xN8JehXBouZMAzQiL6e4WbCJg (Gateway-Start 18.07.)
  • BEIDE Richtungen: accepted ✅✅

Gelernte Lektionen

  1. hermes webhook subscribe --secret X ist eine Lüge — es schreibt nur in die DB, der Gateway merkt nichts
  2. Gateway-Neustart ist Pflicht nach Secret-Änderung — aber von innen unmöglich
  3. Immer das Gateway-Startup-Secret verwenden — nicht das zuletzt gesubscribete
  4. hermes webhook list zeigt KEINE Secrets — man sieht nicht was der Gateway wirklich erwartet
  5. ps aux | grep "gateway run" → Startzeit ist der Schlüssel zum richtigen Secret

Praktischer Workflow für zukünftige Sessions

# 1. Gateway-Startzeitpunkt ermitteln
ps aux | grep "gateway run" | grep -v grep
# → Start: Jul17 → Secret aus collaboration-secrets.md vom Stand 17.07. nehmen

# 2. Webhook auf DIESES Secret setzen (nicht --secret mit neuem Wert!)
hermes webhook remove collab-from-b
hermes webhook subscribe collab-from-b \
  --secret <original-gateway-startup-secret> \
  --deliver telegram --prompt "..."

# 3. Bidirektional testen
# A→B mit B's Gateway-Startup-Secret
# B→A mit A's Gateway-Startup-Secret
# BEIDE müssen accepted sein!

Aktuell gültige Secrets (12.07.2026)

Richtung Secret Gateway-Start
A→B JB5WeE62GYxE6PpJo-xN8JehXBouZMAzQiL6e4WbCJg B: 18.07.
B→A xyvNK6G1nDjHMOgn8oPcjVQkK2cQpguWqc8Od1jnbx4 A: 17.07.

⚠️ Nach JEDEM Gateway-Neustart ändern sich die gültigen Secrets! Dann --secret mit NEUEM Wert verwenden und sowohl subscriben ALS AUCH Gateway neustarten (extern!).

Bidirektionaler Schnelltest (nach jedem Setup/Neustart)

# BEIDE Richtungen mit JEWEILIGEM Gateway-Startup-Secret testen:
python3 -c "
import hmac, hashlib, json, subprocess

tests = [
    ('A->B', 'JB5WeE62GYxE6PpJo-xN8JehXBouZMAzQiL6e4WbCJg', 'http://172.24.34.142:8644/webhooks/collab-from-a'),
    ('B->A', 'xyvNK6G1nDjHMOgn8oPcjVQkK2cQpguWqc8Od1jnbx4', 'http://172.24.196.119:8644/webhooks/collab-from-b'),
]
all_ok = True
for label, secret, url in tests:
    p = {'topic':'ping','idea':'test','from':'agent-a' if 'A->' in label else 'agent-b'}
    pj = json.dumps(p, separators=(',',':'))
    sig = 'sha256=' + hmac.new(secret.encode(), pj.encode(), hashlib.sha256).hexdigest()
    r = subprocess.run(['curl','-s','-X','POST',url,'-H','Content-Type: application/json',
        '-H',f'X-Hub-Signature-256: {sig}','-d',pj,'--max-time','5'], capture_output=True, text=True)
    ok = 'accepted' in r.stdout
    all_ok = all_ok and ok
    print(f'{label}: {\"✅\" if ok else \"❌\"} {r.stdout.strip()}')
print(f'\\nGesamt: {\"✅ MESH BEREIT\" if all_ok else \"❌ FEHLER — Troubleshooting nötig\"}')
"