Repository: opensanctions/opensanctions
Pull request #2241: [us_trade_csl] relationships establishment
Author: login: nvmbrasserie
Created: 2025-05-09T21:49:05Z | Merged: 2025-05-15T16:20:26Z

@pudo:
"I feel like maybe doing a full lookup in us_trade_csl could be a wonderful improvement: split out a clean version of the Authority, and map to a programId at the same time."


Diff:
diff --git a/datasets/us/trade_csl/crawler.py b/datasets/us/trade_csl/crawler.py
index 92eea20a3d..b1c4d6555f 100644
--- a/datasets/us/trade_csl/crawler.py
+++ b/datasets/us/trade_csl/crawler.py
@@ -8,10 +8,89 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+# Programs emitted by this crawler (is_ofac=False):
+# These are non-OFAC sanctions or export control lists where entities are emitted
+# with their own unique internal identifiers.
+#
+#     "Nonproliferation Sanctions (ISN) - State Department",
+#     "ITAR Debarred (DTC) - State Department",
+#     "Unverified List (UVL) - Bureau of Industry and Security",
+#     "Entity List (EL) - Bureau of Industry and Security",
+#     "Denied Persons List (DPL) - Bureau of Industry and Security",
+#     "Military End User (MEU) List - Bureau of Industry and Security",
+
+# The following programs refer to entities that are emitted with the ID format
+# `ofac-<entity_number>`. This allows them to match directly with existing OFAC data.
+# It prevents duplication across datasets.
+#
+#     "Capta List (CAP) - Treasury Department",
+#     "Palestinian Legislative Council List (PLC) - Treasury Department",
+#     "Foreign Sanctions Evaders (FSE) - Treasury Department",
+#     "Non-SDN Chinese Military-Industrial Complex Companies List (CMIC) - Treasury Department",
+#     "Non-SDN Menu-Based Sanctions List (NS-MBS List) - Treasury Department",
+#     "Specially Designated Nationals (SDN) - Treasury Department",
+#     "Sectoral Sanctions Identifications List (SSI) - Treasury Department",
 
 REGEX_AUTHORITY_ID_SEP = re.compile(r"(\d+ F\.?R\.?)")
 
 
+def emit_relationship(
+    context: Context,
+    entity_id: str,
+    *,
+    related_name: str,
+    list_entry: Dict[str, Any],
+    source_program: str
+):
+    related_entity = context.make("LegalEntity")
+    related_entity.id = context.make_id(related_name)
+    related_entity.add("name", related_name)
+    context.emit(related_entity)
+
+    make_and_emit_sanction(
+        context,
+        related_entity,
+        source_program=source_program,
+        list_entry=list_entry,
+    )
+
+    rel = context.make("UnknownLink")
+    rel.id = context.make_id(entity_id, "linked to", rel.id)
+    rel.add("subject", entity_id)
+    rel.add("object", related_entity.id)
+    context.emit(rel)
+
+
+def make_and_emit_sanction(
+    context: Context, entity: Entity, *, source_program: str, list_entry: Dict[str, Any]
+):
+    sanction = h.make_sanction(
+        context,
+        entity,
+        program_name=source_program,
+        source_program_key=source_program,
+        program_key=(
+            h.lookup_sanction_program_key(context, source_program)
+            if source_program
+            else None
+        ),
+    )
+    sanction.add("program", list_entry.pop("programs", []))
+    sanction.add("provisions", list_entry.pop("license_policy", []))
+    sanction.add("reason", list_entry.pop("license_requirement", []))
+    sanction.add(
+        "authorityId",
+        clean_authority(list_entry.pop("federal_register_notice", None)),
+    )
+    h.apply_date(sanction, "startDate", list_entry.pop("start_date", None))
+    h.apply_date(sanction, "endDate", list_entry.pop("end_date", None))
+    sanction.add("country", "us")
+    sanction.add("authority", source_program)
+    sanction.add("sourceUrl", list_entry.pop("source_information_url", None))
+
+    context.emit(sanction)
+
+
 def parse_addresses(
     context: Context, addresses: List[Dict[str, str]]
 ) -> Generator[Entity, None, None]:
@@ -66,29 +145,29 @@ def clean_authority(value: Optional[str]) -> Optional[List[str]]:
     return h.multi_split(value, [";", ", "])
 
 
-def parse_result(context: Context, result: Dict[str, Any]):
-    for k, v in list(result.items()):
+def parse_list_entry(context: Context, list_entry: Dict[str, Any]):
+    for k, v in list(list_entry.items()):
         if isinstance(v, str) and len(v.strip()) == 0:
-            result.pop(k)
+            list_entry.pop(k)
 
-    type_ = result.pop("type", None)
+    type_ = list_entry.pop("type", None)
     schema = context.lookup_value("type", type_)
     if schema is None:
         context.log.error("Unknown result type", type=type_)
         return
-    name = result.pop("name", None)
+    name = list_entry.pop("name", None)
     if name and re.match(r"^Address \d+", name):
         schema = "Address"
 
     entity = context.make(schema)
-    entity.id = context.make_slug(result.pop("id"))
-    source = result.pop("source", "")
-    if source.startswith("Unverified List"):
+    entity.id = context.make_slug(list_entry.pop("id"))
+    source_program = list_entry.pop("source", "")
+    if source_program.startswith("Unverified List"):
         entity.add("topics", "export.control")
     else:
         entity.add("topics", "sanction")
 
-    entity_number = result.pop("entity_number", None)
+    entity_number = list_entry.pop("entity_number", None)
     is_ofac = False
     if entity_number is not None:
         assert int(entity_number)
@@ -103,17 +182,37 @@ def parse_result(context: Context, result: Dict[str, Any]):
     name = name.replace("and any successor, sub-unit, or subsidiary thereof", "")
 
     # Handle messed-up unicode in BIS names
-    if "bis.doc.gov" in result.get("source_list_url", ""):
+    if "bis.doc.gov" in list_entry.get("source_list_url", ""):
         name = name.replace("?s ", "'s ")
         name = name.replace("?", " ")
 
-    name_with_information_res = context.lookup("name_with_information", name)
-    if name_with_information_res is not None:
-        entity.add("name", name_with_information_res.properties["name"])
-        entity.add("notes", name_with_information_res.properties["notes"])
+    name_with_info_res = context.lookup("name_with_info_res", name)
+    if name_with_info_res is not None:
+        entity.add("name", name_with_info_res.properties["name"], original_value=name)
+        entity.add("previousName", name_with_info_res.properties.get("previous_name"))
+        entity.add("notes", name_with_info_res.properties.get("notes"))
+
+        related_names = name_with_info_res.properties.get("related")
+        # For now we only support one related name, even though conceptually there could be multiple
+        assert isinstance(related_names, str) or related_names is None
+        # Example: "Huawei Technologies Co., Ltd. (Huawei). Affiliated Entity: Hangzhou Huawei (...)"
+        # Here, the affiliate (Hangzhou Huawei) is processed directly, while the main entity (Huawei)
+        # is extracted from the 'related' field and emitted via 'emit_relationship'. Since some main
+        # entities might only appear through related names, we also apply 'make_and_emit_sanction'
+        # within 'emit_relationship' to ensure they're not missed.
+        if related_names:
+            emit_relationship(
+                context,
+                entity.id,
+                related_name=related_names[0],
+                list_entry=list_entry,
+                source_program=source_program,
+            )
     else:
         # If it's a really long name, it's likely a name with extra info
-        if len(name) > registry.name.max_length:
+        if len(name) > registry.name.max_length or any(
+            kw in name.lower() for kw in ["affiliated", "subordinate", "f.k.a."]
+        ):
             context.log.warning(
                 "Name long is very long, maybe it contains extra information?",
                 name=name,
@@ -125,74 +224,64 @@ def parse_result(context: Context, result: Dict[str, Any]):
         # Don't double-import OFAC entities
         return
 
-    for alias in ensure_list(result.pop("alt_names", "")):
+    for alias in ensure_list(list_entry.pop("alt_names", "")):
         entity.add("alias", alias.split("; "))
-    entity.add("notes", result.pop("remarks", None))
-    entity.add("country", result.pop("country", None))
+    entity.add("notes", list_entry.pop("remarks", None))
+    entity.add("country", list_entry.pop("country", None))
     if entity.schema.is_a("Person"):
-        entity.add("position", result.pop("title", None))
-        entity.add("nationality", result.pop("nationalities", None))
-        entity.add("citizenship", result.pop("citizenships", None))
-        for dob in ensure_list(result.pop("dates_of_birth", "")):
+        entity.add("position", list_entry.pop("title", None))
+        entity.add("nationality", list_entry.pop("nationalities", None))
+        entity.add("citizenship", list_entry.pop("citizenships", None))
+        for dob in ensure_list(list_entry.pop("dates_of_birth", "")):
             dob = h.multi_split(dob, ["circa ", " to "])
             for date in dob:
                 h.apply_date(entity, "birthDate", date)
-        entity.add("birthPlace", result.pop("places_of_birth", None))
+        entity.add("birthPlace", list_entry.pop("places_of_birth", None))
     elif entity.schema.is_a("Vessel"):
-        entity.add("flag", result.pop("vessel_flag", None))
-        entity.add("callSign", result.pop("call_sign", None))
-        entity.add("type", result.pop("vessel_type", None))
-        grt = result.pop("gross_registered_tonnage", None)
+        entity.add("flag", list_entry.pop("vessel_flag", None))
+        entity.add("callSign", list_entry.pop("call_sign", None))
+        entity.add("type", list_entry.pop("vessel_type", None))
+        grt = list_entry.pop("gross_registered_tonnage", None)
         entity.add("grossRegisteredTonnage", grt)
-        gt = result.pop("gross_tonnage", None)
+        gt = list_entry.pop("gross_tonnage", None)
         entity.add("tonnage", gt)
 
         # TODO: make adjacent owner entity
-        result.pop("vessel_owner", None)
+        list_entry.pop("vessel_owner", None)
 
-    assert result.pop("title", None) is None
+    assert list_entry.pop("title", None) is None
     # print(result)
-    assert not result.pop("nationalities", None)
-    assert not result.pop("citizenships", None)
-    assert not result.pop("dates_of_birth", None)
-    assert not result.pop("places_of_birth", None)
-    result.pop("call_sign", None)
-    assert not result.pop("gross_tonnage", None)
-    assert not result.pop("gross_registered_tonnage", None)
-    assert not result.pop("vessel_flag", None)
-    assert not result.pop("vessel_owner", None)
-    assert not result.pop("vessel_type", None)
-
-    for obj in parse_addresses(context, result.pop("addresses", [])):
+    assert not list_entry.pop("nationalities", None)
+    assert not list_entry.pop("citizenships", None)
+    assert not list_entry.pop("dates_of_birth", None)
+    assert not list_entry.pop("places_of_birth", None)
+    list_entry.pop("call_sign", None)
+    assert not list_entry.pop("gross_tonnage", None)
+    assert not list_entry.pop("gross_registered_tonnage", None)
+    assert not list_entry.pop("vessel_flag", None)
+    assert not list_entry.pop("vessel_owner", None)
+    assert not list_entry.pop("vessel_type", None)
+
+    for obj in parse_addresses(context, list_entry.pop("addresses", [])):
         # h.apply_address(context, entity, obj)
         if entity.schema.is_a("Address"):
             entity.add("full", obj.get("full"))
         else:
             h.copy_address(entity, obj)
 
-    for ident in result.pop("ids", []):
+    for ident in list_entry.pop("ids", []):
         context.log.warning("Unknown ID type", id=ident)
 
-    sanction = context.make("Sanction")
-    sanction.id = context.make_id(entity.id, "Sanction")
-    sanction.add("entity", entity)
-    sanction.add("program", result.pop("programs", []))
-    sanction.add("provisions", result.pop("license_policy", []))
-    sanction.add("reason", result.pop("license_requirement", []))
-    sanction.add(
-        "authorityId",
-        clean_authority(result.pop("federal_register_notice", None)),
+    make_and_emit_sanction(
+        context,
+        entity,
+        source_program=source_program,
+        list_entry=list_entry,
     )
-    sanction.add("startDate", result.pop("start_date", None))
-    sanction.add("endDate", result.pop("end_date", None))
-    sanction.add("country", "us")
-    sanction.add("authority", source)
-    sanction.add("sourceUrl", result.pop("source_information_url"))
-    result.pop("source_list_url")
+    list_entry.pop("source_list_url")
 
-    context.emit(sanction)
     context.emit(entity)
-    context.audit_data(result, ignore=["standard_order"])
+    context.audit_data(list_entry, ignore=["standard_order"])
 
 
 def crawl(context: Context):
@@ -200,5 +289,5 @@ def crawl(context: Context):
     context.export_resource(path, JSON, title=context.SOURCE_TITLE)
     with open(path, "r") as file:
         data = json.load(file)
-        for result in data.get("results"):
-            parse_result(context, result)
+        for list_entry in data.get("results"):
+            parse_list_entry(context, list_entry)
diff --git a/datasets/us/trade_csl/us_trade_csl.yml b/datasets/us/trade_csl/us_trade_csl.yml
index 7a50604a79..3f63ae3258 100644
--- a/datasets/us/trade_csl/us_trade_csl.yml
+++ b/datasets/us/trade_csl/us_trade_csl.yml
@@ -73,6 +73,20 @@ assertions:
       Address: 35
 
 lookups:
+  sanction.program:
+    options:
+      - match: Nonproliferation Sanctions (ISN) - State Department
+        value: US-DOS-ISN
+      - match: ITAR Debarred (DTC) - State Department
+        value: US-AECA-DEBARRED
+      - match: Unverified List (UVL) - Bureau of Industry and Security
+        value: US-BIS-UVL
+      - match: Entity List (EL) - Bureau of Industry and Security
+        value: US-BIS-EL
+      - match: Denied Persons List (DPL) - Bureau of Industry and Security
+        value: US-BIS-DPL
+      - match: Military End User (MEU) List - Bureau of Industry and Security
+        value: US-BIS-MEU
   type:
     options:
       - match:
@@ -86,7 +100,7 @@ lookups:
         value: Vessel
       - match: Aircraft
         value: Airplane
-  name_with_information:
+  name_with_info_res:
     options:
       - match: The Ministry of Defence of the Republic of Belarus, including the Armed Forces of Belarus and all operating units wherever located.  This includes the national armed services (army and air force), as well as the national guard and national police, government intelligence or reconnaissance organizations of the Republic of Belarus.  All addresses located in Belarus.
         properties:
@@ -100,6 +114,228 @@ lookups:
         properties:
           name: Ministry of Defence of the Russian Federation
           notes: Includes the Armed Forces of Russia and all operating units wherever located.  This includes the national armed services (army, navy, marine, air force, or coast guard), as well as the national guard and national police, government intelligence or reconnaissance organizations of the Russian Federation.  All address located in Russia.
+      - match: 'Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Beijing Huawei Longshine Information Technology Co., Ltd.'
+        properties:
+          name: Beijing Huawei Longshine Information Technology Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Hangzhou New Longshine Information Technology Co., Ltd."
+        properties:
+          name: Hangzhou New Longshine Information Technology Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Communication Technology Co., Ltd."
+        properties:
+          name: Hangzhou Huawei Communication Technology Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Digital Technologies (Suzhou) Co., Ltd."
+        properties:
+          name: Huawei Digital Technologies (Suzhou) Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Enterprises"
+        properties:
+          name: Hangzhou Huawei Enterprises
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Marine Networks Co., Ltd."
+        properties:
+          name: Huawei Marine Networks Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Mobile Technology Ltd."
+        properties:
+          name: Huawei Mobile Technology Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Tech. Investment Co."
+        properties:
+          name: Huawei Tech. Investment Co.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technology Co., Ltd. Chengdu Research Institute"
+        properties:
+          name: Huawei Technology Co., Ltd. Chengdu Research Institute
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technology Co., Ltd. Hangzhou Research Institute"
+        properties:
+          name: Huawei Technology Co., Ltd. Hangzhou Research Institute
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technologies Co., Ltd., Beijing Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd., Beijing Research Institute
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technologies Co., Ltd., Material Characterization Lab"
+        properties:
+          name: Huawei Technologies Co., Ltd., Material Characterization Lab
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Technologies Co., Ltd., Xi'an Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd., Xi'an Research Institute
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Terminal (Shenzhen) Co., Ltd. "
+        properties:
+          name: Huawei Terminal (Shenzhen) Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Nanchang Huawei Communication Technology "
+        properties:
+          name: Nanchang Huawei Communication Technology
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Ningbo Huawei Computer & Net Co., Ltd."
+        properties:
+          name: Ningbo Huawei Computer & Net Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shanghai Huawei Technologies Co., Ltd."
+        properties:
+          name: Shanghai Huawei Technologies Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei New Technology Co., Ltd."
+        properties:
+          name: Shenzhen Huawei New Technology Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei Technology Service"
+        properties:
+          name: Shenzhen Huawei Technology Service
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei Technologies Software"
+        properties:
+          name: Shenzhen Huawei Technologies Software
+          related: Huawei Technologies Co., Ltd.
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Zhejiang Huawei Communications Technology Co., Ltd."
+        properties:
+          name: Zhejiang Huawei Communications Technology Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "Affiliated Supply and Consultancy Services"
+        properties:
+          name: Affiliated Supply and Consultancy Services
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Shenzhen Huawei Anjiexin Electricity Co., Ltd."
+        properties:
+          name: Shenzhen Huawei Anjiexin Electricity Co., Ltd.
+          related: Huawei Technologies Co., Ltd.
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution -  Second Design Department"
+        properties:
+          name: Second Design Department of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 23rd Research Institute"
+        properties:
+          name: 23rd Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 25th Research Institute"
+        properties:
+          name: 25th Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 201 Research Institute"
+        properties:
+          name: 201 Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 203rd Research Institute"
+        properties:
+          name: 203rd Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 204th Research Institute"
+        properties:
+          name: 204th Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 206th Research Institute"
+        properties:
+          name: 206th Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 207th Research Institute"
+        properties:
+          name: 207th Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 208th Research Institute"
+        properties:
+          name: 208th Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 210th Research Institute"
+        properties:
+          name: 210th Research Institute of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 283 Factory"
+        properties:
+          name: 283 Factory of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 284 Factory"
+        properties:
+          name: 284 Factory of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 699 Factory"
+        properties:
+          name: 699 Factory of the China Aerospace Science and Industry Corporation Second Academy
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Bowei Integrated Circuits "
+        properties:
+          name: Bowei Integrated Circuits
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Envoltek "
+        properties:
+          name: Envoltek
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Hebei Sinopack Electronics"
+        properties:
+          name: Hebei Sinopack Electronics
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Hebei Brightway International"
+        properties:
+          name: Hebei Brightway International
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Hebei Medicines Health"
+        properties:
+          name: Hebei Medicines Health
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Hebei Puxing Electronic"
+        properties:
+          name: Hebei Puxing Electronic
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Micro Electronic Technology"
+        properties:
+          name: Micro Electronic Technology
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Shijiazhuang Development Zone Maiteda Microelectronics Technology Development and Application Corporation"
+        properties:
+          name: Shijiazhuang Development Zone Maiteda Microelectronics Technology Development and Application Corporation
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - MT Microsystems"
+        properties:
+          name: MT Microsystems
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - North China Integrated Circuit Corporation"
+        properties:
+          name: North China Integrated Circuit Corporation
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Tonghui Electronics"
+        properties:
+          name: Tonghui Electronics
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "China Electronics Technology Group Corporation 14th Research Institute (CETC 14).  Subordinate Institution - Nanjing SunSea Industry Corporation"
+        properties:
+          name: Nanjing SunSea Industry Corporation
+          related: China Electronics Technology Group Corporation 14th Research Institute (CETC 14)
+      - match: "China Electronics Technology Group Corporation 14th Research Institute (CETC 14).  Subordinate Institution - Nanjing Institute of Radio Technology"
+        properties:
+          name: Nanjing Institute of Radio Technology
+          related: China Electronics Technology Group Corporation 14th Research Institute (CETC 14)
+      - match: "Pakistan Atomic Energy Commission (PAEC), and subordinate entity National Development Complex (NDC) "
+        properties:
+          name: National Development Complex (NDC)
+          related: Pakistan Atomic Energy Commission (PAEC)
+      - match: "Pakistan Atomic Energy Commission (PAEC), and subordinate entity Pakistan Institute for Nuclear Science and Technology (PINSTECH)"
+        properties:
+          name: Pakistan Institute for Nuclear Science and Technology (PINSTECH)
+          related: Pakistan Atomic Energy Commission (PAEC)
+      - match: "Pakistan Atomic Energy Commission (PAEC), and subordinate entity National Institute of Lasers and Optronics (NILOP)"
+        properties:
+          name: National Institute of Lasers and Optronics (NILOP)
+          related: Pakistan Atomic Energy Commission (PAEC)
+      - match: "Guangzhou Hongyu Technology Co., Ltd. (a subordinate institute of CETC-7)"
+        properties:
+          name: Guangzhou Hongyu Technology Co., Ltd.
+          related: CETC-7
+      - match: "Guangzhou Tongguang Communication Technology Co., Ltd. (a subordinate institute of CETC-7)"
+        properties:
+          name: Guangzhou Tongguang Communication Technology Co., Ltd.
+          related: CETC-7
+      - match: "China Electronics Technology Group Corporation 13th Research Institute (CETC 13).  Subordinate Institution - Hebei Poshing Electronics"
+        properties:
+          name: Hebei Poshing Electronics
+          related: China Electronics Technology Group Corporation 13th Research Institute (CETC 13)
+      - match: "Resort Nizhnyaya Oreanda (f.k.a., Federalnoe Gosudarstvennoe Byudzhetnoe Uchrezhdenie Sanatori Nizhnyaya Oreanda Upravleniya)"
+        properties:
+          name: Resort Nizhnyaya Oreanda
+          previous_name: Federalnoe Gosudarstvennoe Byudzhetnoe Uchrezhdenie Sanatori Nizhnyaya Oreanda Upravleniya
+      - match: "OAO Volgogradneftemash (f.k.a. Dochernee Aktsionernoe Obshchestvo Otkrytogo Tipa Volgogradneftemash Rossiiskogo Aktsionernogo Obshchestva Gazprom)"
+        properties:
+          name: OAO Volgogradneftemash
+          previous_name: Dochernee Aktsionernoe Obshchestvo Otkrytogo Tipa Volgogradneftemash Rossiiskogo Aktsionernogo Obshchestva Gazprom
+      - match: "LTS Holding Limited (f.k.a. IPP-International Petroleum Products Ltd.)"
+        properties:
+          name: LTS Holding Limited
+          previous_name: IPP-International Petroleum Products Ltd.
+      - match: "SGM Most OOO (f.k.a., Obshchestvo S Ogranichennoi Otvetstvennostyu SGM Most)"
+        properties:
+          name: SGM Most OOO
+          previous_name: Obshchestvo S Ogranichennoi Otvetstvennostyu SGM Most
   type.date:
     options:
       - match: "3033-01-17"


Reviews:
user: login: leonhandreke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T13:58:02Z
user: login: nvmbrasserie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T16:21:30Z
user: login: github-advanced-security[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:06:27Z
user: login: leonhandreke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:06:41Z
user: login: leonhandreke
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:09:40Z
user: login: nvmbrasserie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T14:24:07Z
user: login: leonhandreke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T14:49:56Z
user: login: leonhandreke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T14:54:49Z

Review comments:
diff_hunk: @@ -100,6 +114,277 @@ lookups:
         properties:
           name: Ministry of Defence of the Russian Federation
           notes: Includes the Armed Forces of Russia and all operating units wherever located.  This includes the national armed services (army, navy, marine, air force, or coast guard), as well as the national guard and national police, government intelligence or reconnaissance organizations of the Russian Federation.  All address located in Russia.
+      - match: 'Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Beijing Huawei Longshine Information Technology Co., Ltd.'
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Beijing Huawei Longshine Information Technology Co., Ltd
+          notes: 'Affiliated Entity:  Beijing Huawei Longshine Information Technology Co., Ltd.'
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Hangzhou New Longshine Information Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou New Longshine Information Technology Co., Ltd
+          notes: "Affiliated Entity: Hangzhou New Longshine Information Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Communication Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou Huawei Communication Technology Co., Ltd
+          notes: "Affiliated Entity:  Hangzhou Huawei Communication Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Digital Technologies (Suzhou) Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Digital Technologies (Suzhou) Co., Ltd
+          notes: "Affiliated Entity:  Huawei Digital Technologies (Suzhou) Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Enterprises"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou Huawei Enterprises
+          notes: "Affiliated Entity:  Hangzhou Huawei Enterprises"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Marine Networks Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Marine Networks Co., Ltd
+          notes: "Affiliated Entity:  Huawei Marine Networks Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Mobile Technology Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Mobile Technology Ltd
+          notes: "Affiliated Entity: Huawei Mobile Technology Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Tech. Investment Co."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Tech. Investment Co
+          notes: "Affiliated Entity: Huawei Tech. Investment Co."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technology Co., Ltd. Chengdu Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technology Co., Ltd. Chengdu Research Institute
+          notes: "Affiliated Entity:  Huawei Technology Co., Ltd. Chengdu Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technology Co., Ltd. Hangzhou Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technology Co., Ltd. Hangzhou Research Institute
+          notes: "Affiliated Entity:  Huawei Technology Co., Ltd. Hangzhou Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technologies Co., Ltd., Beijing Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technologies Co., Ltd., Beijing Research Institute
+          notes: "Affiliated Entity:  Huawei Technologies Co., Ltd., Beijing Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technologies Co., Ltd., Material Characterization Lab"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technologies Co., Ltd., Material Characterization Lab
+          notes: "Affiliated Entity:  Huawei Technologies Co., Ltd., Material Characterization Lab"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Technologies Co., Ltd., Xi'an Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technologies Co., Ltd., Xi'an Research Institute
+          notes: "Affiliated Entity: Huawei Technologies Co., Ltd., Xi'an Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Terminal (Shenzhen) Co., Ltd. "
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Terminal (Shenzhen) Co., Ltd.
+          notes: "Affiliated Entity: Huawei Terminal (Shenzhen) Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Nanchang Huawei Communication Technology "
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Nanchang Huawei Communication Technology
+          notes: "Affiliated Entity: Nanchang Huawei Communication Technology "
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Ningbo Huawei Computer & Net Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Ningbo Huawei Computer & Net Co., Ltd.
+          notes: "Affiliated Entity: Ningbo Huawei Computer & Net Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shanghai Huawei Technologies Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shanghai Huawei Technologies Co., Ltd.
+          notes: "Affiliated Entity: Shanghai Huawei Technologies Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei New Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei New Technology Co., Ltd.
+          notes: "Affiliated Entity: Shenzhen Huawei New Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei Technology Service"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei Technology Service
+          notes: "Affiliated Entity: Shenzhen Huawei Technology Service"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei Technologies Software"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei Technologies Software
+          notes: "Affiliated Entity: Shenzhen Huawei Technologies Software"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Zhejiang Huawei Communications Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Zhejiang Huawei Communications Technology Co., Ltd.
+          notes: "Affiliated Entity: Zhejiang Huawei Communications Technology Co., Ltd."
+      - match: "Affiliated Supply and Consultancy Services"
+        properties:
+          name: Affiliated Supply and Consultancy Services
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Shenzhen Huawei Anjiexin Electricity Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei Anjiexin Electricity Co., Ltd
+          notes: "Affiliated Entity:  Shenzhen Huawei Anjiexin Electricity Co., Ltd."
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution -  Second Design Department"
+        properties:
+          name: China Aerospace Science and Industry Corporation Second Academy
+          related: Second Design Department
+          notes: "Subordinate Institution -  Second Design Department"
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 23rd Research Institute"
path: datasets/us/trade_csl/us_trade_csl.yml
user: login: leonhandreke
body: Hm, for these branches I feel it makes sense to keep around the full name or put the branch name in parentheses or with a comma (like for the Huawei departments above). I think "23rd Research Institute" on its own isn't really enough to make sense.

created_at: 2025-05-14T13:48:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -100,6 +114,277 @@ lookups:
         properties:
           name: Ministry of Defence of the Russian Federation
           notes: Includes the Armed Forces of Russia and all operating units wherever located.  This includes the national armed services (army, navy, marine, air force, or coast guard), as well as the national guard and national police, government intelligence or reconnaissance organizations of the Russian Federation.  All address located in Russia.
+      - match: 'Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Beijing Huawei Longshine Information Technology Co., Ltd.'
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Beijing Huawei Longshine Information Technology Co., Ltd
+          notes: 'Affiliated Entity:  Beijing Huawei Longshine Information Technology Co., Ltd.'
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Hangzhou New Longshine Information Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou New Longshine Information Technology Co., Ltd
+          notes: "Affiliated Entity: Hangzhou New Longshine Information Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Communication Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou Huawei Communication Technology Co., Ltd
+          notes: "Affiliated Entity:  Hangzhou Huawei Communication Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Digital Technologies (Suzhou) Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Digital Technologies (Suzhou) Co., Ltd
+          notes: "Affiliated Entity:  Huawei Digital Technologies (Suzhou) Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Enterprises"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou Huawei Enterprises
+          notes: "Affiliated Entity:  Hangzhou Huawei Enterprises"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Marine Networks Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Marine Networks Co., Ltd
+          notes: "Affiliated Entity:  Huawei Marine Networks Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Mobile Technology Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Mobile Technology Ltd
+          notes: "Affiliated Entity: Huawei Mobile Technology Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Tech. Investment Co."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Tech. Investment Co
+          notes: "Affiliated Entity: Huawei Tech. Investment Co."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technology Co., Ltd. Chengdu Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technology Co., Ltd. Chengdu Research Institute
+          notes: "Affiliated Entity:  Huawei Technology Co., Ltd. Chengdu Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technology Co., Ltd. Hangzhou Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technology Co., Ltd. Hangzhou Research Institute
+          notes: "Affiliated Entity:  Huawei Technology Co., Ltd. Hangzhou Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technologies Co., Ltd., Beijing Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technologies Co., Ltd., Beijing Research Institute
+          notes: "Affiliated Entity:  Huawei Technologies Co., Ltd., Beijing Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Technologies Co., Ltd., Material Characterization Lab"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technologies Co., Ltd., Material Characterization Lab
+          notes: "Affiliated Entity:  Huawei Technologies Co., Ltd., Material Characterization Lab"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Technologies Co., Ltd., Xi'an Research Institute"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Technologies Co., Ltd., Xi'an Research Institute
+          notes: "Affiliated Entity: Huawei Technologies Co., Ltd., Xi'an Research Institute"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Huawei Terminal (Shenzhen) Co., Ltd. "
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Terminal (Shenzhen) Co., Ltd.
+          notes: "Affiliated Entity: Huawei Terminal (Shenzhen) Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Nanchang Huawei Communication Technology "
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Nanchang Huawei Communication Technology
+          notes: "Affiliated Entity: Nanchang Huawei Communication Technology "
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Ningbo Huawei Computer & Net Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Ningbo Huawei Computer & Net Co., Ltd.
+          notes: "Affiliated Entity: Ningbo Huawei Computer & Net Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shanghai Huawei Technologies Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shanghai Huawei Technologies Co., Ltd.
+          notes: "Affiliated Entity: Shanghai Huawei Technologies Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei New Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei New Technology Co., Ltd.
+          notes: "Affiliated Entity: Shenzhen Huawei New Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei Technology Service"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei Technology Service
+          notes: "Affiliated Entity: Shenzhen Huawei Technology Service"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Shenzhen Huawei Technologies Software"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei Technologies Software
+          notes: "Affiliated Entity: Shenzhen Huawei Technologies Software"
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Zhejiang Huawei Communications Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Zhejiang Huawei Communications Technology Co., Ltd.
+          notes: "Affiliated Entity: Zhejiang Huawei Communications Technology Co., Ltd."
+      - match: "Affiliated Supply and Consultancy Services"
+        properties:
+          name: Affiliated Supply and Consultancy Services
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Shenzhen Huawei Anjiexin Electricity Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Shenzhen Huawei Anjiexin Electricity Co., Ltd
+          notes: "Affiliated Entity:  Shenzhen Huawei Anjiexin Electricity Co., Ltd."
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution -  Second Design Department"
+        properties:
+          name: China Aerospace Science and Industry Corporation Second Academy
+          related: Second Design Department
+          notes: "Subordinate Institution -  Second Design Department"
+      - match: "China Aerospace Science and Industry Corporation Second Academy.  Subordinate Institution - 23rd Research Institute"
+        properties:
+          name: China Aerospace Science and Industry Corporation Second Academy
+          related: 23rd Research Institute
+          notes: "Subordinate Institution - 23rd Research Institute"
path: datasets/us/trade_csl/us_trade_csl.yml
user: login: leonhandreke
body: I don't think putting this in the notes adds any value here, let's try to put it in `original_value` somewhere? Or do you think it adds value here?
created_at: 2025-05-14T13:49:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -110,10 +140,15 @@ def parse_result(context: Context, result: Dict[str, Any]):
     name_with_information_res = context.lookup("name_with_information", name)
     if name_with_information_res is not None:
         entity.add("name", name_with_information_res.properties["name"])
path: datasets/us/trade_csl/crawler.py
user: login: leonhandreke
body: can we add the `original_value` here?
created_at: 2025-05-14T13:50:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -100,6 +114,277 @@ lookups:
         properties:
           name: Ministry of Defence of the Russian Federation
           notes: Includes the Armed Forces of Russia and all operating units wherever located.  This includes the national armed services (army, navy, marine, air force, or coast guard), as well as the national guard and national police, government intelligence or reconnaissance organizations of the Russian Federation.  All address located in Russia.
+      - match: 'Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Beijing Huawei Longshine Information Technology Co., Ltd.'
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Beijing Huawei Longshine Information Technology Co., Ltd
+          notes: 'Affiliated Entity:  Beijing Huawei Longshine Information Technology Co., Ltd.'
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity: Hangzhou New Longshine Information Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou New Longshine Information Technology Co., Ltd
+          notes: "Affiliated Entity: Hangzhou New Longshine Information Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Communication Technology Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Hangzhou Huawei Communication Technology Co., Ltd
+          notes: "Affiliated Entity:  Hangzhou Huawei Communication Technology Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Huawei Digital Technologies (Suzhou) Co., Ltd."
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
+          related: Huawei Digital Technologies (Suzhou) Co., Ltd
+          notes: "Affiliated Entity:  Huawei Digital Technologies (Suzhou) Co., Ltd."
+      - match: "Huawei Technologies Co., Ltd. (Huawei).  Affiliated Entity:  Hangzhou Huawei Enterprises"
+        properties:
+          name: Huawei Technologies Co., Ltd. (Huawei)
path: datasets/us/trade_csl/us_trade_csl.yml
user: login: leonhandreke
body: I wonder whether it should actually be the other way round: "Hangzhou Huawei Enterprises" is the entity being targeted by this entry, and they are related to "Huawei Technologies Co., Ltd. (Huawei)". What do you think?
created_at: 2025-05-14T13:54:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,40 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+#     Programs falling under the 'is_ofac=TRUE' check:
path: datasets/us/trade_csl/crawler.py
user: login: leonhandreke
body: I see the `is_ofac` check is somewhere below, maybe move that documentation there?
created_at: 2025-05-14T13:56:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,40 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+#     Programs falling under the 'is_ofac=TRUE' check:
path: datasets/us/trade_csl/crawler.py
user: login: nvmbrasserie
body: I think it's cleaner to keep it at the top as an overview of the programs that matter to us in this crawler. I rephrased it so that it doesn't rely only on the `is_ofac` flag.
created_at: 2025-05-14T16:21:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -103,17 +176,32 @@
     name = name.replace("and any successor, sub-unit, or subsidiary thereof", "")
 
     # Handle messed-up unicode in BIS names
-    if "bis.doc.gov" in result.get("source_list_url", ""):
+    if "bis.doc.gov" in list_entry.get("source_list_url", ""):
path: datasets/us/trade_csl/crawler.py
user: login: github-advanced-security[bot]
body: ## Incomplete URL substring sanitization

The string [bis.doc.gov](1) may be at an arbitrary position in the sanitized URL.

[Show more details](https://github.com/opensanctions/opensanctions/security/code-scanning/22)
created_at: 2025-05-15T13:06:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,40 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+#     Programs falling under the 'is_ofac=TRUE' check:
path: datasets/us/trade_csl/crawler.py
user: login: leonhandreke
body: I just looked into what this actually means. IIUC, this means that we emit these entities with the `ofac-<entity_number>` ID so that they match without a merge? Let's add a sentence about this here to explain this speciality.
created_at: 2025-05-15T13:06:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,83 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+#     Programs that we emit in this crawler (is_ofac=False):
+#     "Nonproliferation Sanctions (ISN) - State Department",
+#     "ITAR Debarred (DTC) - State Department",
+#     "Unverified List (UVL) - Bureau of Industry and Security",
+#     "Entity List (EL) - Bureau of Industry and Security",
+#     "Denied Persons List (DPL) - Bureau of Industry and Security",
+#     "Military End User (MEU) List - Bureau of Industry and Security",
+
+#     Programs that we primarily emit in OFAC (is_ofac=True):
+#     "Capta List (CAP) - Treasury Department",
+#     "Palestinian Legislative Council List (PLC) - Treasury Department",
+#     "Foreign Sanctions Evaders (FSE) - Treasury Department",
+#     "Non-SDN Chinese Military-Industrial Complex Companies List (CMIC) - Treasury Department",
+#     "Non-SDN Menu-Based Sanctions List (NS-MBS List) - Treasury Department",
+#     "Specially Designated Nationals (SDN) - Treasury Department",
+#     "Sectoral Sanctions Identifications List (SSI) - Treasury Department",
 
 REGEX_AUTHORITY_ID_SEP = re.compile(r"(\d+ F\.?R\.?)")
 
 
+def emit_relationship(
+    context: Context,
+    entity_id: str,
+    *,
+    related_name: str,
+    list_entry: Dict[str, Any],
+    source_program: str
+):
+    related_entity = context.make("LegalEntity")
+    related_entity.id = context.make_id(related_name)
+    related_entity.add("name", related_name)
+    context.emit(related_entity)
+
+    make_and_emit_sanction(
path: datasets/us/trade_csl/crawler.py
user: login: leonhandreke
body: Do we need to emit a sanction here? If I understand this correctly, this is mostly "Huawei Inc. Affiliated Entity: Special Lab Ltd.". This sanction means that we not only sanction Special Lab Ltd (which happens in the main function) but also "Huawei Inc." Is this what we want, conceptually? Don't they have their own "you are sanctioned" list entry?
created_at: 2025-05-15T13:09:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,83 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+#     Programs that we emit in this crawler (is_ofac=False):
+#     "Nonproliferation Sanctions (ISN) - State Department",
+#     "ITAR Debarred (DTC) - State Department",
+#     "Unverified List (UVL) - Bureau of Industry and Security",
+#     "Entity List (EL) - Bureau of Industry and Security",
+#     "Denied Persons List (DPL) - Bureau of Industry and Security",
+#     "Military End User (MEU) List - Bureau of Industry and Security",
+
+#     Programs that we primarily emit in OFAC (is_ofac=True):
+#     "Capta List (CAP) - Treasury Department",
+#     "Palestinian Legislative Council List (PLC) - Treasury Department",
+#     "Foreign Sanctions Evaders (FSE) - Treasury Department",
+#     "Non-SDN Chinese Military-Industrial Complex Companies List (CMIC) - Treasury Department",
+#     "Non-SDN Menu-Based Sanctions List (NS-MBS List) - Treasury Department",
+#     "Specially Designated Nationals (SDN) - Treasury Department",
+#     "Sectoral Sanctions Identifications List (SSI) - Treasury Department",
 
 REGEX_AUTHORITY_ID_SEP = re.compile(r"(\d+ F\.?R\.?)")
 
 
+def emit_relationship(
+    context: Context,
+    entity_id: str,
+    *,
+    related_name: str,
+    list_entry: Dict[str, Any],
+    source_program: str
+):
+    related_entity = context.make("LegalEntity")
+    related_entity.id = context.make_id(related_name)
+    related_entity.add("name", related_name)
+    context.emit(related_entity)
+
+    make_and_emit_sanction(
path: datasets/us/trade_csl/crawler.py
user: login: nvmbrasserie
body: I'm not sure about it. I think it's better to be more thorough than not. That's why I factored it out to the separate function so that we don't accidentally skip the 'parent' company if it's not on the main list
created_at: 2025-05-15T14:24:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,83 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+#     Programs that we emit in this crawler (is_ofac=False):
+#     "Nonproliferation Sanctions (ISN) - State Department",
+#     "ITAR Debarred (DTC) - State Department",
+#     "Unverified List (UVL) - Bureau of Industry and Security",
+#     "Entity List (EL) - Bureau of Industry and Security",
+#     "Denied Persons List (DPL) - Bureau of Industry and Security",
+#     "Military End User (MEU) List - Bureau of Industry and Security",
+
+#     Programs that we primarily emit in OFAC (is_ofac=True):
+#     "Capta List (CAP) - Treasury Department",
+#     "Palestinian Legislative Council List (PLC) - Treasury Department",
+#     "Foreign Sanctions Evaders (FSE) - Treasury Department",
+#     "Non-SDN Chinese Military-Industrial Complex Companies List (CMIC) - Treasury Department",
+#     "Non-SDN Menu-Based Sanctions List (NS-MBS List) - Treasury Department",
+#     "Specially Designated Nationals (SDN) - Treasury Department",
+#     "Sectoral Sanctions Identifications List (SSI) - Treasury Department",
 
 REGEX_AUTHORITY_ID_SEP = re.compile(r"(\d+ F\.?R\.?)")
 
 
+def emit_relationship(
+    context: Context,
+    entity_id: str,
+    *,
+    related_name: str,
+    list_entry: Dict[str, Any],
+    source_program: str
+):
+    related_entity = context.make("LegalEntity")
+    related_entity.id = context.make_id(related_name)
+    related_entity.add("name", related_name)
+    context.emit(related_entity)
+
+    make_and_emit_sanction(
path: datasets/us/trade_csl/crawler.py
user: login: leonhandreke
body: I'm a bit worried that after we merge these into Huawei Inc., we'll have 12 Sanctions objects on Huawei that we then need to dedupe.
created_at: 2025-05-15T14:49:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,83 @@
 from zavod import Context, Entity
 from zavod import helpers as h
 
+#     Programs that we emit in this crawler (is_ofac=False):
+#     "Nonproliferation Sanctions (ISN) - State Department",
+#     "ITAR Debarred (DTC) - State Department",
+#     "Unverified List (UVL) - Bureau of Industry and Security",
+#     "Entity List (EL) - Bureau of Industry and Security",
+#     "Denied Persons List (DPL) - Bureau of Industry and Security",
+#     "Military End User (MEU) List - Bureau of Industry and Security",
+
+#     Programs that we primarily emit in OFAC (is_ofac=True):
+#     "Capta List (CAP) - Treasury Department",
+#     "Palestinian Legislative Council List (PLC) - Treasury Department",
+#     "Foreign Sanctions Evaders (FSE) - Treasury Department",
+#     "Non-SDN Chinese Military-Industrial Complex Companies List (CMIC) - Treasury Department",
+#     "Non-SDN Menu-Based Sanctions List (NS-MBS List) - Treasury Department",
+#     "Specially Designated Nationals (SDN) - Treasury Department",
+#     "Sectoral Sanctions Identifications List (SSI) - Treasury Department",
 
 REGEX_AUTHORITY_ID_SEP = re.compile(r"(\d+ F\.?R\.?)")
 
 
+def emit_relationship(
+    context: Context,
+    entity_id: str,
+    *,
+    related_name: str,
+    list_entry: Dict[str, Any],
+    source_program: str
+):
+    related_entity = context.make("LegalEntity")
+    related_entity.id = context.make_id(related_name)
+    related_entity.add("name", related_name)
+    context.emit(related_entity)
+
+    make_and_emit_sanction(
path: datasets/us/trade_csl/crawler.py
user: login: leonhandreke
body: Acutally, looking at https://www.opensanctions.org/statements/NK-P3xHZasb3VZasvJLDwiGHC/?prop=name, it seems like they (always?) have the parent company with the same name. 

I guess we could build a dict of name → entity ID where we then look up the parent... but that seems a bit overkill, we can let the dedupe process take care of it I guess.
created_at: 2025-05-15T14:54:49Z
author_association: CONTRIBUTOR

PR comments:
user: login: nvmbrasserie
created_at: 2025-05-13T22:27:46Z
body: most programs are not found: `[warning  ] Program with key 'EU-AFG' not found.`. Taking a closer look
author_association: CONTRIBUTOR
user: login: leonhandreke
created_at: 2025-05-15T13:11:26Z
body: I pushed a little commit with some renames, type fixes, etc, hope that's alright.

Only one question remaining to me about whether to add a sanction object for both sides of the relationship. Otherwise, looks good!
author_association: CONTRIBUTOR