LevelUp.Health.IdentityGraph
0.2.0-rc.1
See the version list below for details.
dotnet add package LevelUp.Health.IdentityGraph --version 0.2.0-rc.1
NuGet\Install-Package LevelUp.Health.IdentityGraph -Version 0.2.0-rc.1
<PackageReference Include="LevelUp.Health.IdentityGraph" Version="0.2.0-rc.1" />
<PackageVersion Include="LevelUp.Health.IdentityGraph" Version="0.2.0-rc.1" />
<PackageReference Include="LevelUp.Health.IdentityGraph" />
paket add LevelUp.Health.IdentityGraph --version 0.2.0-rc.1
#r "nuget: LevelUp.Health.IdentityGraph, 0.2.0-rc.1"
#:package LevelUp.Health.IdentityGraph@0.2.0-rc.1
#addin nuget:?package=LevelUp.Health.IdentityGraph&version=0.2.0-rc.1&prerelease
#tool nuget:?package=LevelUp.Health.IdentityGraph&version=0.2.0-rc.1&prerelease
LevelUp.Health.IdentityGraph
The .NET twin of the cross-tier identity-graph contract for the LevelUp.Health backend
(the asclepius P2 plane, A3 / DR-3). Schema-first lift of Ares' shared/identity contract, paired
with the TS adapter @lvlup-sw/health-identity off the same single-source identity-graph.yaml.
The package ships three pieces off the single-source asclepius/identity/identity-graph.yaml:
IdentityGraph.gen.cs(committed C# adapter, Task 002). Emitted byidentity/scripts/generate.tsand committed underasclepius/identity/generated/; compile-linked into this project (not copied) so the YAML stays the single source and the CI golden check (Task 012) compares the committed file against a fresh emit. A disjoint scalar surface from the TS adapter:IdentityGraphColumns,IdentityGraphInvariants,IdentityMatchPolicy(namespaceLevelUp.Health.IdentityGraph.Generated). It deliberately does not emitrequiredRolesFor.RoleIdentityRequirements(hand-written, Task 004). The C# counterpart of TSrequiredRolesFor, lifted domain-free: the clinicalPersonLinkTargetcoupling is dropped to plain FHIR resource-type strings. Mirrors the YAMLroles:table —practitionerrequires[Patient, Practitioner]; every other role falls back to the wildcard[Patient].IdentityPersonLinkResolver(lifted, Task 004). The realIIdentityPersonLinkResolverimplementation (lifted from Ares'Aegis.Infrastructure.IdentityPersonLinkResolver), backed byIFhirContext<Person>doingPerson?link=Type/idreverse-resolution, fail-safe — no FHIR failure escapesResolveLinkingPersonIdsAsyncas an exception (cancellation excepted, which propagates deliberately, so a cancelled write cannot masquerade as either answer). Fail-safe no longer means fail-quiet. A FHIR failure now yields a failedResultcarryingIdentityPersonLinkErrors.Unknown— UNKNOWN, which is not a statement that nothing links the resource — and the caching decorator answers it by widening the eviction to the identity resource-type tags, not by falling back to the narrower own-id tag alone. A success with an empty list is NO MATCH; a success with many names every linkingPerson.
Fills A2's no-op seam
A2 shipped IIdentityPersonLinkResolver as a deliberate no-op (NoOpIdentityPersonLinkResolver).
This package supplies the real implementation so a consuming app can register it to replace the
no-op. When registered, A2's FhirServiceCachingDecorator evicts the full identity:{personId}
subgraph on identity-resource writes.
This is no longer an additive delivery. Earlier revisions of this package shipped without
modifying any A2 package; health-v0.2.0-rc.1 ends that. The port itself is retyped in
LevelUp.Health.Fhir — ResolveLinkingPersonIdAsync returning Task<string?> became
ResolveLinkingPersonIdsAsync returning Task<Result<IReadOnlyList<string>>> — so
LevelUp.Health.Fhir changes with this package rather than staying untouched.
Version floor: take LevelUp.Health.Fhir and LevelUp.Health.IdentityGraph at >= 0.2.0-rc.1,
together. The interface lives in Fhir and the implementation lives here, so bumping one and not
the other leaves an implementation that no longer satisfies the interface it claims — with no
compile error, because each assembly was built against a version where the two agreed. It fails
at run time, when the container first constructs the resolver — a TypeLoadException where the
implementation no longer satisfies the interface, or a MissingMethodException where a caller
reaches for a member that moved. FhirServiceCachingDecorator<T> takes the resolver by
constructor, so that is the first request resolving a decorated IFhirService<T>, read or write.
LevelUp.Health.Abstractions moves with them, since the port's Result<T> is declared there.
Register it with the supplied extension, which uses Replace so the swap is order-independent
(works whether called before or after A2's AddFhirInfrastructure, whose no-op TryAdd would
otherwise win):
services.AddFhirInfrastructure(configuration);
services.AddFhirResource<Hl7.Fhir.Model.Person>(); // the IFhirContext<Person> the resolver needs
services.AddIdentityPersonLinkResolver(); // swaps the no-op for the real resolver
Cross-language golden-equal (DR-9)
A characterization test (in the .NET lane) compares the C# consts against the committed TS
adapter (identity-graph.gen.ts, read as a text fixture — no Node needed) on the genuinely
shared scalar surface only: the matchPolicy values and the link columns. It does not assert
agreement on requiredRolesFor (TS-only) or IdentityGraphColumns/Invariants (C#-only).
Build & pack
Inherits the repo-root props: net10.0, MinVer-versioned, SourceLink, Lvlup.Build
warnings-as-errors. Packs cleanly (.nupkg + this README + .snupkg) via the existing keyless
NuGet path (matches A2).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Hl7.Fhir.R4 (>= 6.0.1)
- LevelUp.Health.Fhir (>= 0.2.0-rc.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.3.0-preview.1 | 90 | 8/14/2026 |
| 0.2.0-rc.1 | 2,217 | 8/20/2026 |
| 0.2.0-preview.3 | 83 | 8/18/2026 |
| 0.2.0-preview.2 | 87 | 8/14/2026 |
| 0.2.0-preview.1 | 79 | 8/14/2026 |
| 0.1.0 | 1,223 | 7/17/2026 |
| 0.1.0-rc.1 | 146 | 7/15/2026 |
| 0.1.0-preview.2 | 87 | 7/10/2026 |
| 0.1.0-preview.1 | 189 | 6/26/2026 |