Open the importer kind to third parties, once the file refusals belong to the kind #105

Closed
opened 2026-09-07 16:32:12 +00:00 by tiagoagueda · 0 comments
Owner

Why this is separate

#99 makes Europass an internal plugin and stops there, deliberately — the third-party surface
was the larger half of that issue and none of it is needed to get Europass out of
resume/views.py and into the registry.

This is the rest: telling anybody else they may write one.

What is left to do

Not much, if #99 lands as narrowed:

  • An ImporterPlugin protocol, so _load_third_party's isinstance check has something
    to check against. Built-ins skip that check; third parties do not.
  • A chapter in docs/PLUGINS.md with the contract: can_handle(data, filename),
    read(data) -> Record, and the identity fields from #97.
  • The reference plugin gains one, or does not — postulo-helloworld already ships a
    source and a notifier, and a third example may be more use as a separate repository.

The prerequisite, which #99 should already have handled

An importer is handed a file somebody uploaded, which is not the threat a source faces —
a source gets a URL and HTML that Postulo fetched itself. europass.py refuses a DOCTYPE
before parsing, "because a DOCTYPE is where entity expansion lives, and the point is to
refuse it rather than to hand it to a parser and hope"
, and caps the file at MAX_BYTES.

Those refusals belong to the kind, enforced before a plugin sees a byte. A third-party
importer that forgot the DOCTYPE check would be an XXE hole in an application holding
people's CVs, and "every plugin author remembers" is not a control.

Check this is true before advertising the group. #99 is asked to move them; if it did
not, this issue does it first and nothing else.

Worth having at all?

Yes, and the argument is the one the plugin system was built on. Europass is not the last CV
format: JSON Resume, HR-XML, a LinkedIn export, a PDF somebody wants parsed. Each is
somebody else's itch, and registry.py puts it as "the person who cares about a particular
job board... should not have to wait for this project to accept a patch"
.

Classification

Enhancement. Depends on #99. On 0.4.0 rather than 0.3.0 to keep the release simple, which is
the point of narrowing #99 in the first place.

## Why this is separate #99 makes Europass an internal plugin and stops there, deliberately — the third-party surface was the larger half of that issue and none of it is needed to get Europass out of `resume/views.py` and into the registry. This is the rest: telling anybody else they may write one. ## What is left to do Not much, if #99 lands as narrowed: - **An `ImporterPlugin` protocol**, so `_load_third_party`'s `isinstance` check has something to check against. Built-ins skip that check; third parties do not. - **A chapter in `docs/PLUGINS.md`** with the contract: `can_handle(data, filename)`, `read(data) -> Record`, and the identity fields from #97. - **The reference plugin gains one**, or does not — `postulo-helloworld` already ships a source and a notifier, and a third example may be more use as a separate repository. ## The prerequisite, which #99 should already have handled An importer is handed **a file somebody uploaded**, which is not the threat a source faces — a source gets a URL and HTML that Postulo fetched itself. `europass.py` refuses a DOCTYPE before parsing, *"because a DOCTYPE is where entity expansion lives, and the point is to refuse it rather than to hand it to a parser and hope"*, and caps the file at `MAX_BYTES`. Those refusals belong to the kind, enforced before a plugin sees a byte. A third-party importer that forgot the DOCTYPE check would be an XXE hole in an application holding people's CVs, and "every plugin author remembers" is not a control. **Check this is true before advertising the group.** #99 is asked to move them; if it did not, this issue does it first and nothing else. ## Worth having at all? Yes, and the argument is the one the plugin system was built on. Europass is not the last CV format: JSON Resume, HR-XML, a LinkedIn export, a PDF somebody wants parsed. Each is somebody else's itch, and `registry.py` puts it as *"the person who cares about a particular job board... should not have to wait for this project to accept a patch"*. ## Classification Enhancement. Depends on #99. On 0.4.0 rather than 0.3.0 to keep the release simple, which is the point of narrowing #99 in the first place.
tiagoagueda added this to the 0.4.0 milestone 2026-09-07 16:32:12 +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.

Reference
Postulo/postulo#105
No description provided.