validate_identity_document (Au10tix)

Business purpose: verify that a government ID uploaded to Payability is authentic, unexpired, of acceptable quality, and that its name matches the supplier owner on record.

Au10tix / Entrust coexistence. Entrust Identity Verification (Onfido) is the eventual replacement for Au10tix identity-document validation. During the rollout both vendors run under the same validate_identity_document process, so the GSI, dedup logic and admin reporting keep working unchanged. ToolType.get_by_process_name therefore still maps validate_identity_document to AU10TIX; the Entrust code paths reference ToolType.ENTRUST directly. Do not switch that mapping until Au10tix is fully retired.

Step 1 — au10tix/request_identity_document_validation

InitialTask, runs in the Web API.

Input

supplier_key, person_id, document_id

Allowed sources

INTERNAL, SUPPLIER_DASHBOARD

Input validator

none

Output

{correlation_id}

Side effects, in order:

  1. TaskExecutionTable.save — status=pending, process_name=validate_identity_document, input = the three fields, plus source and requested_by.

  2. ToolTable.update — AU10TIX → PENDING with this correlation_id.

  3. B2BTaskManager.start_swf — workflow id Automatic UW Tool - {supplier_key} - Validate identity document., carrying the handle task name and the full input (this is the only process that passes real fields rather than just the correlation id).

input_body={
    'platform': 'automatic-uw',
    'task_name': 'au10tix/handle_identity_document_validation_response',
    'task_correlation_id': self.correlation_id,
    'task_input': {
        'document_id': input_.document_id,
        'supplier_key': input_.supplier_key,
        'person_id': input_.person_id
    }
}

Because the workflow id is deterministic per supplier, a second concurrent request for the same supplier surfaces CannotRunWorkflow ("Task already running") as a 400.

Step 2 — au10tix/handle_identity_document_validation_response

GenericTask, runs on the worker.

Flow

  1. PYBDocuments.get_document(document_id) — download the uploaded image bytes (DocumentNotFound on a 404).

  2. POST {AU10TIX_API_URL}/IdentityDocuments/BeginProcessingRequest — multipart upload of requestData (the process_identity_document.json template) and documentImage_Page0; returns a RequestId.

  3. Poll POST /IdentityDocuments/CheckReadinessOfResults with {"idList": [request_id]} until the first element is true — 10 attempts, 5 s apart.

  4. GET /IdentityDocuments/Results/{request_id} — accepted only when CompletionStatus == 'Ok'; anything else raises and is retried (10 attempts, 5 s, also forcing a retry on AttributeError).

  5. Archive the raw result JSON to S3.

  6. Compare the document name against the supplier owner from the Payability internal API.

Verdict rules

Derived in __prepare_final_status_data from the Au10tix payload:

Final-status field VERIFIED when

DocumentAuthenticity

validation_result['DocumentAuthenticity'] == 'Authentic'

IsDocumentExpired

ProcessingResult['IsDocumentExpired'] is False

OverallQuality

ProcessingResult['OverallQuality'] == 'Acceptable'

IDNameMatch

the document name fuzzy-matches the owner name

Name matching: DocumentData2.FirstName/LastName are used when both are present, otherwise FullName is split on spaces (first token, last token). The owner comes from PayabilityInternalAPI.get_supplier_info(detailed=True) matched on loginKey == person_id; their firstName is stripped of middle names. Comparison is utils.string_utils.is_full_name_match — accent-folded thefuzz.token_set_ratio at 100. A 400/404 from the internal API yields NOT_VERIFIED rather than a task failure; other HTTP errors propagate.

The tool becomes VERIFIED only when no field is NOT_VERIFIED.

Side effects

  • S3: au10tix/identity_document_validation/supplier_key=<sk>/person_id=<pid>/<timestamp>.json.

  • TaskExecutionTable → processed, output = {raw_result_s3_path}, additional_data.full_result_s3_path.

  • FinalStatusTable.save — the four fields above.

  • ToolTable.update — AU10TIX → VERIFIED / NOT_VERIFIED.

  • EventBridge: ProcessFinishedEvent with DetailType = VALIDATE_IDENTITY_DOCUMENT.

  • Output: {raw_result_s3_path}.

Failure path

task_failure_handling marks the task failed with {'error': str(e)} and sets the AU10TIX tool to ERROR (reading the supplier and person back off the persisted row). This task does not implement purge(), so DELETE /tasks/result deletes nothing for it.

Source files

  • task/au10tix/request_identity_document_validation/

  • task/au10tix/handle_identity_document_validation_response/

  • components/au10tix/client.py, components/au10tix/request_template/

  • Tests: development/unit_tests/task_/au10tix/**