"""Section 16 — MCP Mist Tools: 7-layer test suite.
Covers the mist MCP executors:
Write tools (write_tools/mists.py):
execute_create_mist, execute_update_mist, execute_fork_mist, execute_delete_mist
Read tools (services/musehub_mcp_executor.py):
execute_read_mist, execute_list_mists, execute_read_mist_embed
Resource handlers (mcp/resources.py):
_read_mist, _read_owner_mists (via musehub://mists/... URIs)
Seven layers:
Layer 1 Unit:
- muse_mist_* tool names appear in correct catalogue sets
- _mist_data serialises MistResponse to correct dict keys
- execute_create_mist: empty actor → forbidden
- execute_create_mist: empty filename → missing_args
- execute_create_mist: empty content → missing_args
- execute_update_mist: empty actor → forbidden
- execute_fork_mist: empty actor → forbidden
- execute_delete_mist: empty actor → forbidden
Layer 2 Integration:
- execute_create_mist: happy path returns mist_id, artifact_type, content
- execute_create_mist: duplicate content → already_exists
- execute_update_mist: title change persisted
- execute_update_mist: non-owner → not_found
- execute_update_mist: visibility change to secret
- execute_delete_mist: happy path returns deleted=True
- execute_delete_mist: non-owner → not_found
- execute_delete_mist: unknown mist_id → not_found
- execute_fork_mist: happy path returns new mist_id and fork_parent_id
- execute_fork_mist: unknown source → not_found
- execute_read_mist: public mist readable by anon
- execute_read_mist: secret mist readable by owner
- execute_read_mist: secret mist blocked for non-owner
- execute_read_mist: unknown → not_found
- execute_list_mists: explore mode returns public mists
- execute_list_mists: owner mode returns owner's mists
- execute_list_mists: secret excluded for anon, included for owner
- execute_read_mist_embed: returns iframe, javascript, badge strings
- execute_read_mist_embed: secret mist → forbidden
- execute_read_mist_embed: unknown mist → not_found
Layer 3 E2E (HTTP tools/call):
- Anonymous muse_mist_create → 401
- Anonymous muse_mist_update → 401
- Anonymous muse_mist_fork → 401
- Anonymous muse_mist_delete → 401
- Authenticated muse_mist_create → isError=False, mist_id present
- Authenticated muse_mist_list (read tool) → isError=False, mists list
Layer 4 Stress:
- 10 sequential creates under 1000 ms
Layer 5 Data Integrity:
- Created mist retrievable via execute_read_mist
- Created mist appears in execute_list_mists(owner=...)
- Updated title persisted after execute_update_mist
- Deleted mist not found via execute_read_mist
- Fork parent_id correct + source fork_count incremented
Layer 6 Security:
- muse_mist_create/update/fork/delete in MUSEHUB_WRITE_TOOL_NAMES
- muse_mist_read/list/embed in read set (not in MUSEHUB_WRITE_TOOL_NAMES)
- Secret mist inaccessible via read executor to non-owner
- Secret mist excluded from explore listing
- Content returned as-is (no XSS transformation)
Layer 7 Performance:
- 10 sequential creates under 1000 ms
"""
from __future__ import annotations
import json
import secrets
import time
from datetime import datetime, timezone, timedelta
import pytest
import pytest_asyncio
from httpx import AsyncClient, ASGITransport
from sqlalchemy.ext.asyncio import AsyncSession
from musehub.core.genesis import compute_identity_id, compute_repo_id
from musehub.db.musehub_repo_models import MusehubRepo
from musehub.main import app
from musehub.mcp.tools.musehub import MUSEHUB_WRITE_TOOL_NAMES, MUSEHUB_TOOL_NAMES
from musehub.types.json_types import JSONObject, StrDict
from musehub.mcp.write_tools.mists import (
_mist_data,
execute_create_mist,
execute_delete_mist,
execute_fork_mist,
execute_update_mist,
)
from musehub.services.musehub_mcp_executor import (
execute_list_mists,
execute_list_mist_forks,
execute_read_mist,
execute_read_mist_embed,
execute_read_mist_raw,
)
from musehub.mcp.resources import read_resource
# ── Fixtures ──────────────────────────────────────────────────────────────────
@pytest.fixture
def anyio_backend() -> str:
return "asyncio"
@pytest_asyncio.fixture
async def http_client(db_session: AsyncSession) -> AsyncClient:
async with AsyncClient(
transport=ASGITransport(app=app),
base_url="http://localhost",
) as c:
yield c
# ── Helpers ───────────────────────────────────────────────────────────────────
_OWNER = "alice"
_PY_CONTENT = "def validate(x: str) -> bool:\n return bool(x)\n"
_PY_FILENAME = "validate.py"
def _uid() -> str:
return secrets.token_hex(16)
def _unique_content() -> str:
"""Return content unique enough that its mist_id won't collide."""
return f"{_PY_CONTENT}# salt={secrets.token_hex(16)}"
def _tools_call(name: str, arguments: JSONObject) -> JSONObject:
return {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {"name": name, "arguments": arguments},
}
def _unwrap_tool_text(text: str) -> str:
text = text.strip()
if text.startswith(""):
text = text[len(""):].strip()
if text.endswith(""):
text = text[: -len("")].strip()
return text
async def _create(
content: str | None = None,
filename: str = _PY_FILENAME,
visibility: str = "public",
actor: str = _OWNER,
title: str = "",
) -> "MusehubToolResult": # type: ignore[name-defined]
return await execute_create_mist(
filename=filename,
content=content or _unique_content(),
actor=actor,
title=title,
visibility=visibility,
)
# ── Layer 1 — Unit ────────────────────────────────────────────────────────────
class TestUnitToolCatalogue:
def test_mist_write_tools_in_write_set(self) -> None:
expected = {"muse_mist_create", "muse_mist_update", "muse_mist_fork", "muse_mist_delete"}
missing = expected - MUSEHUB_WRITE_TOOL_NAMES
assert not missing, f"Missing from write set: {missing}"
def test_mist_read_tools_NOT_in_write_set(self) -> None:
read_tools = {"muse_mist_read", "muse_mist_list", "muse_mist_embed"}
in_write = read_tools & MUSEHUB_WRITE_TOOL_NAMES
assert not in_write, f"Read tools incorrectly in write set: {in_write}"
def test_all_mist_tools_in_tool_names(self) -> None:
expected = {
"muse_mist_create", "muse_mist_update", "muse_mist_fork",
"muse_mist_delete", "muse_mist_read", "muse_mist_list", "muse_mist_embed",
}
missing = expected - MUSEHUB_TOOL_NAMES
assert not missing, f"Missing from MUSEHUB_TOOL_NAMES: {missing}"
class TestUnitMistDataHelper:
async def test_mist_data_keys(self, db_session: AsyncSession) -> None:
result = await _create()
assert result.ok is True
data = result.data
for key in ("mist_id", "owner", "artifact_type", "language", "filename",
"content", "size_bytes", "version", "visibility", "tags",
"symbol_anchors", "created_at", "updated_at"):
assert key in data, f"Missing key: {key}"
class TestUnitInputValidation:
async def test_create_empty_actor_returns_forbidden(self) -> None:
result = await execute_create_mist(filename="f.py", content="x", actor="")
assert result.ok is False
assert result.error_code == "forbidden"
async def test_create_empty_filename_returns_missing_args(self) -> None:
result = await execute_create_mist(filename="", content="x", actor=_OWNER)
assert result.ok is False
assert result.error_code == "missing_args"
async def test_create_empty_content_returns_missing_args(self) -> None:
result = await execute_create_mist(filename="f.py", content="", actor=_OWNER)
assert result.ok is False
assert result.error_code == "missing_args"
async def test_update_empty_actor_returns_forbidden(self) -> None:
result = await execute_update_mist(mist_id="aB3xKq9dPwNm", actor="")
assert result.ok is False
assert result.error_code == "forbidden"
async def test_fork_empty_actor_returns_forbidden(self) -> None:
result = await execute_fork_mist(mist_id="aB3xKq9dPwNm", actor="")
assert result.ok is False
assert result.error_code == "forbidden"
async def test_delete_empty_actor_returns_forbidden(self) -> None:
result = await execute_delete_mist(mist_id="aB3xKq9dPwNm", actor="")
assert result.ok is False
assert result.error_code == "forbidden"
# ── Layer 2 — Integration ─────────────────────────────────────────────────────
class TestIntegrationCreate:
async def test_create_happy_path(self, db_session: AsyncSession) -> None:
result = await _create()
assert result.ok is True
data = result.data
assert len(data["mist_id"]) == 12
assert data["artifact_type"] == "code"
assert data["language"] == "python"
assert data["owner"] == _OWNER
assert data["visibility"] == "public"
assert data["version"] == 1
async def test_create_duplicate_content_returns_already_exists(
self, db_session: AsyncSession
) -> None:
content = _unique_content()
r1 = await execute_create_mist(filename=_PY_FILENAME, content=content, actor=_OWNER)
assert r1.ok is True
r2 = await execute_create_mist(filename=_PY_FILENAME, content=content, actor=_OWNER)
assert r2.ok is False
assert r2.error_code == "already_exists"
async def test_create_with_title_and_tags(self, db_session: AsyncSession) -> None:
result = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
title="My helper",
tags=["utils", "security"],
)
assert result.ok is True
assert result.data["title"] == "My helper"
assert result.data["tags"] == ["utils", "security"]
async def test_create_secret_mist(self, db_session: AsyncSession) -> None:
result = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
visibility="secret",
)
assert result.ok is True
assert result.data["visibility"] == "secret"
class TestIntegrationUpdate:
async def test_update_title(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_update_mist(mist_id=mid, actor=_OWNER, title="New title")
assert result.ok is True
assert result.data["title"] == "New title"
async def test_update_visibility_to_secret(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_update_mist(mist_id=mid, actor=_OWNER, visibility="secret")
assert result.ok is True
assert result.data["visibility"] == "secret"
async def test_update_content_increments_version(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_update_mist(
mist_id=mid, actor=_OWNER, content="# new content\n"
)
assert result.ok is True
assert result.data["version"] == 2
async def test_update_non_owner_returns_not_found(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_update_mist(mist_id=mid, actor="bob", title="Stolen")
assert result.ok is False
assert result.error_code == "not_found"
async def test_update_unknown_mist_returns_not_found(self, db_session: AsyncSession) -> None:
result = await execute_update_mist(mist_id="unknown12345", actor=_OWNER, title="X")
assert result.ok is False
assert result.error_code == "not_found"
class TestIntegrationDelete:
async def test_delete_happy_path(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_delete_mist(mist_id=mid, actor=_OWNER)
assert result.ok is True
assert result.data["deleted"] is True
assert result.data["mist_id"] == mid
async def test_delete_non_owner_returns_not_found(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_delete_mist(mist_id=mid, actor="bob")
assert result.ok is False
assert result.error_code == "not_found"
async def test_delete_unknown_returns_not_found(self, db_session: AsyncSession) -> None:
result = await execute_delete_mist(mist_id="unknown12345", actor=_OWNER)
assert result.ok is False
assert result.error_code == "not_found"
class TestIntegrationFork:
async def test_fork_happy_path(self, db_session: AsyncSession) -> None:
source = await _create(actor=_OWNER)
mid = source.data["mist_id"]
result = await execute_fork_mist(mist_id=mid, actor="bob")
assert result.ok is True
assert result.data["fork_parent_id"] == mid
assert result.data["owner"] == "bob"
assert result.data["mist_id"] != mid
async def test_fork_unknown_returns_not_found(self, db_session: AsyncSession) -> None:
result = await execute_fork_mist(mist_id="unknown12345", actor="bob")
assert result.ok is False
assert result.error_code == "not_found"
class TestIntegrationReadMist:
async def test_read_public_mist_anon(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_read_mist(mid, actor="")
assert result.ok is True
assert result.data["mist_id"] == mid
assert "content" in result.data
async def test_read_secret_mist_as_owner(self, db_session: AsyncSession) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
result = await execute_read_mist(mid, actor=_OWNER)
assert result.ok is True
async def test_read_secret_mist_as_non_owner_returns_forbidden(
self, db_session: AsyncSession
) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
result = await execute_read_mist(mid, actor="bob")
assert result.ok is False
assert result.error_code == "forbidden"
async def test_read_unknown_returns_not_found(self, db_session: AsyncSession) -> None:
result = await execute_read_mist("unknown12345")
assert result.ok is False
assert result.error_code == "not_found"
class TestIntegrationListMists:
async def test_explore_returns_public(self, db_session: AsyncSession) -> None:
created = await _create(actor=_OWNER)
mid = created.data["mist_id"]
result = await execute_list_mists(owner=None)
assert result.ok is True
ids = {m["mist_id"] for m in result.data["mists"]}
assert mid in ids
async def test_explore_excludes_secret(self, db_session: AsyncSession) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
result = await execute_list_mists(owner=None)
assert result.ok is True
ids = {m["mist_id"] for m in result.data["mists"]}
assert mid not in ids
async def test_owner_mode_includes_public(self, db_session: AsyncSession) -> None:
created = await _create(actor=_OWNER)
mid = created.data["mist_id"]
result = await execute_list_mists(owner=_OWNER)
assert result.ok is True
ids = {m["mist_id"] for m in result.data["mists"]}
assert mid in ids
async def test_owner_mode_excludes_secret_for_anon(self, db_session: AsyncSession) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
result = await execute_list_mists(owner=_OWNER, include_secret=True, actor="bob")
assert result.ok is True
ids = {m["mist_id"] for m in result.data["mists"]}
assert mid not in ids
async def test_owner_mode_includes_secret_for_owner(self, db_session: AsyncSession) -> None:
created = await _create(visibility="secret", actor=_OWNER)
mid = created.data["mist_id"]
result = await execute_list_mists(owner=_OWNER, include_secret=True, actor=_OWNER)
assert result.ok is True
ids = {m["mist_id"] for m in result.data["mists"]}
assert mid in ids
class TestIntegrationEmbed:
async def test_embed_public_mist(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
result = await execute_read_mist_embed(mid, owner=_OWNER)
assert result.ok is True
data = result.data
assert "iframe" in data
assert "javascript" in data
assert "badge" in data
assert mid in data["iframe"]
async def test_embed_secret_mist_returns_forbidden(self, db_session: AsyncSession) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
result = await execute_read_mist_embed(mid, owner=_OWNER)
assert result.ok is False
assert result.error_code == "forbidden"
async def test_embed_unknown_mist_returns_not_found(self, db_session: AsyncSession) -> None:
result = await execute_read_mist_embed("unknown12345", owner="nobody")
assert result.ok is False
assert result.error_code == "not_found"
class TestIntegrationResource:
async def test_read_resource_single_mist(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
data = await read_resource(f"musehub://mists/{_OWNER}/{mid}")
assert "error" not in data
assert data["mist_id"] == mid
assert "content" in data
async def test_read_resource_owner_mists(self, db_session: AsyncSession) -> None:
created = await _create(actor=_OWNER)
mid = created.data["mist_id"]
data = await read_resource(f"musehub://mists/{_OWNER}")
assert "error" not in data
ids = {m["mist_id"] for m in data["mists"]}
assert mid in ids
async def test_read_resource_unknown_mist(self, db_session: AsyncSession) -> None:
data = await read_resource("musehub://mists/nobody/unknown12345")
assert "error" in data
async def test_read_resource_secret_mist_blocked_for_anon(
self, db_session: AsyncSession
) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
data = await read_resource(f"musehub://mists/{_OWNER}/{mid}", user_id=None)
assert "error" in data
# ── Layer 3 — End-to-End ──────────────────────────────────────────────────────
class TestE2EAuthGate:
"""Write tool calls without auth must return 401."""
async def test_create_mist_no_auth(self, http_client: AsyncClient) -> None:
resp = await http_client.post(
"/mcp",
json=_tools_call("muse_mist_create", {"filename": "f.py", "content": "x"}),
headers={"Content-Type": "application/json"},
)
assert resp.status_code == 401
async def test_update_mist_no_auth(self, http_client: AsyncClient) -> None:
resp = await http_client.post(
"/mcp",
json=_tools_call("muse_mist_update", {"mist_id": "aB3xKq9dPwNm"}),
headers={"Content-Type": "application/json"},
)
assert resp.status_code == 401
async def test_fork_mist_no_auth(self, http_client: AsyncClient) -> None:
resp = await http_client.post(
"/mcp",
json=_tools_call("muse_mist_fork", {"mist_id": "aB3xKq9dPwNm"}),
headers={"Content-Type": "application/json"},
)
assert resp.status_code == 401
async def test_delete_mist_no_auth(self, http_client: AsyncClient) -> None:
resp = await http_client.post(
"/mcp",
json=_tools_call("muse_mist_delete", {"mist_id": "aB3xKq9dPwNm"}),
headers={"Content-Type": "application/json"},
)
assert resp.status_code == 401
async def test_create_mist_with_auth(
self, http_client: AsyncClient, db_session: AsyncSession, auth_headers: StrDict
) -> None:
content = _unique_content()
resp = await http_client.post(
"/mcp",
json=_tools_call("muse_mist_create", {
"filename": _PY_FILENAME,
"content": content,
"title": "E2E mist",
}),
headers=auth_headers,
)
assert resp.status_code == 200
result = resp.json()["result"]
assert result["isError"] is False
payload = json.loads(_unwrap_tool_text(result["content"][0]["text"]))
assert "mist_id" in payload
assert payload["title"] == "E2E mist"
async def test_list_mists_read_tool_no_auth(self, http_client: AsyncClient) -> None:
"""muse_mist_list is a read tool — accessible without auth."""
resp = await http_client.post(
"/mcp",
json=_tools_call("muse_mist_list", {}),
headers={"Content-Type": "application/json"},
)
# Read tools don't require auth at the HTTP layer
assert resp.status_code in (200, 401)
if resp.status_code == 200:
result = resp.json()["result"]
assert result["isError"] is False
# ── Layer 4 — Stress ──────────────────────────────────────────────────────────
class TestStressMistTools:
async def test_10_sequential_creates(self, db_session: AsyncSession) -> None:
start = time.monotonic()
ids: list[str] = []
for _ in range(10):
result = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert result.ok is True
ids.append(result.data["mist_id"])
elapsed = time.monotonic() - start
assert elapsed < 1.0, f"10 creates took {elapsed:.2f}s (> 1s)"
assert len(set(ids)) == 10, "All mist IDs must be unique"
# ── Layer 5 — Data Integrity ──────────────────────────────────────────────────
class TestDataIntegrity:
async def test_created_mist_retrievable(self, db_session: AsyncSession) -> None:
created = await _create(title="Persistent")
mid = created.data["mist_id"]
read = await execute_read_mist(mid, actor=_OWNER)
assert read.ok is True
assert read.data["mist_id"] == mid
assert read.data["title"] == "Persistent"
async def test_created_mist_in_owner_list(self, db_session: AsyncSession) -> None:
created = await _create(actor=_OWNER)
mid = created.data["mist_id"]
result = await execute_list_mists(owner=_OWNER)
assert result.ok is True
ids = {m["mist_id"] for m in result.data["mists"]}
assert mid in ids
async def test_update_title_persisted(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
await execute_update_mist(mist_id=mid, actor=_OWNER, title="Persisted title")
read = await execute_read_mist(mid)
assert read.ok is True
assert read.data["title"] == "Persisted title"
async def test_deleted_mist_not_found(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
del_result = await execute_delete_mist(mist_id=mid, actor=_OWNER)
assert del_result.ok is True
read = await execute_read_mist(mid)
assert read.ok is False
assert read.error_code == "not_found"
async def test_fork_parent_id_and_source_fork_count(self, db_session: AsyncSession) -> None:
source = await _create(actor=_OWNER)
mid = source.data["mist_id"]
fork = await execute_fork_mist(mist_id=mid, actor="bob")
assert fork.ok is True
assert fork.data["fork_parent_id"] == mid
# Source fork_count incremented — verify via read
read = await execute_read_mist(mid, actor=_OWNER)
assert read.ok is True
assert read.data["fork_count"] >= 1
async def test_view_count_increments_on_read(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
r1 = await execute_read_mist(mid)
r2 = await execute_read_mist(mid)
assert r2.data["view_count"] > r1.data["view_count"]
async def test_embed_count_increments_on_embed(self, db_session: AsyncSession) -> None:
created = await _create()
mid = created.data["mist_id"]
r1 = await execute_read_mist(mid)
await execute_read_mist_embed(mid, owner=_OWNER)
r2 = await execute_read_mist(mid)
assert r2.data["embed_count"] > r1.data["embed_count"]
# ── Layer 6 — Security ────────────────────────────────────────────────────────
class TestSecurity:
def test_write_tools_in_auth_gate_set(self) -> None:
write_tools = {"muse_mist_create", "muse_mist_update", "muse_mist_fork", "muse_mist_delete"}
missing = write_tools - MUSEHUB_WRITE_TOOL_NAMES
assert not missing, f"Write tools missing from auth gate: {missing}"
def test_read_tools_not_in_write_set(self) -> None:
read_tools = {"muse_mist_read", "muse_mist_list", "muse_mist_embed"}
in_write = read_tools & MUSEHUB_WRITE_TOOL_NAMES
assert not in_write, f"Read tools in write auth gate (shouldn't be): {in_write}"
async def test_secret_mist_not_in_explore(self, db_session: AsyncSession) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
result = await execute_list_mists(owner=None, actor="")
ids = {m["mist_id"] for m in result.data["mists"]}
assert mid not in ids, "Secret mist must not appear in explore feed"
async def test_secret_mist_blocked_for_non_owner_read(self, db_session: AsyncSession) -> None:
created = await _create(visibility="secret")
mid = created.data["mist_id"]
result = await execute_read_mist(mid, actor="bob")
assert result.ok is False
assert result.error_code == "forbidden"
async def test_content_returned_verbatim_no_xss_transform(
self, db_session: AsyncSession
) -> None:
"""Content is returned verbatim — XSS prevention is a renderer concern."""
xss_payload = ''
created = await execute_create_mist(
filename="test.html",
content=xss_payload,
actor=_OWNER,
)
assert created.ok is True
mid = created.data["mist_id"]
read = await execute_read_mist(mid, actor=_OWNER)
assert read.ok is True
assert read.data["content"] == xss_payload
async def test_agent_id_stored_verbatim(self, db_session: AsyncSession) -> None:
"""agent_id is stored as opaque string — no injection risk in storage."""
agent = "agentception-worker-42; DROP TABLE mists;--"
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
agent_id=agent,
)
assert created.ok is True
assert created.data["agent_id"] == agent
# ── Layer 7 — Performance ─────────────────────────────────────────────────────
class TestPerformance:
async def test_10_creates_under_500ms(self, db_session: AsyncSession) -> None:
start = time.monotonic()
for _ in range(10):
result = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert result.ok is True
elapsed = time.monotonic() - start
assert elapsed < 0.5, f"10 creates took {elapsed:.2f}s (> 500ms)"
async def test_list_100_mists_under_200ms(self, db_session: AsyncSession) -> None: # noqa: E501
from muse.plugins.mist.plugin import compute_mist_id
base_time = datetime.now(tz=timezone.utc)
unique_type = f"perf_{secrets.token_hex(4)}"
owner_id = compute_identity_id(_OWNER.encode())
for i in range(20):
content = f"perf_{i}_{secrets.token_hex(16)}"
mid = compute_mist_id(content.encode())
from musehub.db.musehub_repo_models import MusehubMist
slug = secrets.token_hex(6)
created_at = base_time
repo_id = compute_repo_id(owner_id, slug, "code", created_at.isoformat())
repo = MusehubRepo(
repo_id=repo_id,
name=slug,
owner=_OWNER,
slug=slug,
visibility="public",
owner_user_id=owner_id,
created_at=created_at,
updated_at=created_at,
)
db_session.add(repo)
await db_session.flush()
await db_session.refresh(repo)
row = MusehubMist(
mist_id=mid,
repo_id=str(repo.repo_id),
owner=_OWNER,
filename="p.py",
content=content,
artifact_type=unique_type,
language="python",
visibility="public",
tags=[],
symbol_anchors=[],
created_at=base_time + timedelta(seconds=i),
updated_at=base_time + timedelta(seconds=i),
)
db_session.add(row)
await db_session.commit()
start = time.monotonic()
result = await execute_list_mists(
artifact_type=unique_type,
limit=20,
)
elapsed = time.monotonic() - start
assert result.ok is True
assert elapsed < 0.2, f"list 20 mists took {elapsed:.2f}s (> 200ms)"
# ── execute_list_mist_forks tests ─────────────────────────────────────────────
@pytest.mark.anyio
class TestListMistForks:
"""Tests for execute_list_mist_forks — all 8 tiers.
Covers: empty mist_id guard, not_found, forbidden (secret parent,
non-owner actor), happy path with zero forks, happy path with forks,
limit clamping, and performance (<200ms for 10 forks).
"""
async def test_empty_mist_id_returns_missing_args(
self, db_session: AsyncSession
) -> None:
"""Empty mist_id returns missing_args immediately without a DB hit."""
result = await execute_list_mist_forks("")
assert result.ok is False
assert result.error_code == "missing_args"
async def test_unknown_mist_returns_not_found(
self, db_session: AsyncSession
) -> None:
"""Non-existent parent mist returns not_found."""
result = await execute_list_mist_forks("NoSuchMistXX")
assert result.ok is False
assert result.error_code == "not_found"
async def test_secret_parent_anon_returns_forbidden(
self, db_session: AsyncSession
) -> None:
"""Secret parent mist with anonymous actor returns forbidden."""
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
visibility="secret",
)
assert created.ok is True
mist_id = created.data["mist_id"]
result = await execute_list_mist_forks(mist_id, actor="")
assert result.ok is False
assert result.error_code == "forbidden"
async def test_public_parent_no_forks_returns_empty_list(
self, db_session: AsyncSession
) -> None:
"""Public parent with no forks returns empty forks list, total=0."""
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert created.ok is True
mist_id = created.data["mist_id"]
result = await execute_list_mist_forks(mist_id)
assert result.ok is True
assert result.data["mist_id"] == mist_id
assert result.data["total"] == 0
assert result.data["forks"] == []
async def test_forks_appear_after_fork_creation(
self, db_session: AsyncSession
) -> None:
"""After forking a mist, execute_list_mist_forks returns the fork."""
parent = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert parent.ok is True
parent_id = parent.data["mist_id"]
fork = await execute_fork_mist(mist_id=parent_id, actor="otheruser")
assert fork.ok is True
result = await execute_list_mist_forks(parent_id)
assert result.ok is True
assert result.data["total"] == 1
fork_entry = result.data["forks"][0]
assert fork_entry["owner"] == "otheruser"
assert fork_entry["mist_id"] == fork.data["mist_id"]
async def test_limit_clamped_to_100(
self, db_session: AsyncSession
) -> None:
"""Passing limit=200 is silently clamped to 100 (no error)."""
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert created.ok is True
result = await execute_list_mist_forks(
created.data["mist_id"], limit=200
)
assert result.ok is True
async def test_secret_parent_owner_can_list_forks(
self, db_session: AsyncSession
) -> None:
"""Owner of a secret parent can list its forks."""
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
visibility="secret",
)
assert created.ok is True
result = await execute_list_mist_forks(
created.data["mist_id"], actor=_OWNER
)
assert result.ok is True
assert result.data["total"] == 0
async def test_fork_entry_has_required_keys(
self, db_session: AsyncSession
) -> None:
"""Each fork entry contains the required schema keys."""
parent = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert parent.ok is True
await execute_fork_mist(mist_id=parent.data["mist_id"], actor="otheruser")
result = await execute_list_mist_forks(parent.data["mist_id"])
assert result.ok is True
entry = result.data["forks"][0]
for key in ("mist_id", "owner", "filename", "artifact_type",
"fork_depth", "fork_count", "visibility", "tags",
"created_at"):
assert key in entry, f"Missing key '{key}' in fork entry"
async def test_muse_mist_list_forks_in_tool_catalogue(self) -> None:
"""muse_mist_list_forks appears in MUSEHUB_TOOL_NAMES."""
assert "muse_mist_list_forks" in MUSEHUB_TOOL_NAMES
async def test_muse_mist_list_forks_not_in_write_tools(self) -> None:
"""muse_mist_list_forks is a read tool — must not appear in write set."""
assert "muse_mist_list_forks" not in MUSEHUB_WRITE_TOOL_NAMES
async def test_10_forks_listed_under_200ms(
self, db_session: AsyncSession
) -> None:
"""Listing 10 forks completes in under 200ms."""
parent = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert parent.ok is True
parent_id = parent.data["mist_id"]
for i in range(10):
fork = await execute_fork_mist(mist_id=parent_id, actor=f"user{i}")
assert fork.ok is True
start = time.monotonic()
result = await execute_list_mist_forks(parent_id, limit=10)
elapsed = time.monotonic() - start
assert result.ok is True
assert result.data["total"] == 10
assert elapsed < 0.2, f"listing 10 forks took {elapsed:.2f}s (> 200ms)"
# ── execute_read_mist_raw tests ───────────────────────────────────────────────
@pytest.mark.anyio
class TestReadMistRaw:
"""Tests for execute_read_mist_raw — all 8 tiers.
Covers: empty mist_id guard, not_found, forbidden (secret mist,
non-owner), happy path content/keys, view counter increment,
performance (<50ms), and tool catalogue membership.
"""
async def test_empty_mist_id_returns_missing_args(
self, db_session: AsyncSession
) -> None:
"""Empty mist_id returns missing_args without a DB hit."""
result = await execute_read_mist_raw("")
assert result.ok is False
assert result.error_code == "missing_args"
async def test_unknown_mist_returns_not_found(
self, db_session: AsyncSession
) -> None:
"""Non-existent mist_id returns not_found."""
result = await execute_read_mist_raw("NoSuchMistXX")
assert result.ok is False
assert result.error_code == "not_found"
async def test_secret_mist_anon_returns_forbidden(
self, db_session: AsyncSession
) -> None:
"""Anonymous actor cannot read a secret mist."""
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
visibility="secret",
)
assert created.ok is True
result = await execute_read_mist_raw(created.data["mist_id"], actor="")
assert result.ok is False
assert result.error_code == "forbidden"
async def test_secret_mist_non_owner_returns_forbidden(
self, db_session: AsyncSession
) -> None:
"""Non-owner actor cannot read a secret mist."""
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
visibility="secret",
)
assert created.ok is True
result = await execute_read_mist_raw(
created.data["mist_id"], actor="intruder"
)
assert result.ok is False
assert result.error_code == "forbidden"
async def test_secret_mist_owner_can_read_raw(
self, db_session: AsyncSession
) -> None:
"""Owner can read a secret mist's raw content."""
content = _unique_content()
created = await execute_create_mist(
filename=_PY_FILENAME,
content=content,
actor=_OWNER,
visibility="secret",
)
assert created.ok is True
result = await execute_read_mist_raw(
created.data["mist_id"], actor=_OWNER
)
assert result.ok is True
assert result.data["content"] == content
async def test_public_mist_readable_by_anon(
self, db_session: AsyncSession
) -> None:
"""Public mist is readable by anonymous caller."""
content = _unique_content()
created = await execute_create_mist(
filename=_PY_FILENAME,
content=content,
actor=_OWNER,
)
assert created.ok is True
result = await execute_read_mist_raw(created.data["mist_id"])
assert result.ok is True
assert result.data["content"] == content
async def test_data_has_required_keys(
self, db_session: AsyncSession
) -> None:
"""Successful result contains all expected data keys."""
created = await execute_create_mist(
filename=_PY_FILENAME,
content=_unique_content(),
actor=_OWNER,
)
assert created.ok is True
result = await execute_read_mist_raw(created.data["mist_id"])
assert result.ok is True
for key in ("mist_id", "filename", "artifact_type",
"language", "size_bytes", "content"):
assert key in result.data, f"Missing key '{key}' in raw result"
async def test_size_bytes_matches_content_length(
self, db_session: AsyncSession
) -> None:
"""size_bytes in the result equals the UTF-8 byte length of content."""
content = _unique_content()
created = await execute_create_mist(
filename=_PY_FILENAME,
content=content,
actor=_OWNER,
)
assert created.ok is True
result = await execute_read_mist_raw(created.data["mist_id"])
assert result.ok is True
assert result.data["size_bytes"] == len(content.encode("utf-8"))
async def test_muse_mist_raw_in_tool_catalogue(self) -> None:
"""muse_mist_raw appears in MUSEHUB_TOOL_NAMES."""
assert "muse_mist_raw" in MUSEHUB_TOOL_NAMES
async def test_muse_mist_raw_not_in_write_tools(self) -> None:
"""muse_mist_raw is a read tool — must not appear in the write set."""
assert "muse_mist_raw" not in MUSEHUB_WRITE_TOOL_NAMES
async def test_raw_under_50ms(self, db_session: AsyncSession) -> None:
"""Raw read of a 1 KiB mist completes in under 50ms."""
content = f"x = 1\n# {'a' * 500}\n"
created = await execute_create_mist(
filename=_PY_FILENAME,
content=content,
actor=_OWNER,
)
assert created.ok is True
start = time.monotonic()
result = await execute_read_mist_raw(created.data["mist_id"])
elapsed = time.monotonic() - start
assert result.ok is True
assert elapsed < 0.05, f"raw read took {elapsed:.3f}s (> 50ms)"