feat(server): integrate MCP queries and investigation messaging
Add project-bound OAuth MCP queries and controlled analysis with scoped evidence, limits, timeouts and a nearby-model spatial query using EPSG:4326 inputs. Default nearby searches to 200 meters and five results. Integrate investigation messaging/presentation, health/readiness and typed history; remove duplicate web search and fix online simulation and compressed baseline writes. Include project migrations 023-025; keep local credentials and demo seeding excluded. Validation: 319 focused pytest checks; real PostGIS temporary-table regression; read-only Jinqian bridge radius comparison; cross-language MCP discovery/calls.
This commit is contained in:
@@ -6,7 +6,7 @@ from pydantic import ValidationError
|
||||
|
||||
from app.auth.project_dependencies import ProjectContext
|
||||
from app.api.v1.endpoints.operational_tasks import _task_permissions
|
||||
from app.auth.permissions import SCADA_VIEW, SIMULATION_VIEW
|
||||
from app.auth.permissions import SCADA_VIEW, SIMULATION_VIEW, permissions_for_context
|
||||
from app.domain.schemas.operational_data import TaskDataQuery
|
||||
from app.infra.integrations.operational_data import TaskDataError, TaskDataSettings, read_task_data
|
||||
|
||||
@@ -133,12 +133,42 @@ def test_query_is_a_finite_read_scope_with_bounded_time_and_device_count():
|
||||
TaskDataQuery(source="peripheral_observations")
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
@pytest.mark.parametrize("source", ["scada_devices", "peripheral_work_orders"])
|
||||
async def test_task_service_reads_with_existing_project_permissions(source):
|
||||
ctx = ProjectContext(project_id=uuid4(), user_id=uuid4(), project_code="test",
|
||||
project_role="member", system_role="service")
|
||||
permissions = _task_permissions(ctx)
|
||||
assert permissions == set(permissions_for_context(ctx))
|
||||
assert {SCADA_VIEW, SIMULATION_VIEW} <= permissions
|
||||
|
||||
def handler(request):
|
||||
assert request.method == "GET"
|
||||
assert request.headers["Authorization"] == "Bearer AGENT"
|
||||
assert request.headers["X-Project-Id"] == str(ctx.project_id)
|
||||
return httpx.Response(200, json={"items": [], "project_id": str(ctx.project_id)})
|
||||
|
||||
snapshot = await read_task_data(
|
||||
context=ctx, credential="Bearer AGENT", query=TaskDataQuery(source=source),
|
||||
settings=settings(), transport=httpx.MockTransport(handler),
|
||||
)
|
||||
assert snapshot.source == source
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_service_without_project_read_permission_does_not_gain_access():
|
||||
ctx = ProjectContext(project_id=uuid4(), user_id=uuid4(), project_code="test",
|
||||
project_role="", system_role="service")
|
||||
assert not {SCADA_VIEW, SIMULATION_VIEW} & _task_permissions(ctx)
|
||||
with pytest.raises(TaskDataError, match="没有该数据源的读取权限"):
|
||||
await read_task_data(context=ctx, credential="Bearer AGENT",
|
||||
query=TaskDataQuery(source="scada_devices"), settings=settings())
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_task_service_uses_approved_delegation_only_during_source_read():
|
||||
ctx = ProjectContext(project_id=uuid4(), user_id=uuid4(), project_code="test",
|
||||
project_role="member", system_role="service")
|
||||
assert SCADA_VIEW not in _task_permissions(ctx)
|
||||
assert SIMULATION_VIEW not in _task_permissions(ctx)
|
||||
query = TaskDataQuery(source="scada_devices")
|
||||
with pytest.raises(TaskDataError, match="委托身份尚未配置"):
|
||||
await read_task_data(context=ctx, credential="Bearer AGENT", query=query,
|
||||
|
||||
Reference in New Issue
Block a user