Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
"""Tests for plugins/memory/honcho/oauth.py — OAuth grant storage + refresh."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from plugins.memory.honcho import oauth
|
||||
from plugins.memory.honcho.oauth import OAuthCredential
|
||||
|
||||
|
||||
def _host_block(refresh="hch-rt-old", expires_at=10_000):
|
||||
return {
|
||||
"apiKey": "hch-at-old",
|
||||
"oauth": {
|
||||
"refreshToken": refresh,
|
||||
"expiresAt": expires_at,
|
||||
"clientId": "hermes-desktop",
|
||||
"tokenEndpoint": "http://localhost:8000/oauth/token",
|
||||
"scope": "write",
|
||||
"tokenType": "Bearer",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _write(path: Path, raw: dict) -> None:
|
||||
path.write_text(json.dumps(raw), encoding="utf-8")
|
||||
|
||||
|
||||
class TestTokenDetection:
|
||||
def test_access_token_prefix(self):
|
||||
assert oauth.is_oauth_access_token("hch-at-abc")
|
||||
assert not oauth.is_oauth_access_token("hch-v3-abc")
|
||||
assert not oauth.is_oauth_access_token("hch-rt-abc")
|
||||
assert not oauth.is_oauth_access_token(None)
|
||||
|
||||
|
||||
class TestCredentialModel:
|
||||
def test_roundtrip(self):
|
||||
cred = OAuthCredential.from_host_block(_host_block())
|
||||
assert cred is not None
|
||||
block = cred.oauth_block()
|
||||
assert block["refreshToken"] == "hch-rt-old"
|
||||
assert block["expiresAt"] == 10_000
|
||||
assert block["clientId"] == "hermes-desktop"
|
||||
|
||||
def test_incomplete_block_returns_none(self):
|
||||
# plain API key (no oauth sub-block)
|
||||
assert OAuthCredential.from_host_block({"apiKey": "hch-v3-x"}) is None
|
||||
# oauth block missing refreshToken
|
||||
bad = _host_block()
|
||||
del bad["oauth"]["refreshToken"]
|
||||
assert OAuthCredential.from_host_block(bad) is None
|
||||
|
||||
def test_is_expired_respects_skew(self):
|
||||
cred = OAuthCredential.from_host_block(_host_block(expires_at=1000))
|
||||
assert not cred.is_expired(now=800, skew=120) # 1000-120=880 > 800
|
||||
assert cred.is_expired(now=900, skew=120) # 900 >= 880
|
||||
|
||||
|
||||
class TestEnsureFreshToken:
|
||||
def test_no_oauth_credential_is_noop(self, tmp_path):
|
||||
path = tmp_path / "honcho.json"
|
||||
_write(path, {"hosts": {"hermes": {"apiKey": "hch-v3-static"}}})
|
||||
token, refreshed = oauth.ensure_fresh_token(path, "hermes", now=0)
|
||||
assert token is None and refreshed is False
|
||||
|
||||
def test_fresh_token_skips_refresh(self, tmp_path, monkeypatch):
|
||||
path = tmp_path / "honcho.json"
|
||||
_write(path, {"hosts": {"hermes": _host_block(expires_at=10_000)}})
|
||||
monkeypatch.setattr(
|
||||
oauth, "_http_post_form_status",
|
||||
lambda *a, **k: pytest.fail("refresh must not be called when fresh"),
|
||||
)
|
||||
token, refreshed = oauth.ensure_fresh_token(path, "hermes", now=0)
|
||||
assert token == "hch-at-old" and refreshed is False
|
||||
|
||||
|
||||
def test_expired_token_refreshes_and_persists_rotation(self, tmp_path, monkeypatch):
|
||||
path = tmp_path / "honcho.json"
|
||||
_write(path, {"hosts": {"hermes": _host_block(expires_at=100)}})
|
||||
|
||||
def fake_post(url, data, timeout):
|
||||
assert data["grant_type"] == "refresh_token"
|
||||
assert data["refresh_token"] == "hch-rt-old"
|
||||
assert data["client_id"] == "hermes-desktop"
|
||||
return 200, {
|
||||
"access_token": "hch-at-new",
|
||||
"refresh_token": "hch-rt-new",
|
||||
"expires_in": 3600,
|
||||
"scope": "write",
|
||||
"token_type": "Bearer",
|
||||
}
|
||||
|
||||
monkeypatch.setattr(oauth, "_http_post_form_status", fake_post)
|
||||
token, refreshed = oauth.ensure_fresh_token(path, "hermes", now=1000)
|
||||
assert token == "hch-at-new" and refreshed is True
|
||||
|
||||
# Rotated refresh token + new access token + absolute expiry persisted.
|
||||
saved = json.loads(path.read_text())["hosts"]["hermes"]
|
||||
assert saved["apiKey"] == "hch-at-new"
|
||||
assert saved["oauth"]["refreshToken"] == "hch-rt-new"
|
||||
assert saved["oauth"]["expiresAt"] == 1000 + 3600
|
||||
|
||||
def test_refresh_failure_fails_open(self, tmp_path, monkeypatch):
|
||||
path = tmp_path / "honcho.json"
|
||||
_write(path, {"hosts": {"hermes": _host_block(expires_at=100)}})
|
||||
monkeypatch.setattr(oauth, "_REFRESH_RETRY_DELAY_SECONDS", 0)
|
||||
|
||||
calls = []
|
||||
|
||||
def boom(*a, **k):
|
||||
calls.append(a)
|
||||
raise RuntimeError("network down")
|
||||
|
||||
monkeypatch.setattr(oauth, "_http_post_form_status", boom)
|
||||
token, refreshed = oauth.ensure_fresh_token(path, "hermes", now=1000)
|
||||
# Stale token returned, no crash, file untouched. Transient failures
|
||||
# retry exactly once, then fail open.
|
||||
assert token == "hch-at-old" and refreshed is False
|
||||
assert len(calls) == 2
|
||||
assert json.loads(path.read_text())["hosts"]["hermes"]["apiKey"] == "hch-at-old"
|
||||
|
||||
def test_double_check_uses_disk_when_already_rotated(self, tmp_path, monkeypatch):
|
||||
# Simulates a concurrent thread that rotated the token on disk after our
|
||||
# stale in-memory snapshot: the locked re-read must skip the HTTP call.
|
||||
path = tmp_path / "honcho.json"
|
||||
_write(path, {"hosts": {"hermes": _host_block(refresh="hch-rt-fresh", expires_at=10_000)}})
|
||||
stale_raw = {"hosts": {"hermes": _host_block(refresh="hch-rt-old", expires_at=100)}}
|
||||
stale_raw["hosts"]["hermes"]["apiKey"] = "hch-at-stale"
|
||||
monkeypatch.setattr(
|
||||
oauth, "_http_post_form_status",
|
||||
lambda *a, **k: pytest.fail("must not refresh; disk token is fresh"),
|
||||
)
|
||||
token, refreshed = oauth.ensure_fresh_token(path, "hermes", stale_raw, now=1000)
|
||||
assert token == "hch-at-old" # the on-disk fresh credential's access token
|
||||
|
||||
|
||||
class TestInstallGrant:
|
||||
def test_deep_merges_config_and_preserves_other_hosts(self, tmp_path):
|
||||
path = tmp_path / "honcho.json"
|
||||
_write(path, {
|
||||
"apiKey": "hch-v3-root", # root static key preserved
|
||||
"hosts": {
|
||||
"obsidian": {"workspace": "obsidian"},
|
||||
"hermes": {"workspace": "hermes", "saveMessages": False},
|
||||
},
|
||||
})
|
||||
grant = {
|
||||
"access_token": "hch-at-fresh",
|
||||
"refresh_token": "hch-rt-fresh",
|
||||
"expires_in": 3600,
|
||||
"scope": "write",
|
||||
"config": {
|
||||
"environment": "production",
|
||||
"hosts": {"hermes": {"saveMessages": True, "recallMode": "hybrid"}},
|
||||
},
|
||||
}
|
||||
cred = oauth.install_grant(
|
||||
path, "hermes", grant,
|
||||
client_id="hermes-desktop",
|
||||
token_endpoint="http://localhost:8000/oauth/token",
|
||||
now=1000,
|
||||
)
|
||||
assert cred.expires_at == 1000 + 3600
|
||||
|
||||
saved = json.loads(path.read_text())
|
||||
assert saved["apiKey"] == "hch-v3-root" # untouched
|
||||
assert saved["hosts"]["obsidian"] == {"workspace": "obsidian"} # untouched
|
||||
h = saved["hosts"]["hermes"]
|
||||
assert h["apiKey"] == "hch-at-fresh"
|
||||
assert h["oauth"]["refreshToken"] == "hch-rt-fresh"
|
||||
assert h["saveMessages"] is True # grant config won the deep-merge
|
||||
assert h["recallMode"] == "hybrid" # new key added
|
||||
assert h["workspace"] == "hermes" # pre-existing key preserved
|
||||
assert saved["environment"] == "production" # root key from grant
|
||||
|
||||
def test_rejects_grant_without_tokens(self, tmp_path):
|
||||
path = tmp_path / "honcho.json"
|
||||
_write(path, {})
|
||||
with pytest.raises(ValueError):
|
||||
oauth.install_grant(
|
||||
path, "hermes", {"access_token": "hch-at-x"}, # no refresh_token
|
||||
client_id="c", token_endpoint="e",
|
||||
)
|
||||
|
||||
|
||||
class TestApplyTokenToClient:
|
||||
def test_mutates_live_bearer(self):
|
||||
class FakeHttp:
|
||||
api_key = "hch-at-old"
|
||||
|
||||
class FakeClient:
|
||||
_http = FakeHttp()
|
||||
|
||||
client = FakeClient()
|
||||
assert oauth.apply_token_to_client(client, "hch-at-new") is True
|
||||
assert client._http.api_key == "hch-at-new"
|
||||
|
||||
def test_returns_false_when_shape_unknown(self):
|
||||
assert oauth.apply_token_to_client(object(), "hch-at-new") is False
|
||||
Reference in New Issue
Block a user