validate_personal_information (KYC)

Business purpose: the KYC check. Confirm that the PII a supplier owner submitted (name, date of birth, SSN, address) matches Thomson Reuters records, and tell the rest of the platform which individual fields did not match.

Step 1 — thomson_reuters/request_personal_information_validation

InitialTask, runs in the Web API.

Input

supplier_key, person_id, first_name, last_name, birth_day, birth_month, birth_year, ssn, street, city, state, zip_code

Allowed sources

INTERNAL, SUPPLIER_DASHBOARD

Input validator

yes

Output

{correlation_id}

Side effects: save the row (pending), set THOMSON_REUTERS_CLEAR_ID → PENDING, validate, then start SWF with task_input = {correlation_id} only — the handle step reloads the PII from DynamoDB rather than putting it on the workflow payload. Workflow id: Automatic UW Tool - {supplier_key} - Validate personal informations.

Input validation

input_validator.py raises ValidationError (a TaskExecutionError, so the API answers 400 with {"incorrect_fields": {…​}}):

Field Rule

birth_day

^(0[1-9]|1[0-9]|2[0-9]|3[0-1])$ — two digits, DD.

birth_month

^(0[1-9]|1[012])$ — two digits, MM.

state

Exactly two uppercase letters.

street

Must start with <alphanumeric> <alphanumeric> (house number + street name, PO box, rural route or highway contract route) and must not contain ’ or ".

first_name, last_name

A-Z a-z 0-9, space and ~`@#$%^()_-+={}|[]:;"'<>?,./ only.

ssn

000-00-0000.

supplier_key, person_id

Required.

Note that the task row and the PENDING tool status are written before validation runs, so a rejected input still leaves a failed task and an ERROR tool behind (the failure handler runs on the ValidationError).

Step 2 — thomson_reuters/handle_personal_information_validation_response

GenericTask + PurgableS3ObjectProducer, runs on the worker. Input: {correlation_id}.

Flow

  1. Reload the row: TaskExecutionTable.get(correlation_id) → input (the PII).

  2. Fill clear_id_confirm_person_search.xml with the permissible-purpose block and the criteria, and POST {THOMSON_REUTERS_API_URL}/v2/eidvperson/searchResults.

  3. Read GroupCount from the ns*:EIDVPersonResults node (the namespace prefix is discovered at runtime by find_key_in_tr_response). 0 or missing → ResultNotFound.

  4. Read Uri, then GET it to fetch the actual search result. A missing Uri → MalformedResponse.

  5. Archive the result to S3.

  6. Extract the per-field summary from …EIDVPersonSearchResults.EIDVPersonSearchResult.PersonEntities.PersonEntity.Summary.

Any HTTPError on either call emits ThomsonReutersNotWorkingEvent (so the platform can let the customer proceed without the check) and then fails the task.

Match scoring

Each summary field carries a @matchtype:

@matchtype Treated as

MATCH

matched → MATCH in the final status

PARTIAL MATCH

not matched → NO_MATCH

NO MATCH

not matched → NO_MATCH

  • All fields matched → ThomsonReutersDataMatchEvent.

  • One or more mismatched → ThomsonReutersDataNotMatchEvent carrying the mismatched field names in data_points.

  • The tool is VERIFIED only when every field matched.

  • @matchscore is stripped from the output before it is persisted.

Side effects

  • S3: thomson_reuters/kyc/supplier_key=<sk>/person_id=<pid>/<timestamp>.person_search.json.

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

  • FinalStatusTable.save — one key per field with a @matchtype, valued MATCH / NO_MATCH.

  • ToolTable.update — THOMSON_REUTERS_CLEAR_ID → VERIFIED / NOT_VERIFIED.

  • EventBridge: the match/mismatch/not-working event above plus ProcessFinishedEvent.

  • Output: {match_result} — field → {"@matchtype": "MATCH" | "PARTIAL MATCH" | "NO MATCH"}.

Data deletion

purge(supplier_key, person_id, s3_object_purger) deletes the archived S3 object of every processed execution for that person and marks those rows purged. Driven by DELETE /tasks/result.

Result masking

GET /tasks/result?detailed=true masks the CLEAR ID payload for callers who lack DEV/FINANCE/REST_UW_ACCESS: everything in NormalizedCriteria and in each SearchRecord except FirstName/LastName is replaced with **. See api/tasks.adoc#get-task-result.

Overridable fields

PUT /tasks/{correlation_id}/final_statuses accepts City, FirstName, LastName, SSN, State, StreetName, StreetNumber, ZipCode, BirthDate, MiddleName, PhoneNumber with values MATCH, NO_MATCH or PENDING, and requires every key that the task’s match_result reported.

Source files

  • task/thomson_reuters/request_personal_information_validation/

  • task/thomson_reuters/handle_personal_information_validation_response/

  • components/thomson_reuters/client.py, components/thomson_reuters/request_template/clear_id_confirm_person_search.xml

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