diff --git a/meshai/central/consumer.py b/meshai/central/consumer.py index 7c1f7d9..33f4fff 100644 --- a/meshai/central/consumer.py +++ b/meshai/central/consumer.py @@ -183,6 +183,12 @@ def _subjects_for(adapter: str, region: Optional[str]) -> list[str]: # on Central's scale, inverse of what the handler uses). # Off-season: June–Sep, CENTRAL_AVY will be empty — expected, not broken. "avalanche": [f"central.avy.advisory.>"], + # satpass: pass alerts are region-scoped (Central publishes + # central.sat.pass.us.., per quickstart §7); + # TLEs are global, no region token (central.sat.tle., §4) -- + # same no-region logic as swpc. + "satpass": [f"central.sat.pass.{region}.>", + "central.sat.tle.>"], } return list(table.get(adapter, [])) diff --git a/tests/test_central_region_routing.py b/tests/test_central_region_routing.py index 748ecf3..8fa6d98 100644 --- a/tests/test_central_region_routing.py +++ b/tests/test_central_region_routing.py @@ -117,5 +117,10 @@ def test_central_region_default_propagates_to_consumer_subjects(): assert env.central.region == "us.id" # spec default env.nws.feed_source = "central" so = CentralConsumer(env, None)._subject_owned() - assert list(so.keys()) == ["central.wx.alert.us.id.>"] + # satpass also defaults to feed_source='central', so it appears too + assert "central.wx.alert.us.id.>" in so assert so["central.wx.alert.us.id.>"] == {"nws"} + assert "central.sat.pass.us.id.>" in so + assert so["central.sat.pass.us.id.>"] == {"satpass"} + assert "central.sat.tle.>" in so + assert so["central.sat.tle.>"] == {"satpass"} diff --git a/tests/test_satpass_registration.py b/tests/test_satpass_registration.py index e34bb46..e652ed6 100644 --- a/tests/test_satpass_registration.py +++ b/tests/test_satpass_registration.py @@ -115,3 +115,33 @@ def test_yaml_parsing_satpass(): assert isinstance(env.satpass, SatpassConfig) assert env.satpass.enabled is True assert env.satpass.feed_source == "central" + + + +# -- _subjects_for() region rewrite table ------------------------------------ + +def test_subjects_for_satpass_with_region(): + """_subjects_for('satpass', 'us.id') must return region-scoped pass + subjects and global TLE subject.""" + from meshai.central.consumer import _subjects_for + result = _subjects_for('satpass', 'us.id') + assert len(result) == 2, f'Expected 2 subjects, got {len(result)}: {result}' + assert result[0] == 'central.sat.pass.us.id.>' + assert result[1] == 'central.sat.tle.>' + + +def test_subjects_for_satpass_no_region_falls_back(): + """_subjects_for('satpass', None) must return bare-wildcard forms + from _SUBJECTS_BARE.""" + from meshai.central.consumer import _subjects_for + result = _subjects_for('satpass', None) + assert len(result) == 2, f'Expected 2 subjects, got {len(result)}: {result}' + assert result[0] == 'central.sat.pass.>' + assert result[1] == 'central.sat.tle.>' + + +def test_subjects_for_satpass_empty_region_falls_back(): + """_subjects_for('satpass', '') must behave like None — bare wildcards.""" + from meshai.central.consumer import _subjects_for + result = _subjects_for('satpass', '') + assert result == _subjects_for('satpass', None)