The single entry point for turning an object URI into a path LayoutOperation.Open can take.
Most navigation knows its own destination — a message opened from a mailbox can spell the mailbox
path itself — but generic surfaces (a card, a search result, an agent following a reference) hold an
object and no idea where it lives in the tree. This fans out to every contributed
AppCapabilities.NavigationTargetResolver, so the answer comes from whichever plugin owns the
object's home, and returns targets in resolver position order: one that knows the object's real
location precedes the generic database-path answer, which declares Position.last. Callers wanting
one path take the first target.
Deliberately separate from LayoutOperation.Open: Open's contract is paths in, planks out,
and it is handled by a plugin with no client dependency. Resolution needs a database, so it lives
here and is handled by the plugin that owns the client.
The single entry point for turning an object URI into a path LayoutOperation.Open can take.
Most navigation knows its own destination — a message opened from a mailbox can spell the mailbox path itself — but generic surfaces (a card, a search result, an agent following a reference) hold an object and no idea where it lives in the tree. This fans out to every contributed
AppCapabilities.NavigationTargetResolver, so the answer comes from whichever plugin owns the object's home, and returns targets in resolverpositionorder: one that knows the object's real location precedes the generic database-path answer, which declaresPosition.last. Callers wanting one path take the first target.Deliberately separate from LayoutOperation.Open: Open's contract is paths in, planks out, and it is handled by a plugin with no client dependency. Resolution needs a database, so it lives here and is handled by the plugin that owns the client.