Files
as4-411/docs/architecture/resolution-algorithm.md

78 lines
5.4 KiB
Markdown
Raw Permalink Normal View History

# 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 19)
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 27. 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.