Translate-Skill: POST /vault/translate liefert 401, sobald ein Remote-Token in der Keychain existiert #115

Closed
opened 2026-10-20 10:23:51 +00:00 by alf · 3 comments
Owner

Symptom

Die Übersetzung des translate-Skills (plugins/translate, translate_document.py) schlägt auf dem Mac beim ersten Chunk fehl:

Übersetzung — neural4d-tutorial_de.md fehlgeschlagen: Chunk 1/6: HTTP Error 401: Unauthorized

Worker-Log (/tmp/translate-worker-20718.log, 2026-10-20 11:57, Job CF41E32E-BCFD-464F-80CC-2D5054EE934A):

Chunk 1/6 fehlgeschlagen (Versuch 1/3): HTTP Error 401: Unauthorized
Chunk 1/6 fehlgeschlagen (Versuch 2/3): HTTP Error 401: Unauthorized
Chunk 1/6 fehlgeschlagen (Versuch 3/3): HTTP Error 401: Unauthorized
Übersetzung abgebrochen — Chunk 1/6: HTTP Error 401: Unauthorized

Live reproduzierbar gegen den laufenden Mac-Server (alle ohne Authorization-Header):

Request Ergebnis
GET /health 200
POST /vault/translate 401 Unauthorized
POST /notify (ungültige Felder) 400 — d. h. Auth bestanden, dann Validierung

Ursache

  • Der Worker läuft auf dem Mac als Hermes-Subprozess. Auf dem Mac existiert keine iris_notify_config.json (nur der Linux-Server schreibt sie, hermes_config_writer.ensure_iris_notify_config(), mit dem aktuellen Bearer-Token). _resolve_iris_target() in translate_document.py fällt dort auf 127.0.0.1:8765 mit leerem Token zurück und sendet deshalb gar keinen Authorization-Header — so auch in der SKILL.md als Designannahme dokumentiert („leer auf dem Mac, dort gelten 127.0.0.1/kein Token“).
  • Der Auth-Guard in IrisRemoteServer.swift (isAuthorized()) verlangt für jede Route ein Bearer-Token, außer die Route steht auf der localhost-Ausnahmeliste (isLocalhostNotify): POST /notify, /job-watch/start, /videowatch/playlist, /job-callback/register|unregister, /agent, /client/push-file, GET /agent/:id/status, GET /job-callback/pending, GET /hosts/resolve plus die Pfad-Token-Ausnahmen (htmlserver, hermes-dashboard, pairing-CA, plugin-cfg_token, Marktplatz).
  • POST /vault/translate steht nicht auf dieser Liste → 401.
  • Wahrscheinlich hat der Skill zeitweise funktioniert, solange in der Keychain kein Remote-Token gesetzt war (isAuthorized() lässt ohne gecachtes Token alles zu). Sobald ein Remote-Token existiert (Client-Pairing/Regeneration), bricht der Skill still — der UI-„Übersetzen“-Button im Vault-Editor ist davon nicht betroffen, er läuft in-process ohne HTTP.
  • Linux-Server nicht betroffen: Dort gibt es bewusst keine localhost-Ausnahme (bindet an alle Interfaces → unauthentifizierte Schreibroute wäre ein LAN-Exposure), aber der Worker erhält das Token aus iris_notify_config.json, die server bei jedem Start auf den aktuellen Bearer-Token bringt.

Lösung

POST /vault/translate in IrisRemoteServer.swift in die localhost-Ausnahmeliste (isLocalhostNotify) aufnehmen — exakt das bestehende Muster von POST /notify: Skill-Subprozesse derselben Maschine können das Bearer-Token nicht aus der Keychain lesen (löste Entsperr-Dialoge aus), die Autorisierung übernimmt die Loopback-Herkunft der Verbindung.

  • Kein Wire-Protokoll-Änderung: Die Route existiert auf beiden Servern identisch, geändert wird nur die lokale Vertrauensentscheidung des Mac-Servers (der Linux-Server trifft bereits bewusst eine abweichende lokale Vertrauensentscheidung — keine localhost-Ausnahmen).
  • Keine Clients betroffen: Die Ausnahme greift nur für Verbindungen von 127.0.0.1/::1 (isLocalhostConnection), LAN-/Remote-Verbindungen bleiben bearer-pflichtig.
  • Linux-Server und Clients: keine Änderung.
  • Sicherheitsniveau: innerhalb des vorhandenen Trust-Envelopes — das bereits ausgenommene POST /agent startet komplette Agent-Jobs und ist strikt mächtiger als eine einzelne Übersetzungs-Completion.

Verifikation nach dem Fix

  1. Neu bauen + Iris neu starten („Bau und starte lokal“).
  2. curl -sk -X POST https://127.0.0.1:8765/vault/translate -d '{"text":"Hallo","target_language":"en"}' ohne Token → kein 401 mehr.
  3. Dieselbe Übersetzung erneut anstoßen — der Worker setzt dank State-Datei (neural4d-tutorial_de.md.translate-state.json, Status failed) bei Chunk 1/6 fort und liefert das Ergebnis im Chat.
## Symptom Die Übersetzung des translate-Skills (`plugins/translate`, `translate_document.py`) schlägt auf dem Mac beim ersten Chunk fehl: > Übersetzung — neural4d-tutorial_de.md fehlgeschlagen: Chunk 1/6: HTTP Error 401: Unauthorized Worker-Log (`/tmp/translate-worker-20718.log`, 2026-10-20 11:57, Job CF41E32E-BCFD-464F-80CC-2D5054EE934A): ``` Chunk 1/6 fehlgeschlagen (Versuch 1/3): HTTP Error 401: Unauthorized Chunk 1/6 fehlgeschlagen (Versuch 2/3): HTTP Error 401: Unauthorized Chunk 1/6 fehlgeschlagen (Versuch 3/3): HTTP Error 401: Unauthorized Übersetzung abgebrochen — Chunk 1/6: HTTP Error 401: Unauthorized ``` Live reproduzierbar gegen den laufenden Mac-Server (alle ohne Authorization-Header): | Request | Ergebnis | |---|---| | `GET /health` | 200 | | `POST /vault/translate` | **401 Unauthorized** | | `POST /notify` (ungültige Felder) | 400 — d. h. Auth *bestanden*, dann Validierung | ## Ursache - Der Worker läuft auf dem Mac als Hermes-Subprozess. Auf dem Mac existiert **keine** `iris_notify_config.json` (nur der Linux-Server schreibt sie, `hermes_config_writer.ensure_iris_notify_config()`, mit dem aktuellen Bearer-Token). `_resolve_iris_target()` in `translate_document.py` fällt dort auf `127.0.0.1:8765` mit **leerem Token** zurück und sendet deshalb gar keinen Authorization-Header — so auch in der SKILL.md als Designannahme dokumentiert („leer auf dem Mac, dort gelten 127.0.0.1/kein Token“). - Der Auth-Guard in `IrisRemoteServer.swift` (`isAuthorized()`) verlangt für jede Route ein Bearer-Token, **außer** die Route steht auf der localhost-Ausnahmeliste (`isLocalhostNotify`): `POST /notify`, `/job-watch/start`, `/videowatch/playlist`, `/job-callback/register|unregister`, `/agent`, `/client/push-file`, `GET /agent/:id/status`, `GET /job-callback/pending`, `GET /hosts/resolve` plus die Pfad-Token-Ausnahmen (htmlserver, hermes-dashboard, pairing-CA, plugin-cfg_token, Marktplatz). - `POST /vault/translate` steht **nicht** auf dieser Liste → 401. - Wahrscheinlich hat der Skill zeitweise funktioniert, solange in der Keychain **kein** Remote-Token gesetzt war (`isAuthorized()` lässt ohne gecachtes Token alles zu). Sobald ein Remote-Token existiert (Client-Pairing/Regeneration), bricht der Skill still — der UI-„Übersetzen“-Button im Vault-Editor ist davon nicht betroffen, er läuft in-process ohne HTTP. - **Linux-Server nicht betroffen:** Dort gibt es bewusst keine localhost-Ausnahme (bindet an alle Interfaces → unauthentifizierte Schreibroute wäre ein LAN-Exposure), aber der Worker erhält das Token aus `iris_notify_config.json`, die `server` bei jedem Start auf den aktuellen Bearer-Token bringt. ## Lösung `POST /vault/translate` in `IrisRemoteServer.swift` in die localhost-Ausnahmeliste (`isLocalhostNotify`) aufnehmen — exakt das bestehende Muster von `POST /notify`: Skill-Subprozesse derselben Maschine können das Bearer-Token nicht aus der Keychain lesen (löste Entsperr-Dialoge aus), die Autorisierung übernimmt die Loopback-Herkunft der Verbindung. - **Kein Wire-Protokoll-Änderung:** Die Route existiert auf beiden Servern identisch, geändert wird nur die lokale Vertrauensentscheidung des Mac-Servers (der Linux-Server trifft bereits bewusst eine abweichende lokale Vertrauensentscheidung — keine localhost-Ausnahmen). - **Keine Clients betroffen:** Die Ausnahme greift nur für Verbindungen von `127.0.0.1`/`::1` (`isLocalhostConnection`), LAN-/Remote-Verbindungen bleiben bearer-pflichtig. - **Linux-Server und Clients: keine Änderung.** - Sicherheitsniveau: innerhalb des vorhandenen Trust-Envelopes — das bereits ausgenommene `POST /agent` startet komplette Agent-Jobs und ist strikt mächtiger als eine einzelne Übersetzungs-Completion. ## Verifikation nach dem Fix 1. Neu bauen + Iris neu starten („Bau und starte lokal“). 2. `curl -sk -X POST https://127.0.0.1:8765/vault/translate -d '{"text":"Hallo","target_language":"en"}'` ohne Token → kein 401 mehr. 3. Dieselbe Übersetzung erneut anstoßen — der Worker setzt dank State-Datei (`neural4d-tutorial_de.md.translate-state.json`, Status `failed`) bei Chunk 1/6 fort und liefert das Ergebnis im Chat.
Author
Owner

PR #146 gemergt: fix(remote): POST /vault/translate gehört zu den localhost-Ausnahmen, der translate-Skill liefert auf dem Mac kein 401 mehr (iris/Iris#115)
#146

Commits:

  • fix(remote): POST /vault/translate gehört zu den localhost-Ausnahmen, der translate-Skill liefert auf dem Mac kein 401 mehr (iris/Iris#115)
PR #146 gemergt: fix(remote): POST /vault/translate gehört zu den localhost-Ausnahmen, der translate-Skill liefert auf dem Mac kein 401 mehr (iris/Iris#115) https://forgejo.lewerken.duckdns.org/iris/Iris/pulls/146 Commits: - fix(remote): POST /vault/translate gehört zu den localhost-Ausnahmen, der translate-Skill liefert auf dem Mac kein 401 mehr (iris/Iris#115)
Author
Owner

PR #102 gemergt: docs(wire): POST /vault/translate in den localhost-Ausnahmen des Mac-Servers (iris/Iris#115)
alf/2ndbrain#102

Commits:

  • docs(wire): POST /vault/translate in den localhost-Ausnahmen des Mac-Servers (iris/Iris#115)
PR #102 gemergt: docs(wire): POST /vault/translate in den localhost-Ausnahmen des Mac-Servers (iris/Iris#115) https://forgejo.lewerken.duckdns.org/alf/2ndbrain/pulls/102 Commits: - docs(wire): POST /vault/translate in den localhost-Ausnahmen des Mac-Servers (iris/Iris#115)
Author
Owner

Umgesetzt (PR #146, Wire-Doku PR #102 im Wurzel-Repo)

POST /vault/translate steht jetzt in der localhost-Ausnahmeliste des Mac-Servers (isLocalhostNotify), nur für Verbindungen von 127.0.0.1/::1. LAN- und Remote-Verbindungen bleiben bearer-pflichtig, der Linux-Server ist unverändert.

Geprüft: Die Änderung ist eine Zeile in der Ausnahmeliste; nicht gebaut und nicht gelaufen. Zum Prüfen: Iris neu bauen und starten, dann curl -sk -X POST https://127.0.0.1:8765/vault/translate -d '{"text":"Hallo","target_language":"en"}' ohne Token (kein 401 mehr) und die Übersetzung erneut anstoßen.

## Umgesetzt (PR #146, Wire-Doku PR #102 im Wurzel-Repo) `POST /vault/translate` steht jetzt in der localhost-Ausnahmeliste des Mac-Servers (`isLocalhostNotify`), nur für Verbindungen von 127.0.0.1/::1. LAN- und Remote-Verbindungen bleiben bearer-pflichtig, der Linux-Server ist unverändert. **Geprüft:** Die Änderung ist eine Zeile in der Ausnahmeliste; nicht gebaut und nicht gelaufen. **Zum Prüfen:** Iris neu bauen und starten, dann `curl -sk -X POST https://127.0.0.1:8765/vault/translate -d '{"text":"Hallo","target_language":"en"}'` ohne Token (kein 401 mehr) und die Übersetzung erneut anstoßen.
alf closed this issue 2026-10-27 10:37:21 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
iris/Iris#115
No description provided.