Europass: find out what the platform exports today, and read it #244
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#244
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Split out of #235, whose last bullet was a research task rather than a fix. #235 did the
three concrete things (levels left unset,
record_languagefrom the file's locale,translated group labels) and deliberately left this one alone, because half-building a
reader against a format nobody here has seen is worse than not having one.
What we actually know
reader.readsniffs on the first non-whitespace byte:<is XML,{is JSON, anythingelse is refused with a message naming the two formats.
read_xmlrefuses anything with noLearnerInfoelement;read_jsonacceptsSkillsPassport.LearnerInfoor a bareLearnerInfo.tests/data/are SkillsPassport. Neither came from europass.europa.euthis year.
%.What is plausible and unverified
The audit's claim is that today's Europass editor exports HR-Open Candidate XML, or a
PDF with the XML embedded, rather than SkillsPassport. Nobody has checked. If it is true,
"import your Europass CV" is a promise Postulo does not keep for anybody who made their CV
this year, and the refusal message tells them their own export is not a Europass file.
What to do first, before writing any code
Make a Europass CV on europass.europa.eu and download it in every format the Download
menu offers. Commit each as a fixture with the personal details replaced, the way
tests/data/europass.xmlalready is, and say in the file's comment what produced it andwhen — that comment is the thing that stops the next person guessing again.
Then, depending on what came back
Your career record, and close this.
importing.Record, which is whatthe
Recordshape exists for (#129). It cannot sniff on the first byte, since it is XMLtoo, so
read_xmlgrows a look at the root element's local name and dispatches; therefusal message then has to name three formats rather than two.
An embedded file lives in
/Names /EmbeddedFilesand reaching it means parsing PDFstructure, which Postulo has no dependency for today (WeasyPrint writes and never reads).
Adding one is a supply-chain decision, and it is an untrusted-input decision besides: the
uploaded file is a stranger's, so whatever is added has to be held to the same rules as
the rest of the importer kind — the size cap before parsing, no object-stream bomb, and
refuse_unreadableon what comes out of the attachment as well as on what went in,because the payload is a second file.
Also worth settling while looking
Whether the editor's PDF has any machine-readable payload at all any more. If it does not,
the upload form should say which file to choose rather than leaving somebody to find out by
being refused;
accept=".xml,.json,…"on the input already hints at it, and the sentenceabove it does not.
What europass.europa.eu exports today: the research for #244
Done on 2026-09-29 from public sources only: no account was created, nothing was signed into, and no personal data was sent anywhere. Every page below was fetched that day. Nobody here has downloaded a CV from the platform, so the issue's first step (a person making a CV and downloading it) has still not been done; it is #318 now, with the steps.
Summary
attachment.xml./Type /EmbeddedFilestream written by pdf-lib, with/AFon the catalogue, and the PDF is not encrypted.Candidateinhttp://www.europass.eu/1.0, besidehr:(http://www.hr-xml.org/3),oa:(http://www.openapplications.org/oagis/9) andeures:(http://www.europass_eures.eu/1.0). It is HR Open Standards 3.2 (majorVersionID="3" minorVersionID="2").Candidate.xsdreads "Europass2 1.0.1, 02 June 2020", and the documentation is v3.0.0 of 17/02/2020.RenderingInformation, aSkillsblock andCourseCertifications, none of which it defines, and put children in a different order.Candidate.RenderingInformation; 13 shows the rest. The examples in 13 fail validation against the official XSD at exactly those places (checked with lxml)./v1/document/to/json), and that host now fails TLS with a revoked certificate.Sources
The European Commission's own
14591a994ddd66111d6e0ef3c64086a4680102047c280a946091f8b78ebeee9f.ECV_XSD/org_europass/1.0.1/Developer/Nouns/Candidate.xsdhas rootCandidateand target namespacehttp://www.europass.eu/1.0.Legacy Europass XML to Europass2 v2.0.xlsx; a draft JSON serialisation (ECV_JsonSchema_v4.1_S0.7.json, root keyCandidate), which nothing shows being produced for people; and the sample below.24674c0e7507fc838c0794b619d5590b5f486f284ac280049ba348a8ab1347b4.tests/data/europass-candidate-sample.xml.SkillsPassport, namespacehttp://europass.cedefop.europa.eu/Europass, last changed October 2019, with a RESTful API.Cedefop's old platform
/rest) and https://interop.europass.cedefop.europa.eu/ both failed the TLS handshake with "certificate is revoked". That shows they cannot be used, not that they are switched off.fee3b9758cof 2020-06-11.ExportInfo.jslists the download formats as PDF (default, uploadable), Word, ODT and XML, and no JSON.Constants.javanames the attachmentEuropass-XML-Attachment.xml./v1/document/to/json: the JSON belonged to the API, not the editor.Independent accounts of real downloads
pdfdetach -savefile attachment.xml, readsCandidate.RenderingInformation[0].ClosingStatement[0].Date[0]['hr:FormattedDateTime'], and links 5 as the documentation.2478b3497d: https://github.com/J0ker98/europass-cvattachment.xml,text/xml, made with pdf-lib, with/Desc,/UFand/AF, packed with FlateDecode.RenderingInformation/SectionsOrder; aSkillsblock ofPersonCompetencyentries withTaxonomyIDDigital_Skill; three-letter language codes; lower-case country codes.attachment.xmlin LaTeX PDFs.Europass-XML-Attachment.xml, made with iText. History only.What was built on it (
ac2696504)plugins/europass/candidate.py, behind the sameimporting.Record.read_xmldispatches on the root element's name and namespace. ACandidatefrom another namespace is refused with a message naming both XML formats.plugins/europass/pdf.py, needs no new dependency./Type /EmbeddedFilestreams, which works however much else is compressed.tests/data/europass-candidate.xml, written by hand from the schema and validated against it;tests/data/europass-candidate-sample.xml, the Commission's sample; test PDFs built in the test module. None is a real download.Skillsblock, since only 13 describes it; a reader for the draft Candidate JSON; country names, since the format gives codes.What is still unverified
Whether a PDF downloaded today marks its attachment
/Type /EmbeddedFileand packs it with Flate, which sections it holds, and whether digital skills now live in theSkillsblock. The step that settles all three can only be taken by a person, and it is #318.