From df5ad4ca4a9e1606334ae787bfddc3ddddf7b36b Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Sat, 17 Oct 2026 13:46:00 -0700 Subject: [PATCH] Pair TLE lines through the shared decoder and add the changelog fragment --- changelog.d/1101-tle-catalog-number-match.md | 3 +++ docs/CURRENT-STATE.md | 5 ++++- src/tools/queries/space.test.mjs | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1101-tle-catalog-number-match.md diff --git a/changelog.d/1101-tle-catalog-number-match.md b/changelog.d/1101-tle-catalog-number-match.md new file mode 100644 index 000000000..d1e2aa407 --- /dev/null +++ b/changelog.d/1101-tle-catalog-number-match.md @@ -0,0 +1,3 @@ +- Skip TLE sets whose line 1 and line 2 carry different catalog numbers, so a + spliced catalog cannot pair one satellite's elements with another's; the next + valid set still parses (VG31OP, #1101). diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 458c44c6e..6d066a475 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -1474,7 +1474,10 @@ access. Callers retain validation, transport and response policy. The shared TLE text parser skips incomplete named sets and resumes at the next complete set. A missing orbital line does not discard the later satellites in -the catalog; satellite layers and next-pass tools use the same parser. +the catalog. A set whose two lines carry different catalog numbers, or a +malformed catalog number, is skipped the same way, so a spliced catalog cannot +pair one satellite's elements with another's. Satellite layers and next-pass +tools use the same parser. ## Build configuration and local provider boundaries diff --git a/src/tools/queries/space.test.mjs b/src/tools/queries/space.test.mjs index 5b0fa5837..0eb5ce346 100644 --- a/src/tools/queries/space.test.mjs +++ b/src/tools/queries/space.test.mjs @@ -90,6 +90,21 @@ SAT ALPHA5 assert.equal(tleCatalogNumber(entries[0].line2), 100000); }); +test('TLE parsing rejects a pair whose catalog fields are malformed and resumes', () => { + // Read as digits up to the first non-digit, both fields would be 2554. + const text = `SAT MALFORMED +1 2554AU 98067A 24001.50000000 .00016717 00000-0 30270-3 0 9994 +2 2554B 51.6416 247.4627 0006703 130.5360 325.0288 15.50377579432414 +SAT HALF MALFORMED +1 2554AU 98067A 24001.50000000 .00016717 00000-0 30270-3 0 9994 +2 02554 51.6416 247.4627 0006703 130.5360 325.0288 15.50377579432414 +${TLE}`; + assert.deepEqual( + parseTleText(text).map((entry) => entry.name), + ['ISS (ZARYA)', 'CSS (TIANHE)'], + ); +}); + test('Alpha-5 catalog numbers decode, skipping I and O', () => { for (const [field, id] of [ ['A0000', 100000],