mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-08-05 02:08:44 +02:00
Add sanitized fetch health for agents
This commit is contained in:
@@ -1,4 +1,23 @@
|
||||
from services.fetch_health import record_success, record_failure, get_health_snapshot
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from services import fetch_health
|
||||
from services.fetch_health import (
|
||||
get_agent_health_snapshot,
|
||||
get_health_snapshot,
|
||||
record_failure,
|
||||
record_success,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def clear_fetch_health():
|
||||
with fetch_health._lock:
|
||||
fetch_health._health.clear()
|
||||
yield
|
||||
with fetch_health._lock:
|
||||
fetch_health._health.clear()
|
||||
|
||||
|
||||
def test_record_success_and_failure():
|
||||
@@ -13,3 +32,47 @@ def test_record_success_and_failure():
|
||||
assert entry["last_ok"] is not None
|
||||
assert entry["last_error"] is not None
|
||||
assert entry["last_duration_ms"] is not None
|
||||
|
||||
|
||||
def test_agent_health_snapshot_is_sanitized():
|
||||
fake_secret = "RECOGNIZABLE_FAKE_SECRET_FOR_FETCH_HEALTH"
|
||||
entry = {
|
||||
"ok_count": 3,
|
||||
"error_count": 2,
|
||||
"last_ok": "2026-07-30T12:00:00.000000",
|
||||
"last_error": "2026-07-30T11:00:00.000000",
|
||||
"last_error_msg": f"upstream failed with {fake_secret}",
|
||||
"last_duration_ms": 125.4,
|
||||
"avg_duration_ms": 98.7,
|
||||
"last_count": 42,
|
||||
}
|
||||
with fetch_health._lock:
|
||||
fetch_health._health["latest_success"] = dict(entry)
|
||||
fetch_health._health["latest_failure"] = {
|
||||
**entry,
|
||||
"last_ok": "2026-07-30T10:00:00.000000",
|
||||
"last_error": "2026-07-30T13:00:00.000000",
|
||||
}
|
||||
|
||||
snapshot = get_agent_health_snapshot()
|
||||
|
||||
assert {key: value for key, value in snapshot.items() if key != "tasks"} == {
|
||||
"scope": "process",
|
||||
"persistent": False,
|
||||
"observed_only": True,
|
||||
"semantics": "latest_recorded_task_outcome",
|
||||
}
|
||||
safe_fields = {
|
||||
"condition",
|
||||
"ok_count",
|
||||
"error_count",
|
||||
"last_ok",
|
||||
"last_error",
|
||||
"last_duration_ms",
|
||||
}
|
||||
assert set(snapshot["tasks"]["latest_success"]) == safe_fields
|
||||
assert snapshot["tasks"]["latest_success"]["condition"] == "healthy"
|
||||
assert snapshot["tasks"]["latest_failure"]["condition"] == "degraded"
|
||||
serialized = json.dumps(snapshot)
|
||||
assert "last_error_msg" not in serialized
|
||||
assert fake_secret not in serialized
|
||||
|
||||
@@ -130,6 +130,32 @@ class TestAuthenticatedRequestSucceeds:
|
||||
tool_names = {tool["name"] for tool in data["tools"]}
|
||||
assert set(data["available_commands"]).issubset(tool_names)
|
||||
|
||||
def test_fetch_health_read_command_dispatch_and_discovery(self, remote_client):
|
||||
from services.openclaw_channel import READ_COMMANDS, _dispatch_command
|
||||
|
||||
snapshot = {
|
||||
"scope": "process",
|
||||
"persistent": False,
|
||||
"observed_only": True,
|
||||
"semantics": "latest_recorded_task_outcome",
|
||||
"tasks": {},
|
||||
}
|
||||
with patch(
|
||||
"services.fetch_health.get_agent_health_snapshot", return_value=snapshot
|
||||
):
|
||||
result = _dispatch_command("get_fetch_health", {})
|
||||
|
||||
assert "get_fetch_health" in READ_COMMANDS
|
||||
assert result == {"ok": True, "data": snapshot}
|
||||
|
||||
headers = _sign("GET", "/api/ai/tools")
|
||||
r = remote_client.get("/api/ai/tools", headers=headers)
|
||||
assert r.status_code == 200, r.text
|
||||
tool = next(
|
||||
tool for tool in r.json()["tools"] if tool["name"] == "get_fetch_health"
|
||||
)
|
||||
assert tool["parameters"] == {}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Tampered body rejected (P1A body-binding at route layer)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Regression coverage for OpenClaw skill HMAC environment names."""
|
||||
|
||||
import asyncio
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
@@ -36,3 +37,25 @@ def test_openclaw_skill_accepts_legacy_key_as_hmac_secret_alias(monkeypatch):
|
||||
assert "X-SB-Signature" in headers
|
||||
assert "Authorization" not in headers
|
||||
assert "X-Admin-Key" not in headers
|
||||
|
||||
|
||||
def test_openclaw_skill_get_fetch_health_unwraps_command_result(monkeypatch):
|
||||
module = _load_sb_query(monkeypatch)
|
||||
client = module.ShadowBrokerClient()
|
||||
commands = []
|
||||
|
||||
async def send_command(cmd, args=None):
|
||||
commands.append((cmd, args))
|
||||
return {
|
||||
"result": {
|
||||
"ok": True,
|
||||
"data": {"scope": "process", "tasks": {}},
|
||||
}
|
||||
}
|
||||
|
||||
monkeypatch.setattr(client, "send_command", send_command)
|
||||
|
||||
result = asyncio.run(client.get_fetch_health())
|
||||
|
||||
assert commands == [("get_fetch_health", None)]
|
||||
assert result == {"scope": "process", "tasks": {}}
|
||||
|
||||
Reference in New Issue
Block a user