entity-ref
The one shared contract for cross-service entity linking in the Main X
Index family — agents/share/cross-service-linking.md §3 (the EntityRef
value type) and §9 (the v1 edge-kind registry). Rollout step 1: land
the contracts, no behaviour yet.
A record in another service is named by an opaque URN string
"<entity_type>:<uuid>", e.g. person:0c4f1e2a-…. This crate owns the
parsing/validation and the static metadata; it is pure, panic-free, and
dependency-light (serde + uuid + thiserror). The rollout note below once
framed this as copyable per project until a second non-aggregator
consumer justified a shared dependency — that threshold has since been
crossed several times over; see "Who actually consumes this" below.
use ;
// Parse / display / (de)serialise as the single URN string.
let r: EntityRef = "person:0c4f1e2a-0000-4000-8000-000000000000".parse?;
assert_eq!;
assert_eq!; // entity_type → owning service
assert_eq!;
// The closed v1 edge-kind registry validates endpoint types.
assert!;
assert_eq!;
assert_eq!; // case → person (§10)
Types
| Item | Purpose |
|---|---|
EntityType |
The globally-unique entity discriminator (person, worker, …, courseinstance, care_pathway); as_str, from_token, and the service() map (course + courseinstance → course-service). |
EntityRef |
{entity_type, id: Uuid}; FromStr/Display/serde as the "type:uuid" URN (one indexable TEXT column). |
EdgeKind |
The closed v1 registry (same_identity, works_at, member_of, employed_by, subject_of) with is_symmetric / is_temporal / inverse / sensitivity / permits(from, to). |
Sensitivity |
Medium (affiliation / identity) vs High (case → person, §10). |
Who actually consumes this
As of 2026-08-04, eight crates depend on this one as a real Cargo path
dependency (entity-ref = { path = "../../link/entity-ref-rust-crate" })
— not a copy-per-project, despite the framing above:
link-graph-service-with-loco— the aggregator (the read model); by far the heaviest user, importing acrossauth.rs,consumer.rs,controllers/graph.rs,events.rs,graph.rs,models/edges.rs,models/entity_presence.rs,probe.rs,reconcile.rs, andsuggest/{job,mod}.rs.person-service-with-loco,worker-service-with-loco,case-service-with-loco— the three entity services that originate edges (entity_linkswrite-side +linked/unlinkedevents), as the design doc anticipated.contact-relationship-management-service-with-rust,content-management-system-service-with-rust,patient-flow-service-with-rust,workforce-planning-management-service-with-rust— the four consumer apps, which were not anticipated by the original rollout note. Each usesEntityRef/EntityTypein its ownsrc/validation.rsandsrc/clients.rsto validate and dereference cross-service refs (e.g.person_ref,worker_ref) rather than to originate edges.
Cross-service links are still never a matcher signal — see
cross-service-linking.md §7.