mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-24 16:54:43 +00:00
fix(openviking): match tenant-header errors structurally instead of hard-coding strings
The _needs_trusted_identity_retry method was hard-coding specific
server-side error strings to detect when a request failed due to
missing X-OpenViking-Account / X-OpenViking-User headers. Each new
server-side error variant required another string added to the client.
Replace the string enumeration with a structural match: the error
message mentions one of the tenant headers AND the HTTP status is 400.
This covers all current error variants:
- "Trusted mode requests must include X-OpenViking-Account and User"
- "ROOT requests to tenant-scoped APIs must include X-OpenViking-Account"
- "Trusted mode requests must include X-OpenViking-Account."
- "Trusted mode requests must include X-OpenViking-User."
The 400 status guard avoids false-positives on 403 errors such as
"USER API keys cannot override X-OpenViking-User", which must not
trigger a retry.
All 176 existing tests pass.
(cherry picked from commit 5a24d6766c)
This commit is contained in:
parent
82a383d970
commit
5ea3abc3b3
2 changed files with 24 additions and 9 deletions
|
|
@ -294,12 +294,23 @@ class _VikingClient:
|
|||
|
||||
@staticmethod
|
||||
def _needs_trusted_identity_retry(exc: Exception) -> bool:
|
||||
"""Detect errors that indicate missing tenant-scoped identity headers.
|
||||
|
||||
Trusted mode can ask for ``X-OpenViking-Account`` /
|
||||
``X-OpenViking-User`` using slightly different wording across
|
||||
OpenViking versions. Match that trusted-mode missing-identity shape
|
||||
instead of enumerating every exact string, while keeping deliberate
|
||||
API-key permission denials non-retriable.
|
||||
"""
|
||||
message = str(exc)
|
||||
return (
|
||||
"Trusted mode requests must include X-OpenViking-Account" in message
|
||||
or "Trusted mode requests must include X-OpenViking-User" in message
|
||||
or "Trusted mode requests must include X-OpenViking-Account or explicit account_id" in message
|
||||
)
|
||||
if "Trusted mode requests must include" not in message:
|
||||
return False
|
||||
if "X-OpenViking-Account" not in message and "X-OpenViking-User" not in message:
|
||||
return False
|
||||
status_code = getattr(exc, "status_code", None)
|
||||
if status_code is not None and status_code != 400:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _send_with_trusted_identity_retry(self, send, *, multipart: bool = False) -> dict:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1956,12 +1956,16 @@ def test_viking_client_does_not_retry_root_tenant_error_as_trusted_mode(monkeypa
|
|||
captured_headers.append(kwargs.get("headers") or {})
|
||||
if len(captured_headers) == 1:
|
||||
return SimpleNamespace(
|
||||
status_code=400,
|
||||
status_code=403,
|
||||
text="",
|
||||
json=lambda: {
|
||||
"error": {
|
||||
"code": "INVALID_ARGUMENT",
|
||||
"message": "ROOT requests to tenant-scoped APIs must include X-OpenViking-Account and X-OpenViking-User headers.",
|
||||
"code": "PERMISSION_DENIED",
|
||||
"message": (
|
||||
"ROOT API keys cannot access tenant-scoped data APIs in api_key mode. "
|
||||
"Use a user/admin API key for data access, or trusted mode for upstream "
|
||||
"identity assertion."
|
||||
),
|
||||
},
|
||||
},
|
||||
raise_for_status=lambda: None,
|
||||
|
|
@ -1975,7 +1979,7 @@ def test_viking_client_does_not_retry_root_tenant_error_as_trusted_mode(monkeypa
|
|||
|
||||
monkeypatch.setattr(client._httpx, "post", capture_post)
|
||||
|
||||
with pytest.raises(openviking_module._OpenVikingHTTPError, match="ROOT requests"):
|
||||
with pytest.raises(openviking_module._OpenVikingHTTPError, match="ROOT API keys cannot access"):
|
||||
client.post("/api/v1/search/search", {"query": "status"})
|
||||
|
||||
assert len(captured_headers) == 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue