I'm a bit confused with regards to the repository
Not your fault.
It may help to review chapter six of the blue book. Evans writes
The REPOSITORY retrieves the requested object, encapsulating the machinery of database queries and metadata mapping.
In other words, the REPOSITORY api is expressed in the domain specific language, and the domain agnostic concerns of "how do I get this data to/from the database" are enclosed within the implementation.
From this, you can infer that the consumer of the repository API should be speaking in domain specific values, not domain agnostic primitives.
This is consistent with a theme that Evans comes back to repeatedly; that you want your developers to be spending most of their time in the domain specific language, not manipulating primitive data types.
If it should be queried using a ValueObject (i.e. Category) who should convert the list of strings from the API request into the list of categories?
So the capability for this conversion will normally be provided by the domain model, in the form of value object constructors, factories, message builders, and so on. These tools will normally be invoked by the application code, before everything moves into the domain specific view.
That said... there's been a sort of push back against that approach. It's really kind of weird to start from a string, and now we have to convert it into a MumbleId, that gets passed to a repository that will convert it back into a string for use as a query parameter, and then some document/recordset/bytes are returned, and we reconstitute that into a domain model, that we then turn around and convert into a json document that we send back over the wire as bytes.
CQRS
is, in part, an answer to the question: can't we just bypass the entire model and copy the bytes that we need? Yes, sometimes that makes a lot of sense.
findByCategoriesIn()
lists every product from every given category or only the products that are in each and every given category. Consider:findAllFrom()
findInEach()