78 lines
5.4 KiB
Markdown
78 lines
5.4 KiB
Markdown
|
|
# Resolution Algorithm
|
|||
|
|
|
|||
|
|
Deterministic resolution pipeline that produces ordered routing directives. Input/output contracts are defined in the [OpenAPI spec](../api/openapi.yaml); persistence shape is in the [data model](data-model.md).
|
|||
|
|
|
|||
|
|
## 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:
|
|||
|
|
|
|||
|
|
1. **Tenant override** — Tenant-specific routing artifact or endpoint override.
|
|||
|
|
2. **Contract-specific config** — Contract or connectivity-group mapping.
|
|||
|
|
3. **Internal curated directory** — Participants/endpoints stored in the directory (admin or connector).
|
|||
|
|
4. **External authoritative directory** — SMP/SML, GTT feed, or other external source (cached).
|
|||
|
|
5. **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](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](connectors.md).
|
|||
|
|
|
|||
|
|
## Pipeline (steps 1–9)
|
|||
|
|
|
|||
|
|
1. **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.
|
|||
|
|
|
|||
|
|
2. **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.
|
|||
|
|
|
|||
|
|
3. **Candidate retrieval**
|
|||
|
|
Query the directory store for participants and endpoints matching any of the normalized/expanded identifiers, within the requested tenant and constraints.
|
|||
|
|
|
|||
|
|
4. **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 include `requiredCapability`, `messageType` (e.g. ISO8583 MTI), and `networkBrand` for card rails.
|
|||
|
|
|
|||
|
|
5. **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.
|
|||
|
|
|
|||
|
|
6. **Score and rank**
|
|||
|
|
Score remaining candidates (see [Scoring](#scoring)). Sort by score descending; apply [tie-break rules](#determinism-and-tie-break) for stable ordering.
|
|||
|
|
|
|||
|
|
7. **Assemble directives**
|
|||
|
|
For each ranked candidate, build a `RouteDirective`: map endpoint + participant to `target_protocol`, `target_address`, `transport_profile`, attach security refs (from credentials), `service_context`, `qos`, `ttl_seconds`, and `evidence` (source, lastVerified, confidenceScore).
|
|||
|
|
|
|||
|
|
8. **Sign response (optional)**
|
|||
|
|
In multi-party setups, optionally sign the response for non-repudiation. Not required for MVP.
|
|||
|
|
|
|||
|
|
9. **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](data-model.md#conflict-resolution-deterministic)):
|
|||
|
|
1. **Explicit priority** (endpoint/identifier priority from store) — higher first.
|
|||
|
|
2. **Policy** (allow/deny and policy priority).
|
|||
|
|
3. **Freshness** (updated_at / verified_at / valid_from).
|
|||
|
|
4. **Confidence** (edge or evidence confidence score).
|
|||
|
|
5. **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.
|