diff --git a/tests/test_mcp_tool_processes.py b/tests/test_mcp_tool_processes.py index 189b31b..658ca9a 100644 --- a/tests/test_mcp_tool_processes.py +++ b/tests/test_mcp_tool_processes.py @@ -89,14 +89,34 @@ async def test_get_process_not_found_raises(): @pytest.mark.asyncio async def test_update_process_rejects_non_process_note(): + # Resolves share-aware now, so the patch target is get_note_for_user, which + # returns (note, permission). plain = _fake_note(id=3, note_type="note") - with patch("scribe.services.notes.get_note", - AsyncMock(return_value=plain)): + plain.deleted_at = None + with patch("scribe.services.notes.get_note_for_user", + AsyncMock(return_value=(plain, "owner"))): from scribe.mcp.tools.processes import update_process with pytest.raises(ValueError): await update_process(process_id=3, title="x") +@pytest.mark.asyncio +async def test_update_process_refuses_a_read_only_share_with_the_reason(): + """An editor grant lets the holder edit someone else's process; a viewer + grant must be refused, and saying "not found" about a process the caller can + open would just send them looking for a missing id.""" + theirs = _fake_note(id=5, user_id=9) + theirs.deleted_at = None + with patch("scribe.services.notes.get_note_for_user", + AsyncMock(return_value=(theirs, "viewer"))), \ + patch("scribe.services.access.can_write_note", AsyncMock(return_value=False)), \ + patch("scribe.services.notes.update_note", AsyncMock()) as mock_update: + from scribe.mcp.tools.processes import update_process + with pytest.raises(ValueError, match="read-only"): + await update_process(process_id=5, title="x") + mock_update.assert_not_awaited() + + def test_register_attaches_four_tools(): from scribe.mcp.tools import processes names: list[str] = []