refactor: rename CloudEvents extension attributes hub* → central*

Rename extension attributes for consistency with project naming:
- hubschemaversion → centralschemaversion
- hubcategory → centralcategory
- hubseverity → centralseverity

Non-breaking change - no consumers depend on these names yet.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Matt Johnson 2026-05-15 21:47:06 +00:00 committed by Ubuntu
commit 4a7f1a76c7
2 changed files with 33 additions and 33 deletions

View file

@ -11,27 +11,27 @@ from central.models import Event
def wrap_event(event: Event, config: Config) -> tuple[dict[str, Any], str]: def wrap_event(event: Event, config: Config) -> tuple[dict[str, Any], str]:
""" """
Wrap an Event into a CNCF CloudEvents v1.0 JSON envelope. Wrap an Event into a CNCF CloudEvents v1.0 JSON envelope.
Returns: Returns:
A tuple of (envelope_dict, msg_id) where msg_id is the A tuple of (envelope_dict, msg_id) where msg_id is the
CloudEvent id for use as Nats-Msg-Id header. CloudEvent id for use as Nats-Msg-Id header.
""" """
# Build CE type: {prefix}.{category}.v1 # Build CE type: {prefix}.{category}.v1
ce_type = f"{config.cloudevents.type_prefix}.{event.category}.v1" ce_type = f"{config.cloudevents.type_prefix}.{event.category}.v1"
# Serialize event data # Serialize event data
event_data = event.model_dump(mode="json") event_data = event.model_dump(mode="json")
# Build extension attributes - lowercase, no underscores per CE spec # Build extension attributes - lowercase, no underscores per CE spec
extensions: dict[str, Any] = { extensions: dict[str, Any] = {
"hubschemaversion": config.cloudevents.schema_version, "centralschemaversion": config.cloudevents.schema_version,
"hubcategory": event.category, "centralcategory": event.category,
} }
# Only include hubseverity if severity is present # Only include centralseverity if severity is present
if event.severity is not None: if event.severity is not None:
extensions["hubseverity"] = event.severity extensions["centralseverity"] = event.severity
# Create CloudEvent # Create CloudEvent
ce = CloudEvent( ce = CloudEvent(
attributes={ attributes={
@ -44,9 +44,9 @@ def wrap_event(event: Event, config: Config) -> tuple[dict[str, Any], str]:
}, },
data=event_data, data=event_data,
) )
# Build envelope dict from CloudEvent # Build envelope dict from CloudEvent
envelope: dict[str, Any] = dict(ce.get_attributes()) envelope: dict[str, Any] = dict(ce.get_attributes())
envelope["data"] = ce.data envelope["data"] = ce.data
return envelope, event.id return envelope, event.id

View file

@ -59,12 +59,12 @@ def sample_config() -> Config:
class TestSubjectForEvent: class TestSubjectForEvent:
"""Tests for subject_for_event helper.""" """Tests for subject_for_event helper."""
def test_county_subject(self, sample_event: Event) -> None: def test_county_subject(self, sample_event: Event) -> None:
"""County codes produce county subject.""" """County codes produce county subject."""
subject = subject_for_event(sample_event) subject = subject_for_event(sample_event)
assert subject == "central.wx.alert.us.id.county.ada" assert subject == "central.wx.alert.us.id.county.ada"
def test_zone_subject(self, sample_geo: Geo) -> None: def test_zone_subject(self, sample_geo: Geo) -> None:
"""Zone codes produce zone subject.""" """Zone codes produce zone subject."""
geo = Geo( geo = Geo(
@ -83,7 +83,7 @@ class TestSubjectForEvent:
) )
subject = subject_for_event(event) subject = subject_for_event(event)
assert subject == "central.wx.alert.us.id.zone.z033" assert subject == "central.wx.alert.us.id.zone.z033"
def test_unknown_subject(self, sample_event: Event) -> None: def test_unknown_subject(self, sample_event: Event) -> None:
"""Missing primary_region produces unknown subject.""" """Missing primary_region produces unknown subject."""
geo = Geo(regions=[], primary_region=None) geo = Geo(regions=[], primary_region=None)
@ -97,7 +97,7 @@ class TestSubjectForEvent:
) )
subject = subject_for_event(event) subject = subject_for_event(event)
assert subject == "central.wx.alert.us.unknown" assert subject == "central.wx.alert.us.unknown"
def test_custom_prefix(self, sample_event: Event) -> None: def test_custom_prefix(self, sample_event: Event) -> None:
"""Custom prefix is used in subject.""" """Custom prefix is used in subject."""
subject = subject_for_event(sample_event, prefix="myapp.events") subject = subject_for_event(sample_event, prefix="myapp.events")
@ -106,13 +106,13 @@ class TestSubjectForEvent:
class TestCloudEventsWire: class TestCloudEventsWire:
"""Tests for CloudEvents wire format.""" """Tests for CloudEvents wire format."""
def test_required_fields_present( def test_required_fields_present(
self, sample_event: Event, sample_config: Config self, sample_event: Event, sample_config: Config
) -> None: ) -> None:
"""Required CloudEvents fields are present.""" """Required CloudEvents fields are present."""
envelope, msg_id = wrap_event(sample_event, sample_config) envelope, msg_id = wrap_event(sample_event, sample_config)
assert msg_id == sample_event.id assert msg_id == sample_event.id
assert envelope["id"] == sample_event.id assert envelope["id"] == sample_event.id
assert envelope["source"] == sample_config.cloudevents.source assert envelope["source"] == sample_config.cloudevents.source
@ -121,27 +121,27 @@ class TestCloudEventsWire:
assert "time" in envelope assert "time" in envelope
assert envelope["datacontenttype"] == "application/json" assert envelope["datacontenttype"] == "application/json"
assert "data" in envelope assert "data" in envelope
def test_extension_attributes_lowercase( def test_extension_attributes_lowercase(
self, sample_event: Event, sample_config: Config self, sample_event: Event, sample_config: Config
) -> None: ) -> None:
"""Extension attributes are lowercase with no underscores.""" """Extension attributes are lowercase with no underscores."""
envelope, _ = wrap_event(sample_event, sample_config) envelope, _ = wrap_event(sample_event, sample_config)
# Check that extension attributes exist and are lowercase # Check that extension attributes exist and are lowercase
assert envelope["hubschemaversion"] == "1.0" assert envelope["centralschemaversion"] == "1.0"
assert envelope["hubcategory"] == "wx.alert.severe_thunderstorm_warning" assert envelope["centralcategory"] == "wx.alert.severe_thunderstorm_warning"
assert envelope["hubseverity"] == 3 assert envelope["centralseverity"] == 3
# Verify no uppercase or underscores in extension names # Verify no uppercase or underscores in extension names
for key in ["hubschemaversion", "hubcategory", "hubseverity"]: for key in ["centralschemaversion", "centralcategory", "centralseverity"]:
assert key.islower() assert key.islower()
assert "_" not in key assert "_" not in key
def test_severity_none_omits_hubseverity( def test_severity_none_omits_centralseverity(
self, sample_geo: Geo, sample_config: Config self, sample_geo: Geo, sample_config: Config
) -> None: ) -> None:
"""When severity is None, hubseverity is omitted entirely.""" """When severity is None, centralseverity is omitted entirely."""
event = Event( event = Event(
id="test-no-severity", id="test-no-severity",
source="test", source="test",
@ -151,11 +151,11 @@ class TestCloudEventsWire:
geo=sample_geo, geo=sample_geo,
data={}, data={},
) )
envelope, _ = wrap_event(event, sample_config) envelope, _ = wrap_event(event, sample_config)
# hubseverity should not be present at all # centralseverity should not be present at all
assert "hubseverity" not in envelope assert "centralseverity" not in envelope
# Other extensions should still be present # Other extensions should still be present
assert "hubschemaversion" in envelope assert "centralschemaversion" in envelope
assert "hubcategory" in envelope assert "centralcategory" in envelope