from __future__ import annotations import re from typing import Any from ingestion.common.governance import validate_classifications from ingestion.common.models import Table def classify_table(table: Table, rules: dict[str, Any]) -> list[str]: """Classify a table from source-declared rules. ``rules`` is the source's classification config (a baseline list applied to every table, name/column regex patterns, and table-name rules). The engine carries no source-specific defaults — an empty config yields no classifications. This lives in ``common`` because every extract family classifies the same way; only the *rules* are source-specific (see the config-driven structure principle). Every emitted label must be in the fixed ADR-0011 governance set; an unknown label (typo or invented classification) is rejected here rather than silently flowing into governance metadata. """ names = " ".join([table.name] + [column.name for column in table.columns]) classes = set(rules.get("baseline", [])) for rule in rules.get("name_rules", []): prefix = rule.get("name_prefix") if prefix and table.name.startswith(prefix): classes.add(rule["add"]) for classification, pattern in rules.get("patterns", {}).items(): if re.search(pattern, names, re.IGNORECASE): classes.add(classification) return validate_classifications(sorted(classes), context=f"table {table.name}")