github Fighter90/career-ops-ui v1.10.1

latest releases: v1.239.4, v1.239.3, v1.239.2...
4 months ago

[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) — isValidJobUrl now rejects RFC1918 (10/8, 172.16/12, 192.168/16), the full 127/8 loopback range, link-local 169.254/16 (incl. AWS IMDS), 0.0.0.0, CGNAT 100.64/10, and IPv6 ULA / link-local. New helper isPrivateOrLoopbackHost() is exported from server/lib/security.mjs and reused by /api/pipeline/preview, which now dns.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 on res.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) — successful PUT /api/profile and POST /api/config calls 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 is ko-KR.md. Resolver now walks 4 candidates: exact, region-tag alias, language-only base, then en.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) — new resolveLocale(req) picks a locale from body.lang → body.locale → Accept-Language → 'en'. New buildLocaleDirective(lang) emits a one-line "Respond in X" header. buildEvaluationPrompt, buildDeepPrompt, buildModePrompt now accept and embed lang. SPA API.call() auto-attaches Accept-Language and merges lang into JSON bodies.
  • feat(scripts): post-qa-cleanup.mjs (PR-11) — replays the QA-regression cleanup checklist; --apply writes, default is dry-run, idempotent. Sweeps RFC1918 / nip.io / test-cloud-* URLs from data/pipeline.md and audits cv.md size.

🧪 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-2 resolveLocale precedence + buildLocaleDirective + prompt-builder integration.
  • tests/url-validation.test.mjs extended with 5 new tests for RFC1918 / link-local / 0.0.0.0 / 127/8 / CGNAT / IPv6 ULA / link-local.
  • tests/activity-log.test.mjs test 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.mjs is parent-side data drift in templates/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).


Don't miss a new career-ops-ui release

NewReleases is sending notifications on new releases.