merge origin/main (779 commits) into ethie/pm-clean

Branch semantics kept where main and PM disagree: update_cmd_deps.py,
constraints-termux.txt, the Electron update-api-check module and the
post-swap hand-off test stay deleted; the pending-fleet-restart catch-up
and the local_runtime tag/download ladder stay retired (PM owns engines).

Ported from main onto the branch's shape: profile_scoped_chore for the
auto-archive and plugin-update housekeeping chores, the local-runtime
cross-process boot lock and residency cap, the checkpoint tmp_pack sweep,
the cua daemon-liveness status probe, the remote-served Desktop update
flag (posix.sh / windows.ps1), sign-in for env-pinned remote gateways
(urlDisabled on RemoteSetupFields), the uvloop extra split (uvicorn
without [standard]), and the umask-scoping spawn test.

uv.lock regenerated with pm.build_env --lock-only; new utf-8 reads from
main switched to utf-8-sig (check-windows-footguns).
This commit is contained in:
ethernet
2026-09-21 00:58:39 -04:00
1384 changed files with 51561 additions and 26427 deletions

View File

@@ -173,3 +173,45 @@ def test_post_discovery_registration_is_mirrored(_isolated_registries, monkeypat
)
assert LATE in auth_mod.PROVIDER_REGISTRY
assert auth_mod.PROVIDER_REGISTRY[LATE_ALIAS] is auth_mod.PROVIDER_REGISTRY[LATE]
def test_user_plugin_alias_repoints_and_display_name_follows(_isolated_registries, monkeypatch, tmp_path):
"""A $HERMES_HOME plugin owns the aliases it declares and the display name of a same-name row.
Ownership split (#116668): ``providers.get_provider_profile`` already followed the user's
profile for the alias, while the auth registry kept the alias on whichever row got there first
and kept the bundled display name on a same-name replacement.
"""
monkeypatch.setattr(providers, "_discover_entry_point_providers", lambda: None)
monkeypatch.setattr(providers, "_BUNDLED_PLUGINS_DIR", tmp_path)
monkeypatch.setattr(providers, "_user_plugins_dir", lambda: None)
monkeypatch.setattr(providers, "_installed_plugins_dir", lambda: None)
providers._discover_providers()
taken_alias = "probe-116668-alias"
monkeypatch.setattr(providers, "_current_source", "bundled")
providers.register_provider(ProviderProfile(
name="probe-116668-bundled", display_name="Bundled", base_url="https://bundled.example/v1",
env_vars=("PROBE_116668_BUNDLED_KEY",), aliases=(taken_alias,)))
bundled_row = auth_mod.PROVIDER_REGISTRY["probe-116668-bundled"]
assert auth_mod.PROVIDER_REGISTRY[taken_alias] is bundled_row
# A second bundled plugin claiming the same alias does not steal it.
providers.register_provider(ProviderProfile(
name="probe-116668-other", display_name="Other", base_url="https://other.example/v1",
env_vars=("PROBE_116668_OTHER_KEY",), aliases=(taken_alias,)))
assert auth_mod.PROVIDER_REGISTRY[taken_alias] is bundled_row
# The user's plugin does, and its same-name replacement rewrites the display name in place.
monkeypatch.setattr(providers, "_current_source", "user")
providers.register_provider(ProviderProfile(
name="probe-116668-user", display_name="Mine", base_url="https://mine.example/v1",
env_vars=("PROBE_116668_USER_KEY",), aliases=(taken_alias,)))
assert auth_mod.PROVIDER_REGISTRY[taken_alias] is auth_mod.PROVIDER_REGISTRY["probe-116668-user"]
providers.register_provider(ProviderProfile(
name="probe-116668-bundled", display_name="Bundled (mine)", base_url="https://mine.example/v2",
env_vars=("PROBE_116668_BUNDLED_KEY",), aliases=(taken_alias,)))
assert bundled_row.name == "Bundled (mine)"
assert bundled_row.inference_base_url == "https://mine.example/v2"
assert auth_mod.PROVIDER_REGISTRY[taken_alias] is bundled_row

View File

@@ -105,3 +105,60 @@ def test_token_url_off_authorize_allowlist_refused_before_any_request(idp, monke
assert {login_err.value.code, refresh_err.value.code} == {"oauth_token_host_rejected"}
with pytest.raises(AuthError, match="HTTPS"):
pkce.validate_config(PROVIDER, _config(idp, authorize_url="http://auth.example.com/authorize"))
def test_spent_refresh_token_is_grant_dead_and_marks_the_pool_row_dead(idp, monkeypatch, tmp_path, request):
"""RFC 6749 invalid_grant on refresh is terminal. The pool must DEAD the row, not EXHAUST it."""
from agent.credential_pool import STATUS_DEAD, load_pool
monkeypatch.setattr(pkce.webbrowser, "open", _browser_hits)
monkeypatch.setattr("hermes_cli.auth_device_flow._can_open_graphical_browser", lambda: True)
cfg = _config(idp)
handler, refresh = pkce.pkce_auth_handler(cfg), pkce.pkce_refresh_credential(cfg)
register_provider(ProviderProfile(name=PROVIDER, auth_type="oauth_external",
base_url="https://example.invalid/v1",
auth_handler=handler, refresh_credential=refresh))
request.addfinalizer(lambda: (providers._REGISTRY.pop(PROVIDER, None),
hermes_cli.auth.PROVIDER_REGISTRY.pop(PROVIDER, None)))
args = SimpleNamespace(provider=PROVIDER, no_browser=False)
assert handler("add", args) is True
rows = json.loads((tmp_path / "hermes" / "auth.json").read_text())["credential_pool"][PROVIDER]
spent = rows[0]["refresh_token"]
idp.refresh_tokens.discard(spent)
with pytest.raises(AuthError) as excinfo:
refresh(SimpleNamespace(provider=PROVIDER, id=rows[0]["id"], refresh_token=spent,
access_token=rows[0]["access_token"], expires_at_ms=None))
assert excinfo.value.code == "invalid_grant"
pool = load_pool(PROVIDER)
result = pool.try_refresh_matching(credential_id=rows[0]["id"])
assert result is None or result.last_status == STATUS_DEAD
disk = json.loads((tmp_path / "hermes" / "auth.json").read_text())["credential_pool"][PROVIDER][0]
assert disk["last_status"] == STATUS_DEAD
def test_alias_login_stores_the_row_under_the_canonical_profile_name(idp, monkeypatch, tmp_path, request):
"""hermes auth add <alias> must write the pool under ProviderProfile.name, not the typed alias."""
from agent.credential_pool import load_pool
alias = "example-pkce-alias"
monkeypatch.setattr(pkce.webbrowser, "open", _browser_hits)
monkeypatch.setattr("hermes_cli.auth_device_flow._can_open_graphical_browser", lambda: True)
cfg = _config(idp)
handler = pkce.pkce_auth_handler(cfg)
register_provider(ProviderProfile(
name=PROVIDER, aliases=(alias,), auth_type="oauth_external",
base_url="https://example.invalid/v1",
auth_handler=handler, refresh_credential=pkce.pkce_refresh_credential(cfg)))
request.addfinalizer(lambda: (
providers._REGISTRY.pop(PROVIDER, None),
providers._ALIASES.pop(alias, None),
hermes_cli.auth.PROVIDER_REGISTRY.pop(PROVIDER, None),
hermes_cli.auth.PROVIDER_REGISTRY.pop(alias, None)))
args = SimpleNamespace(provider=alias, no_browser=False)
assert handler("add", args) is True
pool = json.loads((tmp_path / "hermes" / "auth.json").read_text())["credential_pool"]
assert PROVIDER in pool and alias not in pool
assert handler("status", args) is True
assert load_pool(PROVIDER).entries()[0].provider == PROVIDER