Files
as4-411/docs/architecture/resolution-algorithm.md
defiQUG c24ae925cf
Some checks failed
CI / lint (push) Has been cancelled
CI / build (push) Has been cancelled
Initial commit: AS4/411 directory and discovery service for Sankofa Marketplace
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 08:44:20 -08:00

78 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.