feat(scada): require complete authorized investigation evidence
Generic Container CI/CD / test-build-publish (push) Successful in 5m52s
Server CI/CD v2 / build-test-publish-and-deploy (push) Successful in 5m52s

This commit is contained in:
2026-11-07 21:15:01 +08:00
parent 2552a9b40d
commit 06d8539aa8
12 changed files with 498 additions and 30 deletions
+28
View File
@@ -774,6 +774,34 @@ def test_scada_catalog_default_100_paginates_without_changing_other_queries(runt
assert TOOLS["list_elements"].model(context_handle=value.context_handle, element_type="pipe").limit == 20
@pytest.mark.parametrize("complete", [False, True])
def test_complete_scada_input_is_not_replaced_by_12kb_preview_but_details_stay_bounded(runtime, complete):
app, client, _, _ = runtime
value = binding()
data = {"devices": [{"device_id": f"D{index}", "node_id": f"J{index}", "description": "x" * 100}
for index in range(168)],
"readings": [{"device_id": f"D{index}", "monitored_value": 20., "cleaned_value": 19.}
for index in range(168)],
"coverage": {"mode": "all_scada", "query_complete": True, "queried_device_count": 168}}
assert len(json.dumps(data).encode()) > 12000
app.executor = AsyncMock(return_value=QueryResult(
source="query_scada_readings", source_ref="mcp:all-scada", queried_at=datetime.now(timezone.utc),
semantics="observed", data=data,
))
arguments = {"context_handle": value.context_handle, "start": "2026-07-16T05:00:00+08:00",
"end": "2026-07-16T08:00:00+08:00"}
if not complete:
arguments["device_ids"] = ["D1"]
response = request(client, "tools/call", {"name": "query_scada_readings", "arguments": arguments}).json()["result"]
if complete:
assert not response.get("isError"), response
assert response["structuredContent"]["data"] == data
assert response["structuredContent"]["truncated"] is False
else:
assert response["isError"] is True
assert response["structuredContent"]["error"]["code"] == "RESULT_TOO_LARGE"
def test_business_skill_is_delivered_over_mcp_without_recording_event_evidence(runtime, monkeypatch):
app, client, _, _ = runtime
value = binding(task=True)