5.4 KiB
Resolution Algorithm
Deterministic resolution pipeline that produces ordered routing directives. Input/output contracts are defined in the OpenAPI spec; persistence shape is in the data model.
Precedence ladder (per rail)
When multiple sources can contribute a directive, apply this order. The first successful source wins unless overridden by tenant/contract config:
- Tenant override — Tenant-specific routing artifact or endpoint override.
- Contract-specific config — Contract or connectivity-group mapping.
- Internal curated directory — Participants/endpoints stored in the directory (admin or connector).
- External authoritative directory — SMP/SML, GTT feed, or other external source (cached).
- Fallback heuristics — Optional, disabled by default (e.g. default route).
Log and expose resolution_trace in the response so callers see which source(s) contributed (e.g. "tenant override", "internal directory", "SMP cache"). See route-directive.md.
Source-driven mappings (e.g. SS7): Data from connectors (GTT, NP/range feeds) is only as good as the ingested sources. Expose confidence and last_verified in directives; tag edges with provenance. No implied authority—see connectors.md.
Pipeline (steps 1–9)
-
Normalize input
Parse and validate all identifiers in the request. Validate formats per type (E.164, PartyId, PC/SSN, etc.). Reject invalid or unsupported types early. -
Expand context
Infer candidate identifier equivalences using the mapping graph (same participant: multiple identifier types pointing to the same participant). Build a set of "equivalent" identifiers for lookup. -
Candidate retrieval
Query the directory store for participants and endpoints matching any of the normalized/expanded identifiers, within the requested tenant and constraints. -
Capability filter
Retain only participants/endpoints whose capabilities match the requested service context (service, action, process, document type) and any constraints in the request. Constraints may includerequiredCapability,messageType(e.g. ISO8583 MTI), andnetworkBrandfor card rails. -
Policy filter
Apply tenant-scoped policies (ABAC). Enforce trust domain, geo, compliance, and allow/deny rules. Remove any candidate that is denied or out of scope. -
Score and rank
Score remaining candidates (see Scoring). Sort by score descending; apply tie-break rules for stable ordering. -
Assemble directives
For each ranked candidate, build aRouteDirective: map endpoint + participant totarget_protocol,target_address,transport_profile, attach security refs (from credentials),service_context,qos,ttl_seconds, andevidence(source, lastVerified, confidenceScore). -
Sign response (optional)
In multi-party setups, optionally sign the response for non-repudiation. Not required for MVP. -
Cache
Store result in positive cache (keyed by normalized request + tenant) with TTL. On cache hit, return cached directives and skip steps 2–7. Negative results (no candidates after filters) may be cached with shorter TTL and invalidation hooks.
Determinism and tie-break
- Invariant: Same inputs + same store state ⇒ same ordered list of directives.
- Tie-break order when scores are equal (aligned with data-model conflict resolution):
- Explicit priority (endpoint/identifier priority from store) — higher first.
- Policy (allow/deny and policy priority).
- Freshness (updated_at / verified_at / valid_from).
- Confidence (edge or evidence confidence score).
- Lexical — stable sort by deterministic key (e.g. participant id + endpoint id).
Implementation must use a fixed ordering (e.g. sort by (score DESC, priority DESC, updated_at DESC, id ASC)).
Scoring
Factors that contribute to the score (combined by weighted sum or ordered rules; exact weights are implementation/config):
| Factor | Description |
|---|---|
| Explicit priority | From identifiers.priority / endpoints.priority in the store. |
| Endpoint health/status | Prefer active over draining over inactive. |
| Freshness/verification | Higher score when identifiers.verified_at or evidence is recent. |
| Trust domain affinity | Match between requested trust domain and endpoint/participant metadata. |
Scoring must be deterministic: same inputs and same data ⇒ same scores and thus same order after tie-break.
Caching
- Positive cache: Key = hash or canonical form of (normalized identifiers, serviceContext, constraints, tenant). Value = ordered list of directives + TTL. Reuse until TTL expires or explicit invalidation.
- Negative cache: When no candidates survive filters, cache "no result" with a shorter TTL to avoid thundering herd on missing keys. Invalidation: on participant/identifier/endpoint/policy change for that tenant or key scope.
- Invalidation hooks: Connectors or admin updates that change participants/endpoints/policies should invalidate affected cache keys (by tenant, participant id, or key prefix). Optional: publish events for external caches.