# scripts

## CN-CNY bank code dataset

`build_cn_cny_bank_codes.py` builds the China lookup dataset,
`static/products/payments-direct-2/data-requirements/china-cny-ripple-bank-codes.json`.

The CN-CNY corridor was withdrawn from v2026.03, so that dataset is not
currently in the repo and the Bank Codes utility no longer reads it. This
script is kept to regenerate it if the corridor returns.

```bash
python3 scripts/build_cn_cny_bank_codes.py          # dry run, prints counts
python3 scripts/build_cn_cny_bank_codes.py --write  # write the JSON
python3 scripts/build_cn_cny_bank_codes.py --check  # verify, write nothing
```

Source of truth is the `ripple-bank-codes` repo, read from a sibling checkout.
Run this after any CN/CNY change there, otherwise the published lookup drifts
from the master.

`--check` re-derives the dataset and compares it to the published JSON, exiting
non-zero if they disagree. It reports the difference per bank code rather than
as a line diff, since a line diff across 3,437 rows buries the change, and it
distinguishes a genuine content difference from a row-order or formatting one.

The CN master carries no Chinese bank names, so the script reconstructs them by
joining the Hanshan and LianLian partner mappings. Its own header documents that
join and the English-name fallback, which should match nothing; the script
prints the fallback count so a regression is visible.

## Corridor data requirements pages

`generate_corridor_pages.py` builds the six v2026.03 African corridor pages
(GH, NG, RW, UG, ZA, ZM) under
`products/payments-direct-2/@v2026.03/api-docs/integration-resources/emea/`.
`corridor_page_sources.py` holds the source readers and the Markdoc table
helper.

```bash
python3 scripts/generate_corridor_pages.py            # regenerate all six
python3 scripts/generate_corridor_pages.py GH ZA      # regenerate some
python3 scripts/generate_corridor_pages.py --check     # verify, write nothing
```

Requires `pyyaml`. Paths resolve relative to the script, so it works from any
checkout of the RPD2 monorepo; set `RPD2_ROOT` if your checkout lives
elsewhere.

`--check` re-derives every page and diffs it against what is on disk, exiting
non-zero if they disagree. Run it after either source system changes to find
out whether the published pages have gone stale.

### Sources and precedence

| Content | Source of truth |
|  --- | --- |
| Identity requirements | PII v3 spec (`pii-service` `payment-participants.yaml`) |
| Financial instrument requirements | PII v3 spec |
| Transaction requirements, purpose codes | ADR (`data-requirements/adr`) |


Deviations between the two are expected, and PII v3 wins for identity and
financial instrument data. The ADR is the PII v2 view: its `Cdtr.*` and
`Dbtr.*` fields are ISO 20022 renderings of data that v3 carries inside the
identity and financialInstrument objects. PII v3 does not use the ISO field
names, so those fields are deliberately absent from the generated pages.
`Purp.Cd` is the only ADR field set on the payment itself, and v3 names it
`purposeCode`.

Nothing is inferred. A constraint absent from both sources is omitted rather
than guessed at, and the table helper refuses to emit a table with no rows, so
a broken lookup fails loudly instead of publishing an empty section.

Two tables in `generate_corridor_pages.py` are hand-maintained rather than read
from a source system, each with a comment citing where it came from:

- `LIVE_PARTNERS` restricts each corridor to the partners that actually serve
it. The ADR also carries files for partners that are not live, and without
this their requirements would leak into the published tables.
- `SUPPORTED_USE_CASES` records the commercially supported use cases. DRE
carries routing rules for all six use cases in every African corridor, but
routing config is not the same as a supported offering. ZA is C2B2C only.


### Known upstream defect

In every African corridor the ADR has the description, help text and
`maxLength` attached to the wrong one of `CdtrAgt.FinInstnId.Nm` and
`CdtrAgt.FinInstnId.Othr.Id`. The enum values prove the swap: `Othr.Id` carries
codes while `Nm` carries names. The lengths are wrong too, with `Nm` capped at
20 while 17 of its own 47 values run longer, up to 49 characters. Raised with
CPE 2026-09-09. This does not affect the generated pages, which take bank name
and bank code from the PII v3 financial instrument schema, but it will matter to
anything that reads those two ADR fields.