One suggested way to model entity identities in a domain model is to create value objects instead of using primitive types (f.e. in C#):
public class CustomerId
{
public long Id { get; set; }
}
In my opinion this classes should be used throughout the whole application and not only in the domain model. Together with commands and events they can define a service contract for a bounded context. Now in an message/event driven architecture with multiple bounded contexts and each having a separate service contract it is easy to run into circle dependencies.
In the communication between bounded contexts you will have adapters and translators and usually most properties will be crunched into local values. But how to deal with identities of aggregate roots living in other bounded contexts? One solution to this problem is to create local context sibling classes for identity classes of foreign (remote) entities. But this violates somehow the DRY principle. An other approach could be to place the contracts for all bounded contexts in one assembly. I've seen this in many CQRS examples and in my opinion this is code smell. As a last solutions one can decompose the identity classes back to primitive types in all contracts (events and commands) and let each bounded context compose back his local identity classes (if needed) in the domain model. But this could lead to wrong identity compositions on compound identities (f.e. UserId+TenantId).
How do you deal in your projects with identity sharing across bounded context boundaries?