ISNI: the check character is never verified, and the link is written with spaces in it #637

Closed
opened 2026-10-01 10:48:33 +00:00 by tiagoagueda · 1 comment
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, comparing the ISNI scheme with the ORCID scheme beside it.

Checked again on 2026-10-01 against main at 0a5cad587: still present. plugins/identifiers/schemes.py and the three tests are unchanged; Scheme.url_for is now at core/identifiers.py:96-98.

An ISNI ends in a check character computed with ISO 7064 MOD 11-2, the same algorithm as ORCID (an ORCID is an ISNI from a reserved block). The ORCID scheme verifies it; the ISNI scheme does not, and it builds its link from the display form with the spaces left in.

  • Where:
    • plugins/identifiers/schemes.py:157-166: the ISNI scheme has tidy=_regroup(16, " "), link="https://isni.org/isni/{value}" and no checksum=.
    • plugins/identifiers/schemes.py:95-107 (orcid_checks_out): the check that exists, which strips hyphens only.
    • core/identifiers.py:91-93 (Scheme.url_for): template.format(value=value), with no encoding and no compact form.
    • tests/test_identifier_registry.py:110-116, :167 and tests/test_person_identifiers.py:75: the tests use 0000 0001 2281 9550 and 0000 0001 2281 9553, neither of which has a valid check character, and assert row.url == "https://isni.org/isni/0000 0001 2281 9550".
  • What happens: an ISNI typed with one digit wrong or two swapped is saved as valid, on a person and on a company; the same mistake in an ORCID is refused. Run against the snapshot: orcid_checks_out("0000-0001-2281-955X") is true for the scheme's own example, and clean("isni", …) accepted 0000 0001 2281 9551, 0000 0001 2281 9559 and 0000 0001 2182 955X. Each came back with a link such as https://isni.org/isni/0000 0001 2281 9551. ISNI's own address form is the sixteen characters run together (https://isni.org/isni/000000012281955X). Not checked: whether isni.org happens to resolve the spaced form.
  • Why it matters: the module says a scheme "checks the digits where it has some" and that a checksum is why no lookup is needed. For ISNI a typo is kept, and the link on the company page is not the identifier's address.
  • Fix: make the MOD 11-2 check accept either separator (strip everything but digits and X before computing) and give the ISNI scheme checksum= with a message of its own. Build the ISNI link from the value without spaces: a per-scheme function for the link's value, or a flag that makes Scheme.url_for format the compacted value. Replace the ISNIs in the three tests above with ones that check out. An ISNI already stored with a wrong check character will be refused the next time its form is saved, which is the intended result; say so in the release notes.

Done when

  • Tests in tests/test_identifier_registry.py: an ISNI with a wrong check character is refused on a person and on a company, the scheme's example is accepted, and url_for returns an address with no space. The first and the last fail today.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, comparing the ISNI scheme with the ORCID scheme beside it. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. `plugins/identifiers/schemes.py` and the three tests are unchanged; `Scheme.url_for` is now at `core/identifiers.py:96-98`. An ISNI ends in a check character computed with ISO 7064 MOD 11-2, the same algorithm as ORCID (an ORCID is an ISNI from a reserved block). The ORCID scheme verifies it; the ISNI scheme does not, and it builds its link from the display form with the spaces left in. - **Where:** - `plugins/identifiers/schemes.py:157-166`: the ISNI scheme has `tidy=_regroup(16, " ")`, `link="https://isni.org/isni/{value}"` and no `checksum=`. - `plugins/identifiers/schemes.py:95-107` (`orcid_checks_out`): the check that exists, which strips hyphens only. - `core/identifiers.py:91-93` (`Scheme.url_for`): `template.format(value=value)`, with no encoding and no compact form. - `tests/test_identifier_registry.py:110-116`, `:167` and `tests/test_person_identifiers.py:75`: the tests use `0000 0001 2281 9550` and `0000 0001 2281 9553`, neither of which has a valid check character, and assert `row.url == "https://isni.org/isni/0000 0001 2281 9550"`. - **What happens:** an ISNI typed with one digit wrong or two swapped is saved as valid, on a person and on a company; the same mistake in an ORCID is refused. Run against the snapshot: `orcid_checks_out("0000-0001-2281-955X")` is true for the scheme's own example, and `clean("isni", …)` accepted `0000 0001 2281 9551`, `0000 0001 2281 9559` and `0000 0001 2182 955X`. Each came back with a link such as `https://isni.org/isni/0000 0001 2281 9551`. ISNI's own address form is the sixteen characters run together (`https://isni.org/isni/000000012281955X`). Not checked: whether isni.org happens to resolve the spaced form. - **Why it matters:** the module says a scheme "checks the digits where it has some" and that a checksum is why no lookup is needed. For ISNI a typo is kept, and the link on the company page is not the identifier's address. - **Fix:** make the MOD 11-2 check accept either separator (strip everything but digits and `X` before computing) and give the ISNI scheme `checksum=` with a message of its own. Build the ISNI link from the value without spaces: a per-scheme function for the link's value, or a flag that makes `Scheme.url_for` format the compacted value. Replace the ISNIs in the three tests above with ones that check out. An ISNI already stored with a wrong check character will be refused the next time its form is saved, which is the intended result; say so in the release notes. ## Done when - Tests in `tests/test_identifier_registry.py`: an ISNI with a wrong check character is refused on a person and on a company, the scheme's example is accepted, and `url_for` returns an address with no space. The first and the last fail today.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:48:33 +00:00
Author
Owner

The maintainer's list of 2026-10-02 confirms the link half of this issue: “ISNI url is wrong. Do not add spaces to it.”

Still true on main at f09b6010b: the link is built from the display form (src/postulo/plugins/identifiers/schemes.py:162-165). The one assertion that pins the spaced address is tests/test_identifier_registry.py:116; it changes with the fix.

#675 builds on the check-character half: its offline rule reports a stored ISNI that fails the check once that lands.

As this is a one-line, user-visible bug, could the milestone move from 0.6.0 to 0.5.0? This is a question; nothing has been moved.

From the list of improvements of 2026-10-02.

The maintainer's list of 2026-10-02 confirms the link half of this issue: “ISNI url is wrong. Do not add spaces to it.” Still true on `main` at `f09b6010b`: the link is built from the display form (`src/postulo/plugins/identifiers/schemes.py:162-165`). The one assertion that pins the spaced address is `tests/test_identifier_registry.py:116`; it changes with the fix. #675 builds on the check-character half: its offline rule reports a stored ISNI that fails the check once that lands. As this is a one-line, user-visible bug, could the milestone move from 0.6.0 to 0.5.0? This is a question; nothing has been moved. From the list of improvements of 2026-10-02.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#637
No description provided.