Gäste im Free-Tier bekommen für Connectoren keine Browser-Challenge mehr: das gescopte Guest-Token


Sie haben auf einem Server einen geplanten Job zurückgelassen, der Ihren Kalender liest, ein paar Listen prüft und über das Free-Tier einige Managed Tools aufruft. In der letzten Nacht ist er wieder fehlgeschlagen. Im Log steht kein Stacktrace — nur ein ausgegebener Link, und dann endet der Job still. Sie haben den Link einmal angeklickt und alles war wieder normal, aber nächste Woche kann er um 3 Uhr morgens erneut scheitern.

Dieser Link ist die Browser-Challenge des Free-Tiers. Wir haben erklärt, warum sie erscheint, und wie Hermes daraus einen nicht blockierenden Ablauf im Stil „Link ausgeben, Status pollen“ gemacht hat. Damit war nur die Hälfte des Problems gelöst: ein Gast, der ausschließlich Connectoren nutzt, hätte nie beweisen müssen, dass er ein Mensch ist.

Eine im Zeitfenster von v0.21.7 gemergte Änderung schließt diese Hälfte. Connectoren und Managed Tools nutzen jetzt ein dediziertes Token, das den Challenge-Ablauf überhaupt nicht betritt.

Ein Gast hat tatsächlich zwei Arten von Berechtigung

Zunächst, warum es zwei Tokens gibt. Im Free-Tier kann ein Gast zwei recht unterschiedliche Dinge tun:

  • Inference aufrufen — ein freies Modell etwas generieren lassen. Das verbraucht Compute.
  • Connectoren und Managed Tools aufrufen — das Konto lesen, das Tool-Gateway ansprechen, über Connectoren routen. Meist reine Weiterleitung, und es verbraucht kein Inference-Kontingent.

Die Challenge, einschließlich des Proof-of-Work-Gates, existiert, um Compute vor Missbrauch zu schützen, gehört also nur auf die Inference-Seite. In der alten Implementierung wurde ein Gast, der einen Connector berührte, trotzdem durch einen Inference-Token-Austausch gezogen — und damit durch eine Challenge, die niemand brauchte.

Der Server kennt nun den Unterschied: der anonyme Token-Austausch nimmt einen purpose-Parameter entgegen, und purpose: "connectors" prägt ein JWT, dessen einziger Scope connectors:invoke ist. Das Gateway erlässt für dieses Token die Challenge- und PoW-Gates und lehnt es für Inference ab.

Der Scope-Claim wählt den Slot, nicht der Mint, der ihn erzeugt hat

Das ist das Design-Detail, das man sich merken sollte: welchen Slot ein Token füllt, ergibt sich aus seinem eigenen JWT-scope-Claim, nicht daraus, welcher Mint ihn erzeugt hat.

  • Das Connectoren-Token liegt in providers.nous.connectors_token (access_token + expires_at), direkt neben dem bestehenden Inference-Slot.
  • Der Inference-Mint ist unverändert: weiterhin lazy, weiterhin beim ersten tatsächlichen Aufruf eines freien Modells, weiterhin in den Challenge-Ablauf eingebettet.
  • Aufrufer von Connectoren nutzen nun das bereits aktive Token wieder — ein Inference-Token deckt Connectoren mit ab, es wird also nichts zusätzlich geprägt.

Den Scope statt der Herkunft zu lesen hält die Kompatibilität sauber. Ein älteres Portal ignoriert purpose und liefert ein Inference-Token zurück, das damit im Inference-Slot landet. Und wenn dieser ältere Server eine Connectoren-Anfrage mit 428 beantwortet, fällt der Connectoren-Aufruf auf die heutige Challenge-Behandlung zurück, statt zu scheitern.

Drei Hintergrundpfade, die früher versehentlich Inference geprägt haben

Das ist der Teil, der Debugging verwirrend macht — keiner davon wird vom Nutzer ausgelöst:

  • Auth-Keepalive. Er frischte früher bei jedem Tick das Inference-Token für jeden Gast auf, und das Messaging-Gateway und das Desktop-Backend starten ihn bedingungslos. Unter Enforcement bedeutete das einen 428 pro Tick für einen Gast, der nur Connectoren nutzt, plus eine versteckte Challenge auf dem Desktop. Jetzt überspringt er einen Gast vollständig und folgt damit der Guard, die die Startfunktion ohnehin schon hatte: die Tokens eines Gasts werden bei Bedarf erzeugt.
  • Der Nous-Modellkatalog und die Preisliste. _nous_catalog (erreichbar über provider_model_ids("nous")) und _resolve_nous_pricing_credentials liefen im Vordergrund, sodass das Auflisten von Nous-Modellen als Gast über die CLI eine Browser-Challenge öffnen konnte. Beide laufen jetzt als Hintergrundaufrufer und fallen auf die kuratierte Liste und die öffentlichen Preise zurück, genau wie sie es bei einem Credential-Fehler ohnehin schon taten.
  • Konto-Lesezugriffe. Diese liegen auf der Connectoren-Seite und nehmen daher das Connectoren-Token.

Der kombinierte Effekt: eine Challenge erscheint jetzt nur noch in dem Moment, in dem Sie tatsächlich ein freies Modell aufrufen.

Was sich nicht geändert hat

  • Angemeldete Konten, der Inference-Pfad und die persistierte Gast-Struktur bleiben unberührt.
  • Ein 403 (signin_required / access_denied) bei einem Connectoren-Mint erscheint mit demselben Code und Text wie zuvor — kein neuer nutzerseitiger Text.
  • Zwischen den beiden Mints wird nichts geteilt, es wurden also keine Sperren oder keyed Memos pro Zweck hinzugefügt: das Mint-Fehler-Memo deckt die Identitätserzeugung ab (die keinen Zweck hat), das 5-Sekunden-Token-Memo existiert nur im Connectoren-Resolver, und der Challenge-Zustand (Work-Lock, Give-up-Cooldown) wird nur von einem Mint erreicht, der ein 428 bekommt — was auf einem aktuellen Server der Inference-Mint ist.

Erkennen, welchen Pfad ein Aufruf genommen hat

Worauf es beim Debugging ankommt, ist, an wen der Aufruf tatsächlich gegangen ist. Ein paar Stellen zum Nachsehen:

# anonymer Token-Austausch und Challenge-Zustand (Gast-Identität)
hermes logs --follow | grep -i -E "anon|challenge|connectors"

# Status auf der Konto-Seite
hermes account status

# wo die Auth-Slots landen (unter dem Host-Home)
ls -l "$HERMES_HOME/auth.json"

Wenn Sie einen Challenge-Link sehen, während Ihre Workload nur Connectoren oder Managed Tools berührt, sind Sie auf einem älteren Build: ab v0.21.7 läuft dieser Pfad nicht mehr durch eine Challenge. Wenn Sie tatsächlich ein freies Modell aufrufen, ist eine Challenge zu erwarten — der frühere Beitrag dreht sich darum, sie daran zu hindern, unbeaufsichtigte Läufe zu blockieren.

Einschränkungen

  • Das dedizierte Token ist nicht für Inference verwendbar — das Gateway lehnt es ab. Den Wert aus connectors_token in eine Inference-Konfiguration zu kopieren, beschert Ihnen nur einen Authentifizierungsfehler.
  • Der Bild-Standard des Free-Pools folgte der Änderung „Abonnenten standardmäßig auf Krea“ nicht; Resource-Pools werden weiterhin unabhängig entschieden.
  • Bei einem selbst gehosteten oder älteren privaten Deployment hängt das Verhalten von diesem Server ab: ein alter Server ignoriert purpose und alles bleibt wie es war, und ein 428 fällt auf die alte Behandlung zurück, statt abzustürzen.

Das Fazit

Der Wert hier ist keine neue API — es sind feinere Berechtigungen. Die Seite, die von Ihnen den Nachweis verlangt, ein Mensch zu sein (Inference), behält die Challenge; die reine Weiterleitungsseite (Connectoren, Managed Tools) kommt mit einem scope-begrenzten Token durch. Für unbeaufsichtigte geplante Jobs entfernt das einen zuvor intermittierenden, schwer reproduzierbaren Fehler — nicht indem man ihn umgeht, sondern indem man den Grund für seine Existenz beseitigt.