Docs / TeoScore / Risk & Protection
Risk & Protection (V10–V12)
Category 4 — what happens if things go wrong: connection protection, same-day recovery options, and how flexible the ticket is. A default top-priority category for most personas.
How the category aggregates
Fixed weighting: V10 active (connecting, not disabled) → V10×0.30 + V11×0.35 + V12×0.35; V10 inactive (nonstop, or disabled) → V11×0.50 + V12×0.50. V11 and V12 are always active (each returns a neutral 50 with no data — V12 now unconditionally, see below). A +5 loyalty boost is applied to the category when your wallet gives a positive adjustment.
Measures — how protected your connection would be if the first leg is late — one ticket vs a self-transfer. Currently disabled, not scored.
Disabled 2026-08-04 (V10_DISABLED)
Turned off by an explicit product decision — no specific data-availability or spec-scope gap recorded for this one, unlike V3/V6/V9. The tier logic and alliance detection below are intact for re-enabling; they just aren't contributing to any score right now. A connecting itinerary's Category 4 score today is V11 + V12 renormalized, as if V10 didn't exist.
single_ticket → 100 · alliance_interline → 80 · insured_connection → 50 · self_transfer → 0 otherwise per-connection min-wins (weakest link sets the tier)
Data & accuracy (when re-enabled) — neither our cash nor award data sources return a “protection tier” field. It is inferred in the search layer: award options → single_ticket; cash options → single_ticket if there's a booking reference or all legs are the same airline. That inference is reliable for single-carrier / award itineraries.
Known gap for mixed-carrier connections (predates the disable above)
The multi-airline branch of the inference is incomplete — the alliance lookup is stubbed off and the emitted values don't match the engine's tier enum — so multi-carrier connections don't get the 80/50 tiers and fall back to the per-connection estimate. This may be part of why V10 was disabled, but that wasn't confirmed at the time — don't assume it without checking.
Gotchas — would drop on nonstops if re-enabled (there's no connection to protect).
Measures — how easily you could be rebooked to the destination the same day if this flight is cancelled. More same-day alternatives → higher score; one arriving soon after your original arrival, on the same airline, is worth more than one further out or on another carrier.
Contribution = Time_Weight × Carrier_Weight (per qualifying alternative) Score = min(100, Base_Floor + ΣContribution)
| Factor | Condition | Value |
|---|---|---|
| Carrier Weight | Same marketing carrier | 1.0 |
| Carrier Weight | Interline / other carrier | 0.5 |
| Time Weight | <2h / 2–6h / 6–12h / >12h later than your original arrival | 10 / 7 / 5 / 3 |
| Base Floor | Direct or connecting × ≥3 or <3 qualifying alternatives | 75 / 25 / 40 / 10 |
Data & accuracy (fixed 2026-08-04) — qualifying alternatives are the other options already in this same search on your exact route, arriving the same local day at or after your original's scheduled departure — no separate schedule feed needed. A richer details.recoveryFlights[].carrierRelation feed still takes priority when present (flat 50/other-20 scale, no time weighting), but no live provider populates it today; a plain recoveryFlightCount falls back to the other-airline rate with no time weighting or floor.
This search's result set is a biased slice of what's actually flying
The "alternatives" are whatever this specific search returned — filtered by your cabin class, award-vs-cash mode, and other search parameters — not an independent query of everything flying that route that day. A thin result set (e.g. business-class-only, or an award-only search on a route with sparse award availability) will under-count real alternatives that exist in other cabins or fare types. This is a real accuracy tradeoff of the current implementation, not a bug.
Neutral vs zero — no siblings on the route at all → neutral 50 (we genuinely don't know); siblings exist but none qualify → a real, counted zero, using the Base Floor Matrix's low tier (25 direct / 10 connecting) rather than the neutral fallback.
Measures — how flexible the ticket is if your plans change (refund / change rules), cash and award scored separately. Currently disabled, always neutral.
Disabled 2026-08-04 (V12_DISABLED)
Reason: not enough data validated. Confirmed before implementing — fareFlexibility, awardFlexibility, eliteFlexibilityTier, and fareComponents are only ever populated by a local test-fixture data path, never by the real Duffel/seats.aero normalizers, so every real option was already landing on the neutral/lowest-tier fallback. The tier tables and elite-bonus math below are intact for re-enabling; they just aren't contributing to any score right now.
V12a cash: full_refund 100 · free_change 75 · fee_change 50 · none 0 V12b award: free_cancel 100 · redeposit_low 70 · redeposit_high 45 · no_cancel 0 per fare component: min(100, Base + eliteBonus), then min across components
Data & accuracy — reads fareFlexibility (cash) or awardFlexibility (award). An elite bonus (cash +0/+5/+10/+15, award +0/+0/+20/+30) is added when the operating carrier matches your status tier. Mixed-fare itineraries take the weakest component.
Gotchas — disabled; always returns a neutral 50 regardless of flexibility data.