{
  "version": 1,
  "recipe": "docs/journey-key-v1.md",
  "frozen": "Never edit this file. A recipe change adds journey-key.v2.vectors.json, keys jk2_/lk2_ and @contractUnit journey-key-v2.",
  "vectors": [
    {
      "id": "A1",
      "description": "Case A: Malaysia Airlines BOM to DPS round trip via KUL, every time stated (seller A, INR 52,000, 1 seat).",
      "offer": {
        "supplierOfferRef": "floffer_2Ry7mKq9TzW4bXc1Vn8LpA",
        "pricing": {
          "totalAmount": 52000,
          "currency": "INR"
        },
        "availableSeats": 1,
        "cabin": "ECONOMY",
        "legs": [
          {
            "departureTime": "2026-11-07T00:15:00+05:30",
            "arrivalTime": "2026-11-07T12:35:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "195"
                },
                "originCode": "BOM",
                "destCode": "KUL",
                "departureTime": "2026-11-07T00:15:00+05:30",
                "arrivalTime": "2026-11-07T06:20:00+08:00",
                "originTerminal": "2"
              },
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "715"
                },
                "originCode": "KUL",
                "destCode": "DPS",
                "departureTime": "2026-11-07T09:30:00+08:00",
                "arrivalTime": "2026-11-07T12:35:00+08:00"
              }
            ]
          },
          {
            "departureTime": "2026-11-14T13:30:00+08:00",
            "arrivalTime": "2026-11-14T22:05:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "714"
                },
                "originCode": "DPS",
                "destCode": "KUL",
                "departureTime": "2026-11-14T13:30:00+08:00",
                "arrivalTime": "2026-11-14T16:35:00+08:00"
              },
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "194"
                },
                "originCode": "KUL",
                "destCode": "BOM",
                "departureTime": "2026-11-14T19:00:00+08:00",
                "arrivalTime": "2026-11-14T22:05:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_08e989777e95001e81f2a6e79f5a99e4",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-07T00:15|2026-11-07T12:35|MH195:BOM-KUL,MH715:KUL-DPS",
            "legKey": "lk1_8a9bacde0040d6e9cfcc81fb9648fb4a",
            "legKeyComparable": true,
            "legKeyGaps": []
          },
          {
            "canonical": "2026-11-14T13:30|2026-11-14T22:05|MH714:DPS-KUL,MH194:KUL-BOM",
            "legKey": "lk1_18c9cfceb3188b608662f0f19accb521",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "A2",
      "description": "Case A: the same flights from a second seller of the same seats (INR 52,300): naive times without offsets, other terminals, other times at KUL, no cabin stated (null). Same keys as A1.",
      "offer": {
        "supplierOfferRef": "floffer_5Hc3nWd8QsE0yLt6Mb2KxR",
        "pricing": {
          "totalAmount": 52300,
          "currency": "INR"
        },
        "availableSeats": 1,
        "cabin": null,
        "legs": [
          {
            "departureTime": "2026-11-07T00:15:00",
            "arrivalTime": "2026-11-07T12:35:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "mh",
                  "flightNumber": "0195"
                },
                "originCode": "bom",
                "destCode": "KUL",
                "departureTime": "2026-11-07T00:15:00",
                "arrivalTime": "2026-11-07T06:25:00",
                "originTerminal": "1"
              },
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "715"
                },
                "originCode": "KUL",
                "destCode": "DPS",
                "departureTime": "2026-11-07T09:35:00",
                "arrivalTime": "2026-11-07T12:35:00"
              }
            ]
          },
          {
            "departureTime": "2026-11-14T13:30:00",
            "arrivalTime": "2026-11-14T22:05:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "714"
                },
                "originCode": "DPS",
                "destCode": "KUL",
                "departureTime": "2026-11-14T13:30:00",
                "arrivalTime": "2026-11-14T16:30:00"
              },
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "194"
                },
                "originCode": "KUL",
                "destCode": "BOM",
                "departureTime": "2026-11-14T19:05:00",
                "arrivalTime": "2026-11-14T22:05:00"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_08e989777e95001e81f2a6e79f5a99e4",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-07T00:15|2026-11-07T12:35|MH195:BOM-KUL,MH715:KUL-DPS",
            "legKey": "lk1_8a9bacde0040d6e9cfcc81fb9648fb4a",
            "legKeyComparable": true,
            "legKeyGaps": []
          },
          {
            "canonical": "2026-11-14T13:30|2026-11-14T22:05|MH714:DPS-KUL,MH194:KUL-BOM",
            "legKey": "lk1_18c9cfceb3188b608662f0f19accb521",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "A3",
      "description": "A one-way BOM to DPS on the same outbound flights: its legKey equals the package outbound legKey; its journeyKey differs from the package journeyKey.",
      "offer": {
        "supplierOfferRef": "floffer_8Kd2pLx7RqT1vNz4Wc6YbH",
        "legs": [
          {
            "departureTime": "2026-11-07T00:15:00+05:30",
            "arrivalTime": "2026-11-07T12:35:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "195"
                },
                "originCode": "BOM",
                "destCode": "KUL",
                "departureTime": "2026-11-07T00:15:00+05:30",
                "arrivalTime": "2026-11-07T06:20:00+08:00"
              },
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "715"
                },
                "originCode": "KUL",
                "destCode": "DPS",
                "departureTime": "2026-11-07T09:30:00+08:00",
                "arrivalTime": "2026-11-07T12:35:00+08:00"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_8a9bacde0040d6e9cfcc81fb9648fb4a",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-07T00:15|2026-11-07T12:35|MH195:BOM-KUL,MH715:KUL-DPS",
            "legKey": "lk1_8a9bacde0040d6e9cfcc81fb9648fb4a",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "B1",
      "description": "Case B: VietJet VJ 910 then VJ 997 via HAN, arriving DPS 16:25.",
      "offer": {
        "supplierOfferRef": "floffer_3Fh8tQw2ZkM6pRx9Lb1CvN",
        "legs": [
          {
            "departureTime": "2026-11-07T00:40:00+05:30",
            "arrivalTime": "2026-11-07T16:25:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "910"
                },
                "originCode": "BOM",
                "destCode": "HAN",
                "departureTime": "2026-11-07T00:40:00+05:30",
                "arrivalTime": "2026-11-07T06:40:00+07:00"
              },
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "997"
                },
                "originCode": "HAN",
                "destCode": "DPS",
                "departureTime": "2026-11-07T10:20:00+07:00",
                "arrivalTime": "2026-11-07T16:25:00+08:00"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_1851acae636507cd52f1d744dbd26d66",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-07T00:40|2026-11-07T16:25|VJ910:BOM-HAN,VJ997:HAN-DPS",
            "legKey": "lk1_1851acae636507cd52f1d744dbd26d66",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "B2",
      "description": "Case B: the same first flight VJ 910, then VJ 993, arriving DPS 21:10: a different journey, a different key.",
      "offer": {
        "supplierOfferRef": "floffer_7Gj4yUe6XnP2sTq8Md3BwK",
        "legs": [
          {
            "departureTime": "2026-11-07T00:40:00+05:30",
            "arrivalTime": "2026-11-07T21:10:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "910"
                },
                "originCode": "BOM",
                "destCode": "HAN",
                "departureTime": "2026-11-07T00:40:00+05:30",
                "arrivalTime": "2026-11-07T06:40:00+07:00"
              },
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "993"
                },
                "originCode": "HAN",
                "destCode": "DPS",
                "departureTime": "2026-11-07T15:05:00+07:00",
                "arrivalTime": "2026-11-07T21:10:00+08:00"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_0c38744be3de7c30f89b588624a6b300",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-07T00:40|2026-11-07T21:10|VJ910:BOM-HAN,VJ993:HAN-DPS",
            "legKey": "lk1_0c38744be3de7c30f89b588624a6b300",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "D1",
      "description": "Case D: B1 flights from a seller that does not state the times at HAN (inner times left out). Only the leg start and end are read, so it groups with B1.",
      "offer": {
        "supplierOfferRef": "floffer_9Lm1qSa5VcJ7wEr3Nf6HdZ",
        "legs": [
          {
            "departureTime": "2026-11-07T00:40:00+05:30",
            "arrivalTime": "2026-11-07T16:25:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "910"
                },
                "originCode": "BOM",
                "destCode": "HAN",
                "departureTime": "2026-11-07T00:40:00+05:30"
              },
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "997"
                },
                "originCode": "HAN",
                "destCode": "DPS",
                "arrivalTime": "2026-11-07T16:25:00+08:00"
              }
            ],
            "layovers": [
              {
                "airport": "HAN",
                "durationMinutes": 220,
                "isOvernight": null
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_1851acae636507cd52f1d744dbd26d66",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-07T00:40|2026-11-07T16:25|VJ910:BOM-HAN,VJ997:HAN-DPS",
            "legKey": "lk1_1851acae636507cd52f1d744dbd26d66",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "C1",
      "description": "Case C: VietJet PQC to HYD stated as two VJ 326 flights via SGN, every time stated.",
      "offer": {
        "supplierOfferRef": "floffer_4Pn6rDk1YtB8xWm2Qg7JcS",
        "legs": [
          {
            "departureTime": "2026-11-19T14:20:00+07:00",
            "arrivalTime": "2026-11-19T22:35:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "PQC",
                "destCode": "SGN",
                "departureTime": "2026-11-19T14:20:00+07:00",
                "arrivalTime": "2026-11-19T15:10:00+07:00"
              },
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "SGN",
                "destCode": "HYD",
                "departureTime": "2026-11-19T19:40:00+07:00",
                "arrivalTime": "2026-11-19T22:35:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_6bda240ba9043cb9b1fca59f8bd3b052",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-19T14:20|2026-11-19T22:35|VJ326:PQC-SGN,VJ326:SGN-HYD",
            "legKey": "lk1_6bda240ba9043cb9b1fca59f8bd3b052",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "C2",
      "description": "The same journey as ONE flight VJ 326 with a technical stop at SGN: a stop expands into hops, so it equals C1.",
      "offer": {
        "supplierOfferRef": "floffer_6Qr3sFm8ZuC1yXn5Rh2KdT",
        "legs": [
          {
            "departureTime": "2026-11-19T14:20:00+07:00",
            "arrivalTime": "2026-11-19T22:35:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "PQC",
                "destCode": "HYD",
                "departureTime": "2026-11-19T14:20:00+07:00",
                "arrivalTime": "2026-11-19T22:35:00+05:30",
                "technicalStops": [
                  {
                    "airportCode": "SGN",
                    "arrivalTime": "2026-11-19T15:10:00+07:00",
                    "departureTime": "2026-11-19T19:40:00+07:00",
                    "durationMinutes": 270
                  }
                ]
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_6bda240ba9043cb9b1fca59f8bd3b052",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-19T14:20|2026-11-19T22:35|VJ326:PQC-SGN,VJ326:SGN-HYD",
            "legKey": "lk1_6bda240ba9043cb9b1fca59f8bd3b052",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "C3",
      "description": "Case C: a seller that splits the flight at the stop: VJ 326 PQC to SGN, then a VietJet flight with no number. Not comparable; its key is unique to this offer.",
      "offer": {
        "supplierOfferRef": "floffer_1Ts9uGn4AvD6zYp8Sj3LeU",
        "legs": [
          {
            "departureTime": "2026-11-19T14:20:00+07:00",
            "arrivalTime": "2026-11-19T22:35:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "PQC",
                "destCode": "SGN",
                "departureTime": "2026-11-19T14:20:00+07:00",
                "arrivalTime": "2026-11-19T15:10:00+07:00"
              },
              {
                "marketingCarrier": {
                  "code": "VJ"
                },
                "originCode": "SGN",
                "destCode": "HYD",
                "departureTime": "2026-11-19T19:40:00+07:00",
                "arrivalTime": "2026-11-19T22:35:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_6f1049fd70acfc600611194b0b83ab6d",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_1f99670034ae1a9398c04fcbdc320897",
            "legKeyComparable": false,
            "legKeyGaps": ["FLIGHT_NUMBER_MISSING"]
          }
        ]
      }
    },
    {
      "id": "C4",
      "description": "Case C: the same flights from a second split copy, same seller: still unique, never equal to C3.",
      "offer": {
        "supplierOfferRef": "floffer_0Uv2wHp7BxE3aZq9Tk4MfV",
        "legs": [
          {
            "departureTime": "2026-11-19T14:20:00+07:00",
            "arrivalTime": "2026-11-19T22:35:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "PQC",
                "destCode": "SGN",
                "departureTime": "2026-11-19T14:20:00+07:00",
                "arrivalTime": "2026-11-19T15:10:00+07:00"
              },
              {
                "marketingCarrier": {
                  "code": "VJ"
                },
                "originCode": "SGN",
                "destCode": "HYD",
                "departureTime": "2026-11-19T19:40:00+07:00",
                "arrivalTime": "2026-11-19T22:35:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_05a08616836656193487e5666dfa4bd6",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_3479e719a91aa2d41a802216e12e1325",
            "legKeyComparable": false,
            "legKeyGaps": ["FLIGHT_NUMBER_MISSING"]
          }
        ]
      }
    },
    {
      "id": "C5",
      "description": "Case C: a card that says one stop without naming the airport (unnamedStops). Not comparable.",
      "offer": {
        "supplierOfferRef": "floffer_5Wx7yJr2CzF9bAs1Ul6NgW",
        "legs": [
          {
            "departureTime": "2026-11-19T14:20:00+07:00",
            "arrivalTime": "2026-11-19T22:35:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "PQC",
                "destCode": "HYD",
                "departureTime": "2026-11-19T14:20:00+07:00",
                "arrivalTime": "2026-11-19T22:35:00+05:30",
                "unnamedStops": 1
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_c0d1bbd0cb3898c3ef117ba2e1ae3cdd",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_b25fbb92740a57e7d96f1e8004775a52",
            "legKeyComparable": false,
            "legKeyGaps": ["STOP_NOT_NAMED"]
          }
        ]
      }
    },
    {
      "id": "C6",
      "description": "Case C: another seller states VJ 326 leaving PQC at 14:10, not 14:20: a different stated time, a different key.",
      "offer": {
        "supplierOfferRef": "floffer_3Yz5aLs8DbG2cBt4Vm7PhX",
        "legs": [
          {
            "departureTime": "2026-11-19T14:10:00+07:00",
            "arrivalTime": "2026-11-19T22:35:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "PQC",
                "destCode": "SGN",
                "departureTime": "2026-11-19T14:10:00+07:00",
                "arrivalTime": "2026-11-19T15:00:00+07:00"
              },
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "326"
                },
                "originCode": "SGN",
                "destCode": "HYD",
                "departureTime": "2026-11-19T19:40:00+07:00",
                "arrivalTime": "2026-11-19T22:35:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_80dd89d65ba0a2a8e09d06984669bcf4",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-19T14:10|2026-11-19T22:35|VJ326:PQC-SGN,VJ326:SGN-HYD",
            "legKey": "lk1_80dd89d65ba0a2a8e09d06984669bcf4",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "E1",
      "description": "Case E: IndiGo 6E 5092 + 6E 6059 BOM to JRG via BLR from a seller with 1 seat(s) at INR 7,000. One key for all three; never add their seats.",
      "offer": {
        "supplierOfferRef": "floffer_7Ab1cNt3EdH5dCu8Wn2RjY",
        "pricing": {
          "totalAmount": 7000,
          "currency": "INR"
        },
        "availableSeats": 1,
        "legs": [
          {
            "departureTime": "2026-11-05T05:40:00+05:30",
            "arrivalTime": "2026-11-05T12:55:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "5092"
                },
                "originCode": "BOM",
                "destCode": "BLR",
                "departureTime": "2026-11-05T05:40:00+05:30",
                "arrivalTime": "2026-11-05T07:25:00+05:30"
              },
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "6059"
                },
                "originCode": "BLR",
                "destCode": "JRG",
                "departureTime": "2026-11-05T10:30:00+05:30",
                "arrivalTime": "2026-11-05T12:55:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_344c5d853065ce68d3ee7ea34e7e55e2",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-05T05:40|2026-11-05T12:55|6E5092:BOM-BLR,6E6059:BLR-JRG",
            "legKey": "lk1_344c5d853065ce68d3ee7ea34e7e55e2",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "E2",
      "description": "Case E: IndiGo 6E 5092 + 6E 6059 BOM to JRG via BLR from a seller with 4 seat(s) at INR 7,070. One key for all three; never add their seats.",
      "offer": {
        "supplierOfferRef": "floffer_2Bc4dPu6FeJ8eDv1Xo5SkZ",
        "pricing": {
          "totalAmount": 7070,
          "currency": "INR"
        },
        "availableSeats": 4,
        "legs": [
          {
            "departureTime": "2026-11-05T05:40:00+05:30",
            "arrivalTime": "2026-11-05T12:55:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "5092"
                },
                "originCode": "BOM",
                "destCode": "BLR",
                "departureTime": "2026-11-05T05:40:00+05:30",
                "arrivalTime": "2026-11-05T07:25:00+05:30"
              },
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "6059"
                },
                "originCode": "BLR",
                "destCode": "JRG",
                "departureTime": "2026-11-05T10:30:00+05:30",
                "arrivalTime": "2026-11-05T12:55:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_344c5d853065ce68d3ee7ea34e7e55e2",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-05T05:40|2026-11-05T12:55|6E5092:BOM-BLR,6E6059:BLR-JRG",
            "legKey": "lk1_344c5d853065ce68d3ee7ea34e7e55e2",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "E3",
      "description": "Case E: IndiGo 6E 5092 + 6E 6059 BOM to JRG via BLR from a seller with 9 seat(s) at INR 7,280. One key for all three; never add their seats.",
      "offer": {
        "supplierOfferRef": "floffer_9Cd7eQv9GfK1fEw4Yp8TmA",
        "pricing": {
          "totalAmount": 7280,
          "currency": "INR"
        },
        "availableSeats": 9,
        "legs": [
          {
            "departureTime": "2026-11-05T05:40:00+05:30",
            "arrivalTime": "2026-11-05T12:55:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "5092"
                },
                "originCode": "BOM",
                "destCode": "BLR",
                "departureTime": "2026-11-05T05:40:00+05:30",
                "arrivalTime": "2026-11-05T07:25:00+05:30"
              },
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "6059"
                },
                "originCode": "BLR",
                "destCode": "JRG",
                "departureTime": "2026-11-05T10:30:00+05:30",
                "arrivalTime": "2026-11-05T12:55:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_344c5d853065ce68d3ee7ea34e7e55e2",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-05T05:40|2026-11-05T12:55|6E5092:BOM-BLR,6E6059:BLR-JRG",
            "legKey": "lk1_344c5d853065ce68d3ee7ea34e7e55e2",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "S1",
      "description": "IndiGo 6E 1607 BOM to DPS as one flight with its technical stop at MAA.",
      "offer": {
        "supplierOfferRef": "floffer_4De1fRw2HgL4gFx7Zq1UnB",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T17:50:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "1607"
                },
                "originCode": "BOM",
                "destCode": "DPS",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T17:50:00+08:00",
                "technicalStops": [
                  {
                    "airportCode": "MAA",
                    "arrivalTime": "2026-11-18T08:15:00+05:30",
                    "departureTime": "2026-11-18T08:55:00+05:30"
                  }
                ]
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_e40f0edfd5b035847fa60b0d729552fa",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-18T06:10|2026-11-18T17:50|6E1607:BOM-MAA,6E1607:MAA-DPS",
            "legKey": "lk1_e40f0edfd5b035847fa60b0d729552fa",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "S2",
      "description": "The same flight sent as two 6E 1607 rows (BOM to MAA, MAA to DPS): equal to S1.",
      "offer": {
        "supplierOfferRef": "floffer_6Ef4gSx5IhM7hGy0Ar4VoC",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T17:50:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "1607"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              },
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "1607"
                },
                "originCode": "MAA",
                "destCode": "DPS",
                "departureTime": "2026-11-18T08:55:00+05:30",
                "arrivalTime": "2026-11-18T17:50:00+08:00"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_e40f0edfd5b035847fa60b0d729552fa",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-18T06:10|2026-11-18T17:50|6E1607:BOM-MAA,6E1607:MAA-DPS",
            "legKey": "lk1_e40f0edfd5b035847fa60b0d729552fa",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "G1",
      "description": "A card sold as one flight \"910/997\" with one unnamed stop (joined numbers): not comparable, two reasons.",
      "offer": {
        "supplierOfferRef": "floffer_8Fg7hTy8JiN0iHz3Bs7WpD",
        "legs": [
          {
            "departureTime": "2026-11-07T00:40:00+05:30",
            "arrivalTime": "2026-11-07T16:25:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "910/997"
                },
                "originCode": "BOM",
                "destCode": "DPS",
                "departureTime": "2026-11-07T00:40:00+05:30",
                "arrivalTime": "2026-11-07T16:25:00+08:00",
                "unnamedStops": 1
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_5ab9b07b795e844fa03a18259b8d85e9",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_55ff6123c71ac40e8bd2181142dc1801",
            "legKeyComparable": false,
            "legKeyGaps": ["FLIGHT_NUMBER_JOINED", "STOP_NOT_NAMED"]
          }
        ]
      }
    },
    {
      "id": "G2",
      "description": "A leg whose last arrival is not trusted (arrivalTimeUnconfirmed): not comparable.",
      "offer": {
        "supplierOfferRef": "floffer_1Gh0iUz1KjP3jIa6Ct0XqE",
        "legs": [
          {
            "departureTime": "2026-11-07T23:55:00+05:30",
            "arrivalTime": "2026-11-07T21:10:00+04:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "AI",
                  "flightNumber": "983"
                },
                "originCode": "DEL",
                "destCode": "DXB",
                "departureTime": "2026-11-07T23:55:00+05:30",
                "arrivalTime": "2026-11-07T21:10:00+04:00",
                "arrivalTimeUnconfirmed": true
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_48b148b959761f0eb51b34d12aa92b5a",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_123d2805fae9d19a667b21682a86e898",
            "legKeyComparable": false,
            "legKeyGaps": ["ARRIVAL_UNCONFIRMED"]
          }
        ]
      }
    },
    {
      "id": "G3",
      "description": "A flight whose airline is blank (a carrier Kitionz could not read) and a number with its airline glued on (\"6E1607\"): not comparable.",
      "offer": {
        "supplierOfferRef": "floffer_3Hi2jVa4LkQ6kJb9Du3YrF",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T17:50:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "",
                  "flightNumber": "1607"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              },
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "6E1607"
                },
                "originCode": "MAA",
                "destCode": "DPS",
                "departureTime": "2026-11-18T08:55:00+05:30",
                "arrivalTime": "2026-11-18T17:50:00+08:00"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_5107359d3e643dd651b9cd9fa5e1e610",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_28d692e812229175e4179d74898b211c",
            "legKeyComparable": false,
            "legKeyGaps": ["AIRLINE_NOT_STATED", "FLIGHT_NUMBER_UNREADABLE"]
          }
        ]
      }
    },
    {
      "id": "G4",
      "description": "A stop with a blank airport, a destination that is not a 3-letter code, and a departure that cannot be read to the minute: not comparable.",
      "offer": {
        "supplierOfferRef": "floffer_5Ij5kWb7MlR9lKc2Ev6ZsG",
        "legs": [
          {
            "departureTime": "2026-11-07 00:40",
            "arrivalTime": "2026-11-07T16:25:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "VJ",
                  "flightNumber": "910"
                },
                "originCode": "BOM",
                "destCode": "DPSX",
                "departureTime": "2026-11-07T00:40:00+05:30",
                "arrivalTime": "2026-11-07T16:25:00+08:00",
                "technicalStops": [
                  {
                    "airportCode": ""
                  }
                ]
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_59428f290ceafb78402f3bbbf6a36eb9",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_d349b2bd2861b3c9d21f001875567560",
            "legKeyComparable": false,
            "legKeyGaps": ["AIRPORT_NOT_EXACT", "STOP_NOT_NAMED", "TIME_NOT_STATED"]
          }
        ]
      }
    },
    {
      "id": "G5",
      "description": "A round trip whose outbound is comparable and whose return is not: the outbound legKey still matches A3; the journeyKey is unique.",
      "offer": {
        "supplierOfferRef": "floffer_7Jk8lXc0NmS2mLd5Fw9AtH",
        "legs": [
          {
            "departureTime": "2026-11-07T00:15:00+05:30",
            "arrivalTime": "2026-11-07T12:35:00+08:00",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "195"
                },
                "originCode": "BOM",
                "destCode": "KUL",
                "departureTime": "2026-11-07T00:15:00+05:30",
                "arrivalTime": "2026-11-07T06:20:00+08:00"
              },
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "715"
                },
                "originCode": "KUL",
                "destCode": "DPS",
                "departureTime": "2026-11-07T09:30:00+08:00",
                "arrivalTime": "2026-11-07T12:35:00+08:00"
              }
            ]
          },
          {
            "departureTime": "2026-11-14T13:30:00+08:00",
            "arrivalTime": "2026-11-14T22:05:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "MH",
                  "flightNumber": "714"
                },
                "originCode": "DPS",
                "destCode": "KUL",
                "departureTime": "2026-11-14T13:30:00+08:00",
                "arrivalTime": "2026-11-14T16:35:00+08:00"
              },
              {
                "marketingCarrier": {
                  "code": "MH"
                },
                "originCode": "KUL",
                "destCode": "BOM",
                "departureTime": "2026-11-14T19:00:00+08:00",
                "arrivalTime": "2026-11-14T22:05:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_2e31098767616ef44750ec490d961c06",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": "2026-11-07T00:15|2026-11-07T12:35|MH195:BOM-KUL,MH715:KUL-DPS",
            "legKey": "lk1_8a9bacde0040d6e9cfcc81fb9648fb4a",
            "legKeyComparable": true,
            "legKeyGaps": []
          },
          {
            "canonical": null,
            "legKey": "lk1_5b55c18fd2203d976533eec2c39d36af",
            "legKeyComparable": false,
            "legKeyGaps": ["FLIGHT_NUMBER_MISSING"]
          }
        ]
      }
    },
    {
      "id": "G6",
      "description": "A leg that lists no flights: not comparable.",
      "offer": {
        "supplierOfferRef": "floffer_9Kl1mYd3OnT5nMe8Gx2BuI",
        "legs": [
          {
            "departureTime": "2026-11-07T00:15:00+05:30",
            "arrivalTime": "2026-11-07T12:35:00+08:00",
            "segments": []
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_3ad26dd0b36c494476fee97889929ec5",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_a5030dc4f7d7652c5a5e5c7df15c61be",
            "legKeyComparable": false,
            "legKeyGaps": ["FLIGHTS_NOT_STATED"]
          }
        ]
      }
    },
    {
      "id": "H1",
      "description": "A three-letter (ICAO) airline code: comparable.",
      "offer": {
        "supplierOfferRef": "floffer_1Hm2nZe4PoU6oNf9Hy5CvJ",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T08:15:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "IGO",
                  "flightNumber": "1607"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_adede66f4df6ce409616e3d45834abc9",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-18T06:10|2026-11-18T08:15|IGO1607:BOM-MAA",
            "legKey": "lk1_adede66f4df6ce409616e3d45834abc9",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "H2",
      "description": "An all-digit airline code (\"12\") is not an airline designator.",
      "offer": {
        "supplierOfferRef": "floffer_3In5oAf7QpV9pOg2Iz8DwK",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T08:15:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "12",
                  "flightNumber": "1607"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_76f6a1a8e00b362d954362df59c7dcc1",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_8eb8c32c980107eff3a50c8f70f21647",
            "legKeyComparable": false,
            "legKeyGaps": ["AIRLINE_NOT_STATED"]
          }
        ]
      }
    },
    {
      "id": "H3",
      "description": "A flight number with a letter suffix (\"1607A\") keeps the letter.",
      "offer": {
        "supplierOfferRef": "floffer_5Jo8pBg0RqW2qPh5Ja1ExL",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T08:15:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "1607A"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_12df280f7eacd5330b287ed898ff85d7",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-18T06:10|2026-11-18T08:15|6E1607A:BOM-MAA",
            "legKey": "lk1_12df280f7eacd5330b287ed898ff85d7",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "H4",
      "description": "Lower case and a leading zero (\"6e\", \"01607a\") give the same string as H3.",
      "offer": {
        "supplierOfferRef": "floffer_7Kp1qCh3SrX5rQi8Kb4FyM",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T08:15:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6e",
                  "flightNumber": "01607a"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_12df280f7eacd5330b287ed898ff85d7",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-18T06:10|2026-11-18T08:15|6E1607A:BOM-MAA",
            "legKey": "lk1_12df280f7eacd5330b287ed898ff85d7",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "H5",
      "description": "Flight number \"0\" stays \"0\".",
      "offer": {
        "supplierOfferRef": "floffer_9Lq4rDi6TsY8sRj1Lc7GzN",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T08:15:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "0"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_6d70eb905452676c1acf5b81fa4ab814",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-18T06:10|2026-11-18T08:15|6E0:BOM-MAA",
            "legKey": "lk1_6d70eb905452676c1acf5b81fa4ab814",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "H6",
      "description": "Flight number \"00\" becomes \"0\": the same string as H5.",
      "offer": {
        "supplierOfferRef": "floffer_2Mr7sEj9UtZ1tSk4Md0HaO",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T08:15:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "00"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_6d70eb905452676c1acf5b81fa4ab814",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-18T06:10|2026-11-18T08:15|6E0:BOM-MAA",
            "legKey": "lk1_6d70eb905452676c1acf5b81fa4ab814",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    },
    {
      "id": "H7",
      "description": "A five-digit number (\"12345\") is not 1-4 digits.",
      "offer": {
        "supplierOfferRef": "floffer_4Ns0tFk2VuA4uTl7Ne3IbP",
        "legs": [
          {
            "departureTime": "2026-11-18T06:10:00+05:30",
            "arrivalTime": "2026-11-18T08:15:00+05:30",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "12345"
                },
                "originCode": "BOM",
                "destCode": "MAA",
                "departureTime": "2026-11-18T06:10:00+05:30",
                "arrivalTime": "2026-11-18T08:15:00+05:30"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_009e7f5c604949b9bb08a2a96d305056",
        "journeyKeyComparable": false,
        "legs": [
          {
            "canonical": null,
            "legKey": "lk1_f5dfca2357eb779207554ccdd2d54fad",
            "legKeyComparable": false,
            "legKeyGaps": ["FLIGHT_NUMBER_UNREADABLE"]
          }
        ]
      }
    },
    {
      "id": "H8",
      "description": "Case E flights with times ending in \"Z\": the offset is ignored and the digits are read as written, so it equals E1.",
      "offer": {
        "supplierOfferRef": "floffer_6Ot3uGl5WvB7vUm0Of6JcQ",
        "legs": [
          {
            "departureTime": "2026-11-05T05:40:00Z",
            "arrivalTime": "2026-11-05T12:55:00Z",
            "segments": [
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "5092"
                },
                "originCode": "BOM",
                "destCode": "BLR",
                "departureTime": "2026-11-05T05:40:00Z",
                "arrivalTime": "2026-11-05T07:25:00Z"
              },
              {
                "marketingCarrier": {
                  "code": "6E",
                  "flightNumber": "6059"
                },
                "originCode": "BLR",
                "destCode": "JRG",
                "departureTime": "2026-11-05T10:30:00Z",
                "arrivalTime": "2026-11-05T12:55:00Z"
              }
            ]
          }
        ]
      },
      "expected": {
        "journeyKey": "jk1_344c5d853065ce68d3ee7ea34e7e55e2",
        "journeyKeyComparable": true,
        "legs": [
          {
            "canonical": "2026-11-05T05:40|2026-11-05T12:55|6E5092:BOM-BLR,6E6059:BLR-JRG",
            "legKey": "lk1_344c5d853065ce68d3ee7ea34e7e55e2",
            "legKeyComparable": true,
            "legKeyGaps": []
          }
        ]
      }
    }
  ]
}
