mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fix(gateway): scope pairing platform discovery to the profile dir
The per-profile pairing isolation added self._dir and scoped every per-file path helper (_pending_path, _approved_path) to it, but _all_platforms still enumerated the module-global PAIRING_DIR. For a profile-scoped PairingStore, list_approved/list_pending/clear_pending therefore operated on the GLOBAL platform set while loading each platform's file from the PROFILE dir — so list_approved() returned [] for a user that is_approved() confirmed as approved, a silent divergence between the authz surface and the list/inspect/clear surface. Route discovery through self._dir. Byte-identical for the global store (self._dir == PAIRING_DIR when no profile is set); only the buggy profile-scoped case changes. self._dir is guaranteed to exist (__init__ mkdirs it).
This commit is contained in:
parent
d063684b3f
commit
4cbd46545e
2 changed files with 29 additions and 1 deletions
|
|
@ -727,7 +727,7 @@ class PairingStore:
|
|||
def _all_platforms(self, suffix: str) -> list:
|
||||
"""List all platforms that have data files of a given suffix."""
|
||||
platforms = []
|
||||
for f in PAIRING_DIR.iterdir():
|
||||
for f in self._dir.iterdir():
|
||||
if f.name.endswith(f"-{suffix}.json"):
|
||||
platform = f.name.replace(f"-{suffix}.json", "")
|
||||
if not platform.startswith("_"):
|
||||
|
|
|
|||
|
|
@ -46,6 +46,34 @@ class TestSplitPairingDirMigration:
|
|||
assert "ou_user" in migrated
|
||||
|
||||
|
||||
class TestProfileScopedDiscovery:
|
||||
def test_list_approved_scopes_platform_discovery_to_profile_dir(self, tmp_path):
|
||||
# A profile-scoped store must enumerate platforms from its own
|
||||
# per-profile directory (self._dir), not the module-global PAIRING_DIR.
|
||||
# Regression: _all_platforms iterated PAIRING_DIR while every per-file
|
||||
# path helper routed through self._dir, so a profile store confirmed a
|
||||
# user via is_approved() (reads self._dir) yet returned [] from
|
||||
# list_approved() (scanned the empty global dir).
|
||||
home = tmp_path / "home"
|
||||
global_dir = tmp_path / "global-pairing"
|
||||
global_dir.mkdir(parents=True)
|
||||
|
||||
with patch("gateway.pairing.PAIRING_DIR", global_dir), patch(
|
||||
"gateway.pairing.get_hermes_home", return_value=home
|
||||
):
|
||||
store = PairingStore(profile="alice")
|
||||
# Store lives under the profile dir, provably distinct from PAIRING_DIR.
|
||||
assert store._dir != global_dir
|
||||
with store._lock:
|
||||
store._approve_user("telegram", "tg-456", "Bob")
|
||||
|
||||
assert store.is_approved("telegram", "tg-456") is True
|
||||
approved = store.list_approved()
|
||||
|
||||
assert [r["user_id"] for r in approved] == ["tg-456"]
|
||||
assert approved[0]["platform"] == "telegram"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# _secure_write
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue