"""Entity matching (section 14): decides whether an incoming provider record corresponds to an existing Aurora entity. Core 0.1 policy — deliberately conservative: - An exact external-ID match (this provider has already been linked to an Aurora entity of this type) is the only case treated as MatchConfidence EXACT and reused. - Anything else creates a *new* Aurora entity (MatchConfidence NEW) rather than guessing via fuzzy title matching. Silently merging two providers' differing descriptions of "the same" title is exactly what section 14 prohibits. Fuzzy candidate matching (title + year similarity, surfaced for human review) is genuinely deferred — see docs/architecture.md — until Core has an admin review workflow to act on AMBIGUOUS matches. """ from __future__ import annotations import uuid from sqlalchemy.ext.asyncio import AsyncSession from app.models.enums import MatchConfidence from app.repositories.reference_repository import find_entity_by_external_id async def match_entity( session: AsyncSession, *, provider_id: uuid.UUID, entity_type: str, external_id: str ) -> tuple[uuid.UUID | None, MatchConfidence]: """Return (existing_aurora_id_or_None, confidence).""" existing = await find_entity_by_external_id(session, provider_id, entity_type, external_id) if existing is not None: return existing, MatchConfidence.EXACT return None, MatchConfidence.NEW