import pytest from fin_hub.attribution import ( ClientAttribution, optional_attribution, parse_client_attribution_key, ) def test_client_attribution_key_is_stable(): attribution = ClientAttribution(" acme ", "portal", "prod-01") assert attribution.key == "client:acme|app:portal|instance:prod-01" assert parse_client_attribution_key(attribution.key) == attribution def test_empty_attribution_is_explicitly_unattributed(): assert optional_attribution(None, None, None) is None assert optional_attribution("", "", "") is None @pytest.mark.parametrize("invalid", ["has space", "has/slash", "", "x" * 129]) def test_client_attribution_rejects_unsafe_parts(invalid: str): with pytest.raises(ValueError): ClientAttribution(invalid, "portal", "prod-01") def test_client_attribution_parser_rejects_other_namespaces(): with pytest.raises(ValueError, match="invalid"): parse_client_attribution_key("platform:shared-cluster")