aeat.adapters.outbound.aeat.sede._nif_iva_check module

Read-only AEAT NIF-IVA / VIES proxy browser driver.

Drives the public AEAT-hosted form servlet that proxies non-Spanish EU IVA-identifier validity queries to the European Commission’s VIES service. The driver navigates from the sede gestiones page (which issues the session cookies the form servlet requires) to the form servlet itself, fills the country-code + IVA-number form per declared NIF, scrapes the rendered validity verdict, and returns one observation per declared NIF.

The contract mirrors _renta_web_open: a sibling sede adapter exposing an async collection coroutine plus a synchronous wrapper that the registry oracle can call. Browser-session lifecycle, guarded navigation, form interaction, response parsing, and error mapping are implemented here.

The driver is intentionally read-only: the form mutates no AEAT-side state under any NIF, requires no clave-móvil session, and writes nothing to the autonomo’s filing history. The remote-state guard host-pinning suffix (agenciatributaria.gob.es) covers both the sede entry subdomain and the www1 form-servlet subdomain.

class SedeNifIvaCheckObservation(**data)[source]

Bases: _SedeCheckerModel

One observation emitted per declared NIF after live navigation.

verdict is the AEAT/VIES-rendered validity for that NIF: valid, invalid, or unknown when the response is structurally unanswerable (network error mid-query, etc.).

Parameters:
  • nif (str)

  • verdict (Literal['valid', 'invalid', 'unknown'])

  • raw_evidence_locator (str | None)

nif: str
verdict: Literal['valid', 'invalid', 'unknown']
raw_evidence_locator: str | None
class NifIvaCheckResult(**data)[source]

Bases: _SedeCheckerModel

Aggregate live-driver result across all declared NIFs for one browser pass.

Each entry in observations corresponds to one NIF submitted to the AEAT-hosted VIES proxy form. An empty tuple signals that no NIFs were queried (caller-side guard: expected was empty before the driver ran).

Parameters:

observations (tuple[SedeNifIvaCheckObservation, ...])

observations: tuple[SedeNifIvaCheckObservation, ...]
class NifIvaCheckSedeDriver(*, settings=None)[source]

Bases: object

Live AEAT NIF-IVA driver backed by the central BrowserSession surface.

The driver follows the sequence the oracle’s planned_operations enumerates: GET sede entry, GET form servlet, open the form, per-NIF check, discard the session.

The driver follows the read-only public VIES proxy flow and converts the rendered AEAT response text into registry parity observations.

Parameters:

settings (Settings | None)

property mode: Literal['live']

Driver execution mode — always "live" for this adapter.

planned_operations(payload, *, expected)[source]

Return the ordered list of remote operations this driver will perform.

The sequence is fixed: one HTTP GET to the sede (AEAT electronic office) gestiones entry page, one HTTP GET to the VIES proxy form servlet, one browser action to open the form, one check-nif-<NIF> browser action per NIF in expected (sorted alphabetically), and finally a discard-session action. The sequence is used by the remote-state guard pre-flight to validate that all planned operations are within the driver’s declared RemoteStateGuardPolicy.

Parameters:
  • payload (bytes) – Raw oracle payload bytes. Not read by this driver; the argument exists to satisfy the oracle driver protocol.

  • expected (Mapping[str, object]) – Mapping keyed by NIF (Spanish or EU IVA identifier) whose VIES validity is to be checked. At least one entry is required.

Return type:

tuple[RemoteOperation, ...]

Returns:

An immutable tuple of RemoteOperation records in execution order.

Raises:

RegistryValidationError – When expected is empty.

collect(payload, *, expected, timeout_ms=30000)[source]

Synchronous wrapper around collect_async() for oracle callers.

Runs the full browser-drive sequence inside asyncio.run and translates SedeError, SiteHealthError, and BrowserError into RegistryValidationError so the oracle protocol sees a single typed failure shape.

Parameters:
  • payload (bytes) – Raw oracle payload bytes. Not read; present for protocol compatibility.

  • expected (Mapping[str, object]) – Mapping keyed by NIF whose VIES validity is to be checked.

  • timeout_ms (int) – Per-operation Playwright timeout in milliseconds. Defaults to DEFAULT_NIF_IVA_TIMEOUT_MS.

Return type:

NifIvaCheckResult

Returns:

A NifIvaCheckResult with one observation per NIF.

Raises:

RegistryValidationError – On browser navigation, sede, or health failures.

collect_observation(payload, *, expected)[source]

Collect results and return a typed AeatNifIvaObservation.

Calls collect() and projects the observations into the AeatNifIvaObservation shape the registry oracle expects: a values mapping of NIF -> verdict string and a single raw_evidence_locator (the first non-None URL from the observation set).

Parameters:
  • payload (bytes) – Raw oracle payload bytes. Not read; present for protocol compatibility.

  • expected (Mapping[str, object]) – Mapping keyed by NIF whose VIES validity is to be checked.

Return type:

AeatNifIvaObservation

Returns:

An AeatNifIvaObservation with the collected verdicts and evidence locator.

async collect_async(payload, *, expected, timeout_ms=30000)[source]

Async entry point that delegates to collect_nif_iva_check_observations().

Parameters:
  • payload (bytes) – Raw oracle payload bytes. Not read; present for protocol compatibility.

  • expected (Mapping[str, object]) – Mapping keyed by NIF whose VIES validity is to be checked.

  • timeout_ms (int) – Per-operation Playwright timeout in milliseconds. Defaults to DEFAULT_NIF_IVA_TIMEOUT_MS.

Return type:

NifIvaCheckResult

Returns:

A NifIvaCheckResult with one observation per NIF.

async collect_nif_iva_check_observations(payload, *, expected, settings=None, timeout_ms=30000, browser_session_factory=None)[source]

Open the NIF-IVA form, query each declared NIF, scrape verdicts into a NifIvaCheckResult.

The function navigates the AEAT sede gestiones entry, follows through to the form servlet (which the entry’s session cookies authorise), iterates the declared NIFs alphabetically, and returns one observation per NIF.

Return type:

NifIvaCheckResult

Parameters:
is_aeat_auth_gate_redirect(current_url)[source]

Return True when the live page URL points at AEAT’s 4033 / 403 error page.

AEAT redirects unauthenticated requests to the form servlet to its centralized 4033 auth-gate path (HTTP 200 OK landing on a 403-titled page). The detector keys off the configured path and host suffix so it stays specific to that exact failure mode. Other AEAT errors are intentionally not matched.

Return type:

bool

Parameters:

current_url (str)

extract_verdict_from_response_text(body_text)[source]

Parse the AEAT-rendered verdict from response body text.

AEAT renders the VIES response in Spanish. The parser is conservative: explicit negative verdicts win over generic positive words such as válido so phrases like no válido cannot be misclassified.

Return type:

Literal['valid', 'invalid', 'unknown']

Parameters:

body_text (str)