Documents: untagged PDFs, CV arrows with the #203 bug, a letter preview that 500s, Europass inventing levels, long URLs off the page #235
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
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#235
Loading…
Add table
Add a link
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?
Found in the 2026-09-15 code audit.
1. PDFs are untagged: no PDF/UA structure, no outline, no PDF/A
documents/pdf.py:92callswrite_pdf()withoutpdf_tagsorpdf_variant.pdf.py:140calls Chromium'spage.pdf(...)withouttagged=True, outline=True.<p class="role">(themes/base_cv.html:84-90), so nothing below<h2>can be navigated by a screen reader or read as structure by an ATS. Letter section titles are plain paragraphs.langwork in #67 reaches a screen reader only through a tag tree, and these PDFs have none.Fix:
pdf_variant="pdf/ua-1"(orpdf_tags=True), pluspdf/a-3ufor renders copied to stores.tagged=True, outline=True.<h3>, and author metadata.tests/test_pdf_render.pyasserts/StructTreeRoot,/Langand/Title.2. The CV's entry arrows still have the bug #203 fixed on the career page
documents/views.py:163:item.order = max(0, item.order ± 1). Up at 0 does nothing, one down can jump past several entries, and entries sharing a number don't visibly move.order = count + added(:122-131), which collides after removals.cv_item_movebeyond page coverage.Fix: reuse
resume/ordering.moveandrenumberovercv.items.order_by("order", "pk"), and grey out the arrow at either end.3. Letter preview
letter_detail.html:15links to the preview with no application, and Send freezes the letter without showing the filled text.?application=abcreachesfilter(pk=...)and raisesValueError, a 500 (views.py:273-277).rendering.py:216-218), so a preview reads "Dear ," and a posting with no location sends a gap.Fix:
{{ contact }}placeholder.4. The Europass import invents language levels and ignores the file's language
resume/importing.py:214usesproficiency or "b1", so a file with no CEFR levels claims B1.localeis never read, soprofile.record_languagestays blank and the #131 fallback warnings fire wrongly.plugins/europass/reader.py:82-88), even for a Portuguese record.read_xmlrefuses anything withoutLearnerInfo, and both test fixtures are SkillsPassport.Fix:
record_languagefrom the file's locale when it is blank, and translate the group labels.5. Long URLs can run off the page
plain/cv.html,classic/cv.htmland both letter themes set nooverflow-wrap, and.datesisnowrapinside a flex row. The portfolio themes already handle it (plain/portfolio.html:39). Contact details are also separated only by CSS-generated " · ", which some text extractors drop.Fix:
overflow-wrap: anywhereon every base theme, real separator characters in the markup, and a render test with a 120-character URL.