[1.10.1] — 2026-05-09
Critical-fixes patch driven by the v1.10.0 QA regression run (qa/reports/00-FINAL-SUMMARY.md).
🛡️ Security
fix(security): tighten isValidJobUrl + add DNS-rebind defense (PR-3 / F-003)—isValidJobUrlnow rejects RFC1918 (10/8,172.16/12,192.168/16), the full 127/8 loopback range, link-local169.254/16(incl. AWS IMDS),0.0.0.0, CGNAT100.64/10, and IPv6 ULA / link-local. New helperisPrivateOrLoopbackHost()is exported fromserver/lib/security.mjsand reused by/api/pipeline/preview, which nowdns.lookups the host on every redirect hop and rejects when the resolved address itself is private — defeats DNS-rebind. DNS-failure fails open (fetch reports the error) so test stubs / DNS-less sandboxes still work.
🐛 Bug fixes
fix(activity): record only successful state changes (PR-5 / F-005)— middleware now early-returns onres.statusCode >= 400. Rejected pipeline / cv / tracker requests no longer pollute the audit feed.fix(activity): add profile.save / config.save / cv.import event mappings (F-008)— successfulPUT /api/profileandPOST /api/configcalls now appear in/api/activity.fix(help): alias ko → ko-KR.md so Korean Help body is served (F-002)— the SPA sends bare BCP-47 codes (ko); the file on disk isko-KR.md. Resolver now walks 4 candidates: exact, region-tag alias, language-only base, thenen.md.fix(llm): /api/evaluate honors mode:'manual' (F-009)— mirrors/api/deep. Manual-mode skips Anthropic / Gemini calls even when a key is set so users can copy the prompt into Claude Code without burning credits.fix(api): DELETE /api/pipeline accepts ?url= AND body.url, returns 404 on miss (PR-6 / F-017)— was silently 200-on-miss with?url=only.
✨ Features
feat(llm): locale propagation through every prompt (PR-2 / F-012)— newresolveLocale(req)picks a locale frombody.lang→body.locale→Accept-Language→'en'. NewbuildLocaleDirective(lang)emits a one-line "Respond in X" header.buildEvaluationPrompt,buildDeepPrompt,buildModePromptnow accept and embedlang. SPAAPI.call()auto-attachesAccept-Languageand mergeslanginto JSON bodies.feat(scripts): post-qa-cleanup.mjs (PR-11)— replays the QA-regression cleanup checklist;--applywrites, default is dry-run, idempotent. Sweeps RFC1918 /nip.io/test-cloud-*URLs fromdata/pipeline.mdand auditscv.mdsize.
🧪 Tests
- New
tests/critical-fixes.test.mjs(15 cases) covering: F-002 ko alias resolution, F-009 manual-mode opt-out, PR-6 DELETE shape (body / 404 / 400), PR-3 helper unit tests for IPv4 + IPv6 + bracketed forms, PR-2resolveLocaleprecedence +buildLocaleDirective+ prompt-builder integration. tests/url-validation.test.mjsextended with 5 new tests for RFC1918 / link-local / 0.0.0.0 / 127/8 / CGNAT / IPv6 ULA / link-local.tests/activity-log.test.mjstest 8 updated to assert the new "no log on 4xx" contract.- Total: 318 unit tests (was 298; one pre-existing failure in
portals-dead.test.mjsis parent-side data drift intemplates/portals.example.yml, unrelated to web-ui code).
📝 Docs
- New
docs/reviews/REVIEW-2026-05-09-v1.10.1.md— full session context + scope-out list + verification commands. - All 8 READMEs: badge bumps (test count 298 → 318, release v1.10.0 → v1.10.1), screenshot path moved to
public/images/screen_vacancy_found.png, "What's new in v1.10.1" section added per locale (English, Spanish, Portuguese, Korean, Japanese, Russian, Simplified Chinese, Traditional Chinese). - All 8 CHANGELOGs updated with this entry.
Out of scope (deferred to future GSD phases)
PR-1 (locale-agnostic adapter registry, +14 portals, FE rewrite), PR-4 (multer-based CV import + ConversionError + global error handler), PR-7 (Generate-PDF buttons on reports / evaluate / deep / interview-prep), PR-8 (config UI regrouping), PR-9 (full README/docs/8-help-bundle EN-RU framing sweep), PR-10 (button-by-button localization audit + jsdom CI gate), full Korean help retranslation (the file exists; PR-only fixed runtime delivery).