103 lines
3.7 KiB
Python
103 lines
3.7 KiB
Python
"""Public MCP selectors must not leak storage coordinates to coding agents."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
MCP = Path(__file__).resolve().parents[2] / "plugins" / "1c" / "mcp"
|
|
if str(MCP) not in sys.path:
|
|
sys.path.insert(0, str(MCP))
|
|
|
|
import adapter_1c_mcp as mcp # noqa: E402
|
|
|
|
|
|
def test_read_selector_is_replaced_with_opaque_token() -> None:
|
|
mcp.SELECTOR_TOKENS.clear()
|
|
result = mcp.publicize_read_selectors(
|
|
{
|
|
"read_selector": {
|
|
"method": "metadata.form.decode",
|
|
"base_id": "upo_test",
|
|
"table": "ConfigCAS",
|
|
"file_name": "hash-key",
|
|
"guid": "11111111-1111-1111-1111-111111111111",
|
|
}
|
|
}
|
|
)
|
|
|
|
selector = result["read_selector"]
|
|
assert selector["method"] == "metadata.form.decode"
|
|
assert selector["selector_token"].startswith("onecsel_")
|
|
assert "table" not in selector
|
|
assert "file_name" not in selector
|
|
|
|
payload, error = mcp.resolve_selector_token("metadata.form.decode", {"selector_token": selector["selector_token"]})
|
|
assert error is None
|
|
assert payload is not None
|
|
assert payload["table"] == "ConfigCAS"
|
|
assert payload["file_name"] == "hash-key"
|
|
assert payload["_selector_token_resolved"] is True
|
|
|
|
|
|
def test_public_result_hides_nested_technical_fields() -> None:
|
|
result = mcp.publicize_read_selectors(
|
|
{"object": {"name": "Тест", "guid": "private"}, "source": {"table": "ConfigSave"}}
|
|
)
|
|
assert result == {"object": {"name": "Тест"}, "source": {}}
|
|
|
|
|
|
def test_selector_token_cannot_be_reused_for_another_method() -> None:
|
|
token = mcp.issue_selector_token({"method": "code.read", "base_id": "upo_test", "module_ref": "private"})
|
|
payload, error = mcp.resolve_selector_token("metadata.form.decode", {"selector_token": token})
|
|
assert payload is None
|
|
assert error is not None
|
|
assert error["error"] == "selector_token_method_mismatch"
|
|
|
|
|
|
def test_normal_agent_request_rejects_technical_coordinates() -> None:
|
|
blocked = mcp.normal_agent_technical_field_guardrail(
|
|
"metadata.form.decode",
|
|
{"base_id": "upo_test", "table": "ConfigCASSave", "file_name": "private"},
|
|
)
|
|
assert blocked is not None
|
|
assert blocked["reason"] == "technical_selector_forbidden"
|
|
assert blocked["diagnostics"]["fields"] == ["file_name", "table"]
|
|
|
|
|
|
def test_normal_agent_request_rejects_nested_technical_coordinates() -> None:
|
|
blocked = mcp.normal_agent_technical_field_guardrail(
|
|
"metadata.form.decode",
|
|
{"base_id": "upo_test", "selector": {"table": "ConfigCASSave"}},
|
|
)
|
|
assert blocked is not None
|
|
assert blocked["diagnostics"]["fields"] == ["table"]
|
|
|
|
|
|
def test_diagnostic_request_may_keep_technical_coordinates(monkeypatch) -> None:
|
|
monkeypatch.setenv("ONEC_MCP_ALLOW_DIAGNOSTIC", "true")
|
|
assert mcp.normal_agent_technical_field_guardrail(
|
|
"metadata.form.decode",
|
|
{"base_id": "upo_test", "table": "ConfigCASSave", "diagnostic": True},
|
|
) is None
|
|
|
|
|
|
def test_form_methods_receive_effective_working_state() -> None:
|
|
payload = mcp.apply_freshness_request_policy(
|
|
{"base_id": "upo_test", "ref": "ОбщаяФорма.Тест"},
|
|
"metadata.form.decode",
|
|
)
|
|
assert payload["configuration_view"] == "effective_working"
|
|
assert payload["source_state"] == "working"
|
|
assert payload["state"] == "working"
|
|
|
|
|
|
def test_runtime_form_inspection_is_explicitly_unsupported() -> None:
|
|
result = mcp.runtime_form_inspection_unsupported(
|
|
"runtime.form.elements.inspect",
|
|
{"base_id": "upo_test"},
|
|
)
|
|
assert result is not None
|
|
assert result["error"] == "runtime_inspection_unsupported"
|