Demo data: seed_demo writes a contact address the form rejects, a Paris job translated to Lisbon and a real LEI #423

Closed
opened 2026-10-01 10:46:36 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading seed_demo and running it with its default seed on an in-memory database.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at jobs/models.py:627 (Contact.email) and jobs/forms.py:578 (ContactForm); seed_demo.py and the other locations are unchanged.

Three pieces of the data seed_demo writes are wrong. A contact gets an email address that Postulo's own contact form refuses, so the contact cannot be saved again until the address is rewritten. The one translated CV entry, there to show what a French CV prints, moves the job to another city. A fictional company carries a well-formed LEI that appears to belong to a real company, under a comment that calls the identifiers made up. The demo is how a newcomer judges Postulo, and its rows are written with objects.create and bulk_create, which validate nothing, so none of this is caught.

  • Where:
    • CONTACT_NAMES in core/management/commands/seed_demo.py:143-150; the contact creation in Command._seed at core/management/commands/seed_demo.py:556-566, with email=f"{contact_name.split()[0].lower()}@{website.removeprefix('https://')}"; Contact.email, an EmailField, at jobs/models.py:624; ContactForm at jobs/forms.py:581, whose Meta.fields include email.
    • The first Experience (Weyland-Yutani, location="Paris") at core/management/commands/seed_demo.py:385-398; the French Translation rows for experiences[0] at core/management/commands/seed_demo.py:757-774.
    • DEMO_IDENTIFIERS and its comment at core/management/commands/seed_demo.py:81-90; the LEI scheme's link and example at plugins/identifiers/schemes.py:196-197.
  • What happens:
    1. The address is the contact's first name, lowercased, at the company's website host. Two of the six names, João and Inês, are not ASCII, and Django's EmailValidator accepts only ASCII in the local part. With the default --seed 2026 the run creates four contacts: Anna Schmidt at Wonka Industries, Inês Carvalho at Aperture Science, Luc Moreau at Tyrell Corporation and Marie Dubois at Stark Industries. Inês's address is inês@aperture.example, and full_clean() on that row answers "Enter a valid email address." Someone trying the demo who opens that contact, changes its role or notes and saves it gets that error on a field they never touched. Other seeds can pick João, with the same result.
    2. The translation sets "location": "Lisbonne" on experiences[0], whose location is Paris. Lisbon is the city of experiences[1] (Massive Dynamic). The French summary, "J'ai maintenu en service ce dont les autres équipes dépendaient.", is not a translation of "Platform team for the logistics product." either. Rendered in French, the demo CV shows the Weyland-Yutani job in Lisbon, which is the opposite of what a translation feature should demonstrate.
    3. Initech's LEI, HWUPKR0MPOU8FGXBT394, passes the ISO 17442 mod-97 check. It is the value the LEI scheme uses as its own example, and it appears to be the LEI that GLEIF lists for Apple Inc. The company page links each identifier to its register (https://search.gleif.org/#/record/{value} for an LEI), so the fictional employer leads to a real company's record. The comment above DEMO_IDENTIFIERS says "The ids are made up, as the companies are", and Getting started in the wiki (Getting-started.md:129) says "Everything it creates is obviously invented".
  • Why it matters: the demo is meant to show the features working and to be plainly fictional. Its sample data fails Postulo's own validation on an ordinary edit, misrepresents the translation feature and points at a real company. tests/test_seed_demo.py never validates what the seeder creates, so this kind of drift goes unnoticed.
  • Fix:
    1. Build the local part from an ASCII fold of the first name, for example unicodedata.normalize("NFKD", first).encode("ascii", "ignore").decode().lower(), or give each CONTACT_NAMES entry an explicit address. Leave the displayed names unchanged.
    2. Translate the location as "Paris" and give a French summary that matches the English one, or move the translation onto the Lisbon entry.
    3. Replace Initech's LEI with a value that is clearly not real: LEI-shaped but failing the checksum if nothing validates seeded rows on display, or otherwise a checksum-valid value that GLEIF does not list. Check the Wikidata ids in DEMO_IDENTIFIERS the same way, and correct the comment to say what they are. If they are the real Wikidata items about the fictional companies, say that.

Done when

  • tests/test_seed_demo.py: after seed_demo --no-pdf with the default seed and with a seed that picks João, full_clean() passes on every Contact the account holds. It fails today on inês@aperture.example.
  • tests/test_seed_demo.py: the seeded French translation of the first experience's location is the French name of that experience's own city. It fails today with "Lisbonne" against "Paris".
  • tests/test_seed_demo.py: no seeded CompanyIdentifier with the scheme lei holds HWUPKR0MPOU8FGXBT394. It fails today for Initech.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading `seed_demo` and running it with its default seed on an in-memory database. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `jobs/models.py:627` (`Contact.email`) and `jobs/forms.py:578` (`ContactForm`); `seed_demo.py` and the other locations are unchanged. Three pieces of the data `seed_demo` writes are wrong. A contact gets an email address that Postulo's own contact form refuses, so the contact cannot be saved again until the address is rewritten. The one translated CV entry, there to show what a French CV prints, moves the job to another city. A fictional company carries a well-formed LEI that appears to belong to a real company, under a comment that calls the identifiers made up. The demo is how a newcomer judges Postulo, and its rows are written with `objects.create` and `bulk_create`, which validate nothing, so none of this is caught. - **Where:** - `CONTACT_NAMES` in `core/management/commands/seed_demo.py:143-150`; the contact creation in `Command._seed` at `core/management/commands/seed_demo.py:556-566`, with `email=f"{contact_name.split()[0].lower()}@{website.removeprefix('https://')}"`; `Contact.email`, an `EmailField`, at `jobs/models.py:624`; `ContactForm` at `jobs/forms.py:581`, whose `Meta.fields` include `email`. - The first `Experience` (Weyland-Yutani, `location="Paris"`) at `core/management/commands/seed_demo.py:385-398`; the French `Translation` rows for `experiences[0]` at `core/management/commands/seed_demo.py:757-774`. - `DEMO_IDENTIFIERS` and its comment at `core/management/commands/seed_demo.py:81-90`; the LEI scheme's link and example at `plugins/identifiers/schemes.py:196-197`. - **What happens:** 1. The address is the contact's first name, lowercased, at the company's website host. Two of the six names, João and Inês, are not ASCII, and Django's `EmailValidator` accepts only ASCII in the local part. With the default `--seed 2026` the run creates four contacts: Anna Schmidt at Wonka Industries, Inês Carvalho at Aperture Science, Luc Moreau at Tyrell Corporation and Marie Dubois at Stark Industries. Inês's address is `inês@aperture.example`, and `full_clean()` on that row answers "Enter a valid email address." Someone trying the demo who opens that contact, changes its role or notes and saves it gets that error on a field they never touched. Other seeds can pick João, with the same result. 2. The translation sets `"location": "Lisbonne"` on `experiences[0]`, whose location is Paris. Lisbon is the city of `experiences[1]` (Massive Dynamic). The French summary, "J'ai maintenu en service ce dont les autres équipes dépendaient.", is not a translation of "Platform team for the logistics product." either. Rendered in French, the demo CV shows the Weyland-Yutani job in Lisbon, which is the opposite of what a translation feature should demonstrate. 3. Initech's LEI, `HWUPKR0MPOU8FGXBT394`, passes the ISO 17442 mod-97 check. It is the value the LEI scheme uses as its own `example`, and it appears to be the LEI that GLEIF lists for Apple Inc. The company page links each identifier to its register (`https://search.gleif.org/#/record/{value}` for an LEI), so the fictional employer leads to a real company's record. The comment above `DEMO_IDENTIFIERS` says "The ids are made up, as the companies are", and *Getting started* in the wiki (`Getting-started.md:129`) says "Everything it creates is obviously invented". - **Why it matters:** the demo is meant to show the features working and to be plainly fictional. Its sample data fails Postulo's own validation on an ordinary edit, misrepresents the translation feature and points at a real company. `tests/test_seed_demo.py` never validates what the seeder creates, so this kind of drift goes unnoticed. - **Fix:** 1. Build the local part from an ASCII fold of the first name, for example `unicodedata.normalize("NFKD", first).encode("ascii", "ignore").decode().lower()`, or give each `CONTACT_NAMES` entry an explicit address. Leave the displayed names unchanged. 2. Translate the location as "Paris" and give a French summary that matches the English one, or move the translation onto the Lisbon entry. 3. Replace Initech's LEI with a value that is clearly not real: LEI-shaped but failing the checksum if nothing validates seeded rows on display, or otherwise a checksum-valid value that GLEIF does not list. Check the Wikidata ids in `DEMO_IDENTIFIERS` the same way, and correct the comment to say what they are. If they are the real Wikidata items about the fictional companies, say that. ## Done when - `tests/test_seed_demo.py`: after `seed_demo --no-pdf` with the default seed and with a seed that picks João, `full_clean()` passes on every `Contact` the account holds. It fails today on `inês@aperture.example`. - `tests/test_seed_demo.py`: the seeded French translation of the first experience's location is the French name of that experience's own city. It fails today with "Lisbonne" against "Paris". - `tests/test_seed_demo.py`: no seeded `CompanyIdentifier` with the scheme `lei` holds `HWUPKR0MPOU8FGXBT394`. It fails today for Initech.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:46:36 +00:00
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#423
No description provided.