You might want to check your perspective about who’s doing what vis-à-vis validation. Is it the DB, where you know you’re working with the DB? Or is it a service (that happens to be backed and controlled by DB operations). On my project every aggregate root has a list of groups that can read it and a list of modifiers. When the code looks for a specific root or a list of roots the user can see, all of the details are hidden behind a service that takes the user id and the extra parts of look up context like where the tile starts with “blah”. The code doesn’t care that the DB performs an exists check to see if the user’s groups exist in the readers’ groups. It merely expects a list with or without content based upon what ever the service, which is defined by contract only, provides.
This applies all down the layers. Uniformity of validation is the key. Put as much of your validation in domain as possible. Return constraints with your api. I’mIn the end don’t think of constraints coming from X library or Z storage, but from the service.