Skip to main content

ADR-0060: NaturalPerson AMLR fields — plural nationality, PEP classification/RCA, place_of_birth

Status: Accepted Date: 2026-06-16 Supersedes: none Superseded by: none Deciders: Adrian (Soft4U), Claude Opus 4.8

Decision context:

  • Latency: none (model fields) + one additive migration (add 2 columns + backfill on investigation_persons).
  • Dependency surface: no new packages. Touches the canonical person model, the InvestigationPerson ORM, migration 064, and the goAML mapper/xml_builder (backend + compliance-package copies).
  • Debuggability: legacy nationality/is_pep are kept and synced via validators, so existing readers are unaffected; the new fields are explicit and typed.
  • Reversibility: branch revert + alembic downgrade -1 (drops the 2 added columns). Models additive.
  • Blast radius: additive across ~12 files; the back-compat sync keeps .nationality/.is_pep consumers working untouched.
  • Alternative considered: drop the singular fields and migrate all readers (rejected — high churn/risk; synced legacy fields are zero-risk and removable later).

Context

Three structural defects in the operative person model: singular nationality (AMLR requires plural — multiple nationalities are risk-relevant); boolean PEP (cannot represent RCA — relatives & close associates, AMLR Art. 17); and missing place_of_birth (AMLR-new mandatory, hardcoded None in the goAML mapper). These are structural choices configuration cannot fix, independent of the still-draft field-level RTS (Art. 28(1)).

Decision

Additive change with back-compat sync:

  1. PepStatus: PepClassification enum (not_pep/pep/rca) + rca_of; legacy is_pep kept and synced (a validator resolves toward the stronger PEP signal — never suppresses a PEP).
  2. PersonSchema: nationalities: list[str] + place_of_birth; legacy nationality kept, synced to nationalities[0].
  3. ORM InvestigationPerson + migration 064: nationalities JSONB (backfilled from the singular column) + place_of_birth; legacy nationality column retained; PEP classification lives in the existing pep_status JSONB (no column change).
  4. goAML: birth_placeplace_of_birth (no longer hardcoded None); all three nationality1/2/3 carried per the goAML 5.0.2 XSD (model→IR→XML, both backend + compliance copies, XSD sequence order); RCA classification ⇒ is_pep true.

Consequences

Positive

  • Multi-nationality, RCA, and place_of_birth are representable end-to-end and flow into goAML filings.
  • Back-compat sync keeps every existing .nationality/.is_pep reader working with zero churn.

Negative

  • A second nationality representation (singular kept, synced) until a future cleanup drops it; one migration. PEP enum stored in the existing JSONB.

Neutral

  • IndividualProfile.additional_nationalities (KYC persona) is a separate model, untouched.

Alternatives Considered

Alternative 1: Drop nationality/is_pep outright and migrate all consumers

Rejected — 10+ .nationality and 6 .is_pep consumers; high churn and regression risk. Synced legacy fields are zero-risk and can be removed in a later dedicated cleanup.

Alternative 2: Carry only the primary nationality into goAML (nationality1)

Rejected — the goAML 5.0.2 XSD defines nationality1/2/3; truncating to one would drop a dual-national UBO's nationality from the FIU filing. The IR + mapper + xml_builder were extended to carry all three.