{"id":486081,"date":"2026-07-03T11:47:02","date_gmt":"2026-07-03T11:47:02","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=486081"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=486081","title":{"rendered":"Spec-Driven Development \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435: \u043a\u0430\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 job-\u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440 \u0436\u0438\u0432\u0451\u0442 \u0431\u0435\u0437 \u0440\u0435\u0432\u044c\u044e\u0435\u0440\u043e\u0432 \u0438 \u043d\u0435 \u043b\u043e\u043c\u0430\u0435\u0442\u0441\u044f"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><em>\u0420\u0430\u0437\u0431\u043e\u0440 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0438 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f, senior backend-\u0438\u043d\u0436\u0435\u043d\u0435\u0440, \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u2014 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u0441\u043a\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 job-\u0431\u043e\u0440\u0434\u044b \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u0442\u0440\u0443\u0434\u043e\u0451\u043c\u043a\u043e\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439. \u0412\u043d\u0443\u0442\u0440\u0438: \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0431\u0435\u0437 virtual DOM, \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u043c \u0444\u043e\u043a\u0443\u0441\u043e\u043c, \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 API-\u0441\u043b\u043e\u0439 \u043f\u043e\u0432\u0435\u0440\u0445 SSE, \u0434\u0432\u0443\u0445\u0444\u0430\u0437\u043d\u044b\u0439 \u0441\u043a\u0430\u043d\u0435\u0440 \u0441 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435\u043c, SSRF-envelope \u043d\u0430 DNS-pinning, \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 13 \u043b\u043e\u043a\u0430\u043b\u0435\u0439 \u0441 RTL, \u0437\u0430\u043f\u0443\u0441\u043a \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u043f\u0438\u0440\u0430\u043c\u0438\u0434\u0430 \u0438\u0437 1543 \u043a\u0435\u0439\u0441\u043e\u0432. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u2014 \u043c\u0435\u0442\u043e\u0434 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438: Spec-Driven Development \u0438 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0442\u0435\u0441\u0442\u0430\u043c\u0438.<\/em><\/p>\n<p><strong>\u041f\u0440\u043e\u0435\u043a\u0442:<\/strong> <a href=\"https:\/\/github.com\/Fighter90\/career-ops-ui\" rel=\"noopener noreferrer nofollow\">github.com\/Fighter90\/career-ops-ui<\/a><\/p>\n<p><strong>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a:<\/strong> <a href=\"https:\/\/github.com\/santifer\/career-ops\" rel=\"noopener noreferrer nofollow\">github.com\/santifer\/career-ops<\/a><\/p>\n<p><strong>\u0420\u043e\u0430\u0434\u043c\u0430\u043f (Issue #29):<\/strong> <a href=\"https:\/\/github.com\/Fighter90\/career-ops-ui\/issues\/29\" rel=\"noopener noreferrer nofollow\">github.com\/Fighter90\/career-ops-ui\/issues\/29<\/a><\/p>\n<h3>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438: \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0435\u043d\u044c\u043e\u0440 \u043f\u0438\u0448\u0435\u0442 \u0441\u0435\u0431\u0435 job-\u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440<\/h3>\n<p>\u042f backend-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 (PHP, Go). \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432 \u043f\u043e\u0437\u0438\u0446\u0438\u0438, \u0437\u043d\u0430\u043a\u043e\u043c\u043e\u0439 \u043c\u043d\u043e\u0433\u0438\u043c: \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438 \u043f\u043e\u043b\u043d\u043e\u0439 \u0437\u0430\u043d\u044f\u0442\u043e\u0441\u0442\u0438. \u0418 \u0431\u044b\u0441\u0442\u0440\u043e \u0443\u043f\u0451\u0440\u0441\u044f \u0432 \u0442\u043e, \u0447\u0442\u043e \u0441\u0430\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u0438\u0441\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u2014 \u043d\u0435 \u00ab\u043c\u043e\u0440\u0430\u043b\u044c\u043d\u043e \u0442\u044f\u0436\u0435\u043b\u043e\u00bb, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e.<\/p>\n<p>\u0412\u043e\u0437\u044c\u043c\u0451\u043c \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043d\u0430 hh.ru. \u041f\u043e\u0438\u0441\u043a\u043e\u0432\u0430\u044f \u0432\u044b\u0434\u0430\u0447\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u043b\u0435\u0432\u0430\u043d\u0442\u043d\u044b\u0435 \u0440\u043e\u043b\u0438 \u0441 \u0448\u0443\u043c\u043e\u043c: \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u00abSenior PHP\u00bb \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u044e\u0442 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u0434\u0436\u0443\u043d\u043e\u0432, \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u043e\u0432 \u0438 \u00abPHP-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e \u0437\u043d\u0430\u043d\u0438\u0435\u043c 1\u0421\u00bb. \u041e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u043e\u0434 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 URL \u2014 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u00ab\u043e\u0441\u0432\u0435\u0436\u0430\u0435\u0442\u00bb \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044e, \u0438 \u043e\u043d\u0430 \u0441\u043d\u043e\u0432\u0430 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u0435\u0442 \u0432 \u0432\u044b\u0434\u0430\u0447\u0435 \u043a\u0430\u043a \u043d\u043e\u0432\u0430\u044f; \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0440\u0435\u043f\u043e\u0441\u0442 \u0440\u043e\u043b\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0442\u044b \u0443\u0436\u0435 \u043e\u0442\u043a\u043b\u0438\u043a\u0430\u043b\u0441\u044f \u043c\u0435\u0441\u044f\u0446 \u043d\u0430\u0437\u0430\u0434, \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0417\u0430\u0440\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u0432\u0438\u043b\u043a\u0438 \u0441\u043a\u0440\u044b\u0442\u044b \u0438\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u0430\u043b\u044e\u0442\u0430\u0445 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445. \u0410 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 hh.ru \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c \u0440\u044b\u043d\u043a\u0430: \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u043f\u043e\u0437\u0438\u0446\u0438\u0439 \u0436\u0438\u0432\u0451\u0442 \u0432 ATS \u0437\u0430\u043f\u0430\u0434\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 (Greenhouse, Ashby, Lever, Workable, SmartRecruiters, Workday), \u043d\u0430 Habr Career, \u0432 GetMatch, GeekJob, Trudvsem \u2014 \u0438 \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0441\u0432\u043e\u0439 API, \u0441\u0432\u043e\u044f \u0441\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u0432\u043e\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0437\u0430\u0440\u043f\u043b\u0430\u0442\u044b \u0438 \u043b\u043e\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u2014 \u0418\u0418, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 2026 \u0433\u043e\u0434\u0443 \u0441\u0442\u043e\u0438\u0442 \u043f\u043e \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432\u043e\u0440\u043e\u043d\u043a\u0438 \u043d\u0430\u0439\u043c\u0430 \u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0435\u0451 \u044d\u0442\u0430\u043f\u0435. \u0421\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0430\u0431\u043e\u0442\u043e\u0434\u0430\u0442\u0435\u043b\u044f \u0440\u0435\u0437\u044e\u043c\u0435 \u043f\u0435\u0440\u0432\u044b\u043c \u0447\u0438\u0442\u0430\u0435\u0442 \u043d\u0435 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0430 ATS-\u0441\u043a\u0440\u0438\u043d\u0435\u0440: \u043e\u043d \u043f\u0430\u0440\u0441\u0438\u0442 PDF, \u043c\u0430\u0442\u0447\u0438\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0438 \u0440\u0435\u0436\u0435\u0442 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0435\u043a\u0440\u0443\u0442\u0451\u0440 \u0432\u043e\u043e\u0431\u0449\u0435 \u0443\u0432\u0438\u0434\u0438\u0442 \u043e\u0442\u043a\u043b\u0438\u043a, \u2014 \u0437\u043d\u0430\u0447\u0438\u0442, \u0440\u0435\u0437\u044e\u043c\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043c\u0430\u0448\u0438\u043d\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c (\u0442\u0438\u043f\u043e\u0433\u0440\u0430\u0444\u0438\u043a\u0430, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433 \u0448\u0440\u0438\u0444\u0442\u043e\u0432), \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c. \u0421\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432 \u0440\u044b\u043d\u043e\u043a \u0437\u0430\u0445\u043b\u0435\u0441\u0442\u043d\u0443\u043b\u0430 \u0432\u043e\u043b\u043d\u0430 \u043c\u0430\u0441\u0441\u043e\u0432\u044b\u0445 AI-\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432: \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0446\u0438\u044f \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0438\u0441\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u0437\u0430\u044f\u0432\u043e\u043a, \u0430 \u0440\u0435\u043a\u0440\u0443\u0442\u0451\u0440\u044b \u0432 \u043e\u0442\u0432\u0435\u0442 \u0437\u0430\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u044e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0443\u0447\u0430\u0442\u0441\u044f \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u00ab\u0440\u043e\u0431\u043e\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435\u00bb \u0440\u0435\u0437\u044e\u043c\u0435 \u2014 \u0433\u0435\u043d\u0435\u0440\u0438\u0447\u043d\u044b\u0439 AI-\u0442\u0435\u043a\u0441\u0442 \u0431\u0435\u0437 \u0444\u0430\u043a\u0442\u0443\u0440\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 (\u044d\u0442\u0430 \u0431\u043e\u043b\u044c \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043f\u0440\u044f\u043c\u043e \u0432 issue #1 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430). \u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u043e \u0432\u043e\u0440\u043e\u043d\u043a\u0435 \u2014 AI-\u0441\u043a\u0440\u0438\u043d\u0438\u043d\u0433\u043e\u0432\u044b\u0435 \u0437\u0432\u043e\u043d\u043a\u0438, \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0430\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442\u044b-\u043e\u0442\u043a\u0430\u0437\u044b \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438. \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439 \u043d\u0435\u043b\u044c\u0437\u044f, \u043d\u043e \u0438 \u0441\u043b\u0435\u043f\u043e \u00ab\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435\u00bb \u2014 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0448\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f. \u0420\u0430\u0437\u0443\u043c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0418\u0418 \u043d\u0435 \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0441\u0442\u0438, \u0430 \u0434\u043b\u044f \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438: \u0441\u043a\u043e\u0440\u0438\u043d\u0433 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u043f\u0440\u043e\u0442\u0438\u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0440\u0435\u0437\u044e\u043c\u0435 \u0434\u043e \u043e\u0442\u043a\u043b\u0438\u043a\u0430, \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044f \u0440\u0435\u0437\u044e\u043c\u0435 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e JD \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0444\u0430\u043a\u0442\u0443\u0440\u044b, \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u043f\u0435\u0440\u0435\u0434 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e \u2014 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0442\u043a\u043b\u0438\u043a \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0440\u0443\u0447\u043d\u044b\u043c \u0438 \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0434\u0435\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0447\u0435\u0441\u0442\u043d\u043e, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0438\u043f\u043e\u0432\u043e\u0439 ETL-\u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043d\u0430\u0434 \u043d\u0435\u043e\u0434\u043d\u043e\u0440\u043e\u0434\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438: \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044f \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 \u0438\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 job-board API \u0438 ATS, \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0434\u0435\u0434\u0443\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0440\u0430\u0437\u043d\u043e\u0440\u043e\u0434\u043d\u044b\u0445 \u0441\u0445\u0435\u043c \u0432 \u0435\u0434\u0438\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c, \u0441\u043a\u043e\u0440\u0438\u043d\u0433 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043f\u0440\u043e\u0442\u0438\u0432 \u0440\u0435\u0437\u044e\u043c\u0435 \u0438 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0442\u043a\u043b\u0438\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0420\u043e\u0432\u043d\u043e \u0442\u043e, \u0447\u0442\u043e backend-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b \u0441\u0442\u0440\u043e\u044f\u0442 \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0434 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u0442\u0440\u0443\u0434\u043e\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435.<\/p>\n<p>\u0413\u043e\u0442\u043e\u0432\u044b\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u043d\u0430 \u0440\u044b\u043d\u043a\u0435 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0442. \u042d\u0442\u043e \u043b\u0438\u0431\u043e \u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437\u043d\u044b\u0435 ATS, \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0440\u0435\u043a\u0440\u0443\u0442\u0451\u0440\u0430, \u0430 \u043d\u0435 \u043d\u0430 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430, \u043b\u0438\u0431\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043b\u0435\u043d\u0442\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0431\u043e\u0440\u0434\u043e\u0432 \u2014 \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u043e\u043c, \u0431\u0435\u0437 \u0441\u043a\u0432\u043e\u0437\u043d\u043e\u0439 \u0434\u0435\u0434\u0443\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0431\u0435\u0437 \u0441\u043a\u043e\u0440\u0438\u043d\u0433\u0430 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u0440\u0435\u0437\u044e\u043c\u0435. \u041a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0443 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f Excel-\u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u0438 \u0434\u0435\u0441\u044f\u0442\u043e\u043a \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a. \u041c\u0435\u043d\u044f \u043a\u0430\u043a \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430 \u0442\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0435\u043b \u043d\u0435 \u0443\u0441\u0442\u0440\u043e\u0438\u043b\u043e \u2014 \u0438 \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0434 \u0441\u0435\u0431\u044f.<\/p>\n<p><strong>career-ops-ui<\/strong> \u2014 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442 41 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0432 \u0435\u0434\u0438\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0446\u0435\u043d\u043a\u0443 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u043f\u043e\u0434 \u0440\u0435\u0437\u044e\u043c\u0435, \u0432\u0435\u0434\u0451\u0442 \u0432\u043e\u0440\u043e\u043d\u043a\u0443 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 PDF. \u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043d\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u2014 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u044c: \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043b\u0443\u0448\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e loopback (127.0.0.1:4317); PII (\u0440\u0435\u0437\u044e\u043c\u0435, \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432, \u0437\u0430\u0440\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f) \u043d\u0435 \u043f\u043e\u043a\u0438\u0434\u0430\u0435\u0442 \u043c\u0430\u0448\u0438\u043d\u0443. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u0432, \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e-\u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432. \u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u0430\u043a companion \u043f\u043e\u0432\u0435\u0440\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 santifer\/career-ops \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0441\u0442\u0438\u043d\u044b. \u0414\u0430\u043b\u044c\u0448\u0435 \u2014 \u0440\u0430\u0437\u0431\u043e\u0440 \u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c, \u0441 \u0430\u043a\u0446\u0435\u043d\u0442\u043e\u043c \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434.<\/p>\n<h3>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a: \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043c\u0443\u043b\u044c\u0442\u0438-CLI<\/h3>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u0435 \u2014 <a href=\"https:\/\/github.com\/santifer\/career-ops\" rel=\"noopener noreferrer nofollow\">santifer\/career-ops<\/a>, \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 AI-\u0434\u0432\u0438\u0436\u043e\u043a \u043f\u043e\u0438\u0441\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b (\u043f\u043e\u0434 \u0448\u0435\u0441\u0442\u044c\u0434\u0435\u0441\u044f\u0442 \u0442\u044b\u0441\u044f\u0447 \u0437\u0432\u0451\u0437\u0434 \u043d\u0430 GitHub; \u0441\u0430\u043c\u043e\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u2014 \u00ab14 skill modes, Go dashboard, PDF generation, batch processing\u00bb). \u0414\u0432\u0438\u0436\u043e\u043a \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0443\u044e \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044e \u043f\u0440\u043e\u0442\u0438\u0432 \u0440\u0435\u0437\u044e\u043c\u0435 \u043f\u043e \u0448\u0435\u0441\u0442\u0438\u043c\u0435\u0440\u043d\u043e\u0439 \u0440\u0443\u0431\u0440\u0438\u043a\u0435 0.0\u20135.0, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 PDF-\u0440\u0435\u0437\u044e\u043c\u0435 \u0438 \u0432\u0435\u0434\u0451\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432.<\/p>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e: <strong>\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u043f\u043b\u043e\u0441\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445<\/strong>. \u0420\u0435\u0437\u044e\u043c\u0435 \u2014 <code>cv.md<\/code>, \u043f\u0440\u043e\u0444\u0438\u043b\u044c (\u0446\u0435\u043b\u0435\u0432\u044b\u0435 \u0440\u043e\u043b\u0438, \u043b\u043e\u043a\u0430\u0446\u0438\u044f, \u0434\u0438\u043b-\u0431\u0440\u0435\u0439\u043a\u0435\u0440\u044b) \u2014 <code>config\/profile.yml<\/code>, \u0442\u0440\u0435\u043a\u0435\u0440 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u2014 <code>data\/applications.md<\/code>. \u0421\u0423\u0411\u0414 \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u043e\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u2014 \u0438 \u044d\u0442\u043e \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0430 \u043d\u0435 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435: \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 git-friendly \u0438 \u0434\u0438\u0444\u0444\u0443\u0435\u043c\u043e (\u043b\u044e\u0431\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0432\u0438\u0434\u043d\u043e \u0432 <code>git diff<\/code>), \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c\u043e \u043c\u0435\u0436\u0434\u0443 \u043c\u0430\u0448\u0438\u043d\u0430\u043c\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u0447\u0438\u0442\u0430\u0435\u043c\u043e \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u043c \u0431\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430; \u0438\u043d\u0434\u0435\u043a\u0441 (\u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438) \u2014 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0439 \u043a\u044d\u0448, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>\u0414\u0432\u0438\u0436\u043e\u043a CLI-\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u043d: \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043b\u0435\u0436\u0430\u0442 \u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u0441\u043a\u0438\u043b\u043b-\u043f\u0430\u043a\u0438 \u043f\u043e\u0434 <code>.claude<\/code>, <code>.qwen<\/code>, <code>.grok<\/code>, <code>.kimi<\/code>, <code>.opencode<\/code>. \u042d\u0442\u0443 \u043c\u043e\u0434\u0435\u043b\u044c-\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0451\u043b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u043e\u0446\u0435\u043d\u043a\u0438: Anthropic, Gemini, OpenAI, Qwen, OpenRouter, GitHub Models \u2014 \u0432\u044b\u0431\u043e\u0440 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f: LLM-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u2014 \u044d\u0442\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0441 \u0441\u0430\u043c\u044b\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0432\u0435\u043d\u0434\u043e\u0440\u0443 \u0432 2026 \u0433\u043e\u0434\u0443 \u043d\u0435\u0440\u0430\u0437\u0443\u043c\u043d\u043e.<\/p>\n<p>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0436\u0451\u0441\u0442\u043a\u043e: <strong>\u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u2014 read-only<\/strong>. \u041a\u043b\u0438\u0435\u043d\u0442 \u0447\u0438\u0442\u0430\u0435\u0442 \u0442\u0435 \u0436\u0435 \u0444\u0430\u0439\u043b\u044b, \u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e \u044f\u0432\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044e (<code>POST \/api\/pipeline<\/code>, <code>POST \/api\/tracker<\/code>, <code>PUT \/api\/cv<\/code>); \u043d\u0438 \u043e\u0434\u0438\u043d \u0444\u043e\u043d\u043e\u0432\u044b\u0439 code-path \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u043d\u0435 \u043f\u0438\u0448\u0435\u0442. \u042d\u0442\u043e \u0437\u0430\u0449\u0438\u0449\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043f\u043e\u0432\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u0431\u0430\u0433\u043e\u043c \u0444\u043e\u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u043c: \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f \u2014 \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.<\/p>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 issue \u0434\u0432\u0438\u0436\u043a\u0430: ATS-\u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f AI-\u0440\u0435\u0437\u044e\u043c\u0435 (#1), \u043e\u0442\u043a\u0430\u0437 \u043c\u0435\u0439\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0432\u0435\u0431-\u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u0432 \u044f\u0434\u0440\u043e (#12, \u044f\u0434\u0440\u043e \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e terminal-first), \u0441\u043f\u0440\u043e\u0441 \u043d\u0430 \u043c\u0443\u043b\u044c\u0442\u0438-CLI (#14). #12 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442<\/strong>, \u0430 \u043d\u0435 \u043f\u0430\u0442\u0447\u0438\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a: \u0444\u043e\u0440\u043a \u0441 \u0432\u0435\u0431-\u043c\u043e\u0440\u0434\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0435\u0447\u0451\u043d \u043d\u0430 \u0432\u0435\u0447\u043d\u044b\u0439 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442 \u0441 upstream, \u0430 companion-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0436\u0438\u0432\u0451\u0442 \u0441\u0432\u043e\u0438\u043c \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c.<\/p>\n<h3>\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 engine\/UI<\/h3>\n<p>\u0413\u0440\u0430\u043d\u0438\u0446\u0430 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u044f\u0432\u043d\u043e: \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u2014 \u0434\u043e\u043c\u0435\u043d\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0438 LLM-\u0440\u0435\u0436\u0438\u043c\u044b; \u043a\u043b\u0438\u0435\u043d\u0442 \u2014 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432, \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0441\u043a\u0430\u043d\u0430 \u0438 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u044f. \u041e\u0431\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0447\u0438\u0442\u0430\u044e\u0442 \u043e\u0431\u0449\u0438\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u0439\u0442; \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c read-only. \u042d\u0442\u043e \u0434\u0430\u0451\u0442 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b (\u0434\u0432\u0438\u0436\u043e\u043a \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f terminal-first, \u043a\u043b\u0438\u0435\u043d\u0442 \u0440\u0435\u043b\u0438\u0437\u0438\u0442\u0441\u044f \u0432 \u0441\u0432\u043e\u0451\u043c \u0442\u0435\u043c\u043f\u0435) \u0438 \u0435\u0434\u0438\u043d\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0441\u0442\u0438\u043d\u044b \u0431\u0435\u0437 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0411\u0414 \u2014 \u043a\u043b\u0430\u0441\u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u00ab\u0440\u0430\u0441\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0434\u0432\u0435 \u043a\u043e\u043f\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u00bb \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044e.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/d2\/d8\/76\/d2d876d63c346441ba951602a808794f.png\" alt=\"\u0420\u0438\u0441. 1. \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 engine\/UI: \u043e\u0431\u0449\u0438\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0441\u0442\u0438\u043d\u044b, \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a read-only, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 loopback.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/d2\/d8\/76\/d2d876d63c346441ba951602a808794f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/d2\/d8\/76\/d2d876d63c346441ba951602a808794f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441. 1. \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 engine\/UI: \u043e\u0431\u0449\u0438\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0441\u0442\u0438\u043d\u044b, \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a read-only, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 loopback.<\/figcaption><\/div>\n<\/figure>\n<h3>\u0417\u0430\u043f\u0443\u0441\u043a \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439<\/h3>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e developer experience \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 (\u0434\u0432\u0438\u0436\u043e\u043a + \u043a\u043b\u0438\u0435\u043d\u0442), \u0438 \u00ab\u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0439 \u043e\u0434\u043d\u043e, \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0439 \u0432\u0442\u043e\u0440\u043e\u0435 \u0432\u043d\u0443\u0442\u0440\u044c, \u043d\u0430\u0441\u0442\u0440\u043e\u0439 \u043a\u043b\u044e\u0447\u0438\u00bb \u2014 \u044d\u0442\u043e \u0431\u0430\u0440\u044c\u0435\u0440 \u0432\u0445\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0441\u0435\u043a\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u0436\u0435 \u0448\u0430\u0433\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0435\u0441\u044c \u0431\u0443\u0442\u0441\u0442\u0440\u0430\u043f \u0441\u0432\u0435\u0434\u0451\u043d \u043a \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435:<\/p>\n<pre><code class=\"bash\">curl -fsSL https:\/\/raw.githubusercontent.com\/Fighter90\/career-ops-ui\/main\/bin\/setup.sh | bash<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u0442 <strong>\u043e\u0431\u0430<\/strong> \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f (\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 career-ops \u0438 career-ops-ui \u0432\u043d\u0443\u0442\u0440\u044c \u043d\u0435\u0433\u043e), \u0441\u0442\u0430\u0432\u0438\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443 (<code>doctor<\/code>) \u0438 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 <code>http:\/\/127.0.0.1:4317<\/code> \u2014 \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u043d\u0438\u0439 \u043f\u043b\u0430\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 (\u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f <code>NO_OPEN=1<\/code> \u0434\u043b\u044f headless\/CI).<\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433, \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d \u043d\u0430 \u0433\u043b\u0430\u0433\u043e\u043b\u044b CLI:<\/p>\n<pre><code class=\"bash\">git clone https:\/\/github.com\/Fighter90\/career-ops-uicd career-ops-uinpm link                 # \u0434\u0430\u0451\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 `career-ops-ui` (\u0438\u043b\u0438 npx career-ops-ui &lt;verb&gt;)career-ops-ui setup      # \u0431\u0443\u0442\u0441\u0442\u0440\u0430\u043f: deps \u2192 doctor \u2192 run (SKIP_START=1 \u2014 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430)career-ops-ui init       # \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0438\u0437\u0430\u0440\u0434: \u0432\u044b\u0431\u043e\u0440 LLM-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 + \u043a\u043b\u044e\u0447 \u2192 \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 .envcareer-ops-ui doctor     # \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 Node \/ \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \/ \u043a\u043b\u044e\u0447\u0435\u0439 \/ Playwright (exit 0 \u21d4 \u0432\u0441\u0451 required \u0437\u0435\u043b\u0451\u043d\u043e\u0435)career-ops-ui run        # \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 http:\/\/127.0.0.1:4317career-ops-ui open       # \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0438 \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>init<\/code> \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u0431\u0437\u0430\u0446\u0430, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432. \u0412\u0438\u0437\u0430\u0440\u0434 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0432\u044b\u0431\u043e\u0440 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 (Claude \/ Gemini \/ Codex-OpenCode \/ Auto \u0441 \u0444\u043e\u043b\u0431\u044d\u043a\u043e\u043c Anthropic \u2192 Gemini); \u043a\u043b\u044e\u0447 \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0441 \u043f\u043e\u0434\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c echo \u2014 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0441\u0435\u0434\u0430\u0435\u0442 \u0432 \u0441\u043a\u0440\u043e\u043b\u043b\u0431\u044d\u043a\u0435 \u0448\u0435\u043b\u043b\u0430 \u2014 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 <code>career-ops\/.env<\/code> \u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0442 \u0436\u0435 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u043a\u043b\u0430\u0434\u043a\u0430 API-\u043a\u043b\u044e\u0447\u0435\u0439 \u0432 <code>#\/config<\/code>. \u0414\u043b\u044f CI \u0435\u0441\u0442\u044c \u043d\u0435\u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 (<code>career-ops-ui init --provider claude --anthropic-key \u2026 --yes<\/code>). \u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>LLM_PROVIDER<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0432\u0430\u0436\u0430\u044e\u0442 \u0432\u0441\u0435 live-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043e\u0446\u0435\u043d\u043a\u0438; \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u0437 UI \u0431\u0435\u0437 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<p>\u0421\u043c\u044b\u0441\u043b \u044d\u0442\u043e\u0439 \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u043d\u0435 \u0432 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0435 \u0440\u0430\u0434\u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430: \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 <code>doctor<\/code> \u0441 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c exit-\u043a\u043e\u0434\u043e\u043c \u2014 \u044d\u0442\u043e \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u0447\u0442\u043e \u0438 \u0432 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043b\u0438\u0431\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0435\u043b\u0451\u043d\u0430\u044f, \u043b\u0438\u0431\u043e \u044f\u0432\u043d\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u043b\u043e\u043c\u0430\u043d\u043e.<\/p>\n<h3>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434: \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0431\u0435\u0437 virtual DOM<\/h3>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0443 \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 <strong>\u0432\u0430\u043d\u0438\u043b\u044c\u043d\u043e\u0433\u043e ES-\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0433\u043e JavaScript \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438<\/strong>: \u043c\u043e\u0434\u0443\u043b\u0438 \u043e\u0442\u0434\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0438\u043a\u043e\u0439, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 bundler, \u0442\u0440\u0430\u043d\u0441\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0438 runtime-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a. \u041e\u0431\u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u0435, \u0430 \u043d\u0435 \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435, \u0438 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0442\u0440\u0451\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u2014 \u0430\u0443\u0434\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c. \u041a\u043b\u0438\u0435\u043d\u0442 \u043e\u043f\u0435\u0440\u0438\u0440\u0443\u0435\u0442 PII \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 egress \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b; \u043a\u043e\u0434\u043e\u0432\u0430\u044f \u0431\u0430\u0437\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0430\u044f \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0447\u0438\u0442\u0430\u0435\u043c\u0430 \u043a\u0430\u043a \u0435\u0441\u0442\u044c, \u0431\u0435\u0437 \u0441\u043b\u043e\u0451\u0432 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u043c \u0438 \u0442\u0435\u043c, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u0412\u0442\u043e\u0440\u043e\u0439 \u2014 supply chain. \u041a\u0430\u0436\u0434\u0430\u044f \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u0438\u0432\u043d\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0441\u0442\u0435\u043a\u0430 \u2014 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0435\u043a\u0442\u043e\u0440 \u0430\u0442\u0430\u043a\u0438 \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u044e\u043c\u0435; \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u044d\u0442\u0443 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0434\u0438\u043a\u0430\u043b\u044c\u043d\u043e (\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0445 \u0442\u0440\u0438: Express, js-yaml, multer). \u0422\u0440\u0435\u0442\u0438\u0439 \u2014 CSP. \u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0438\u043d\u043b\u0430\u0439\u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u0433\u0443\u044e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 <code>script-src 'self'<\/code> \u0431\u0435\u0437 <code>unsafe-inline<\/code> \u2014 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432\u044b\u0445 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0440\u043e\u0433\u043e\u0441\u0442\u0438 \u043d\u0435 \u043f\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u044e\u0442 \u0431\u0435\u0437 \u0443\u0445\u0438\u0449\u0440\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0426\u0435\u043d\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043d\u044f\u0442\u043d\u0430: \u043d\u0435\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u043d\u0435\u0442 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0447\u0430\u0441\u0442\u044c \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u0440\u0443\u043a\u0430\u043c\u0438. \u041e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u0430 \u043b\u0438 \u0446\u0435\u043d\u0430 \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044e \u0432 \u043a\u043e\u043d\u0446\u0435.<\/p>\n<h4>\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u043e\u043a\u0443\u0441\u043e\u043c<\/h4>\n<p>\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u2014 hash-based SPA (<code>router.js<\/code>). \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b: \u0442\u0430\u0431\u043b\u0438\u0446\u0430 ALIASES \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0445 \u043f\u0443\u0442\u0435\u0439 (\u043d\u0430\u043f\u0440. <code>#\/settings \u2192 #\/profile<\/code>, <code>#\/portals \u2192 #\/config<\/code>) \u2014 \u0441\u0442\u0430\u0440\u044b\u0435 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0435 \u043b\u043e\u043c\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432; \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0432\u044c\u044e\u0445\u0430 <code>__not_found__<\/code> \u2014 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 hash \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u0441\u044f \u0432 \u0447\u0435\u0441\u0442\u043d\u0443\u044e 404, \u0430 \u043d\u0435 \u043c\u043e\u043b\u0447\u0430 \u0432 \u0434\u0430\u0448\u0431\u043e\u0440\u0434; <code>router.current()<\/code> \u0441\u0440\u0435\u0437\u0430\u0435\u0442 <code>?query<\/code> \u0434\u043e \u0440\u0435\u0437\u043e\u043b\u0432\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430.<\/p>\n<p>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u043e\u043a\u0443\u0441\u043e\u043c \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043e \u0432 <code>focusNewView<\/code>: \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0430 \u0444\u043e\u043a\u0443\u0441 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 <code>&lt;h1&gt;<\/code> (fallback \u2014 \u043d\u0430 \u043a\u043e\u043d\u0442\u0435\u043d\u0442), \u0438 \u044d\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0431\u043e\u0438\u0445 \u043f\u0443\u0442\u044f\u0445 \u0440\u0435\u043d\u0434\u0435\u0440\u0430 \u2014 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u043c \u0438 \u043e\u0448\u0438\u0431\u043e\u0447\u043d\u043e\u043c. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0441\u043a\u0440\u0438\u043d\u0440\u0438\u0434\u0435\u0440\u0430 \u043f\u0440\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043e\u0448\u0438\u0431\u043e\u043a. \u041f\u0435\u0440\u0432\u044b\u0439 paint \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u043e\u043a\u0443\u0441\u0430 \u043d\u0435 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432\u0430\u043b \u0441\u043e skip-link (WCAG 2.4.3, focus order).<\/p>\n<h4>\u0421\u043b\u043e\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f: \u043f\u0440\u044f\u043c\u043e\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 DOM<\/h4>\n<p>Virtual DOM \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442. \u0412\u044c\u044e\u0445\u0438 (<code>public\/js\/views\/*<\/code> \u2014 \u043f\u043e \u043c\u043e\u0434\u0443\u043b\u044e \u043d\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442) \u0441\u0442\u0440\u043e\u044f\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0435\u0432\u043e \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 \u0445\u0435\u043b\u043f\u0435\u0440\u044b-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432; \u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u0431\u0449\u0438\u0439 <code>field()<\/code>-\u0445\u0435\u043b\u043f\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 <code>&lt;label&gt;<\/code> \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u0447\u0435\u0440\u0435\u0437 <code>htmlFor<\/code>\/<code>id<\/code> \u043b\u0438\u0431\u043e <code>aria-labelledby<\/code>. \u0426\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0441\u0432\u044f\u0437\u043a\u0438 \u043f\u043e\u043a\u0440\u044b\u0442\u0430 \u0442\u0435\u0441\u0442\u043e\u043c unbound-label-sweep: \u043a\u0430\u0436\u0434\u044b\u0439 <code>htmlFor<\/code>\/<code>aria-labelledby<\/code> \u043e\u0431\u044f\u0437\u0430\u043d \u0438\u043c\u0435\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 <code>id<\/code> \u0432 \u0442\u043e\u043c \u0436\u0435 \u0444\u0430\u0439\u043b\u0435 \u2014 \u00ab\u043e\u0442\u043e\u0440\u0432\u0430\u043d\u043d\u044b\u0439\u00bb \u043b\u0435\u0439\u0431\u043b \u043b\u043e\u043c\u0430\u0435\u0442 CI, \u0430 \u043d\u0435 \u0442\u0438\u0445\u043e \u0434\u0435\u0433\u0440\u0430\u0434\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u041b\u043e\u043a\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0438 aria-\u043c\u0435\u0442\u043a\u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b <code>data-i18n<\/code> \u0438 <code>data-i18n-aria-label<\/code>; \u043f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u044f\u0437\u044b\u043a\u0430 <code>setLang<\/code> \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443 \u0438 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u2014 \u0431\u0435\u0437 \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u0440\u0435-\u0440\u0435\u043d\u0434\u0435\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u043c\u0435\u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u0438 \u043d\u0435 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0444\u043e\u0440\u043c \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0441\u043a\u0440\u043e\u043b\u043b\u0430. \u0422\u044f\u0436\u0451\u043b\u044b\u0435 \u0441\u043f\u0438\u0441\u043a\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f: \u0432\u044c\u044e\u0445\u0430 pipeline \u043f\u0440\u0438 \u0447\u0438\u0441\u043b\u0435 \u0441\u0442\u0440\u043e\u043a \u0441\u0432\u044b\u0448\u0435 ~1000 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442 \u043e\u043a\u043e\u043d\u043d\u044b\u0439 \u0441\u043b\u0430\u0439\u0441 \u0441 scroll-\u043b\u0438\u0441\u0442\u0435\u043d\u0435\u0440\u043e\u043c (\u043f\u043e\u0440\u043e\u0433 \u0438 \u0447\u0438\u0441\u0442\u0430\u044f \u043e\u043a\u043e\u043d\u043d\u0430\u044f \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u043f\u043e\u043a\u0440\u044b\u0442\u044b \u0442\u0435\u0441\u0442\u0430\u043c\u0438 pipeline-virtualize); \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0441\u043a\u0430\u043d\u0430 \u043f\u0430\u0433\u0438\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e 200 \u0441\u0442\u0440\u043e\u043a (\u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<h4>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 API-\u0441\u043b\u043e\u0439 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 SSE<\/h4>\n<p>\u0421\u0435\u0442\u0435\u0432\u043e\u0439 \u0441\u043b\u043e\u0439 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d \u0432 <code>api.js<\/code>. <code>API.stream<\/code> \u2014 \u043e\u0431\u0451\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 EventSource \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u043c \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435\u043c \u043f\u043e \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u044e (\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 <code>done.final<\/code> \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043e \u0441\u043a\u0430\u043d\u0435\u0440\u0435). \u0411\u0443\u0444\u0435\u0440\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u0434\u0443\u0442 \u0447\u0435\u0440\u0435\u0437 \u0435\u0434\u0438\u043d\u044b\u0439 fetch-\u0445\u0435\u043b\u043f\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u0443\u043c\u0430\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438 \u044d\u0441\u043a\u0430\u043b\u0438\u0440\u0443\u0435\u0442 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u0441\u0431\u043e\u0439 \u0432 <code>role=alert<\/code>-\u0431\u043b\u043e\u043a, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043e\u0442 \u0442\u0435\u043b\u0430 \u043f\u0440\u0435\u0432\u044c\u044e. \u0420\u0435\u043d\u0434\u0435\u0440 markdown \u2014 <code>UI.md()<\/code>: \u044d\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f XSS-\u0433\u0440\u0430\u043d\u0438\u0446\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0430\u044f \u0438\u043d\u043b\u0430\u0439\u043d-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 (bold\/code\/links, \u0432 \u0442. \u0447. \u0432\u043d\u0443\u0442\u0440\u0438 blockquote) \u0432 \u0441\u0430\u043d\u0438\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 DOM. \u041f\u0430\u0433\u0438\u043d\u0430\u0442\u043e\u0440 \u2014 <code>UI.paginate<\/code> (PAGE_SIZE, \u0441\u043b\u0430\u0439\u0441 \u043f\u043e \u043f\u043e\u043b\u043d\u043e\u043c\u0443 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u043d\u0430\u0431\u043e\u0440\u0443, <code>controls()<\/code> \u0434\u043b\u044f \u0441\u0432\u043e\u0434\u043a\u0438 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430). \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u2014 focus-trapped <code>UI.confirm()<\/code> (\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 <code>confirm()<\/code> \u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0451\u043d \u2014 \u043e\u043d \u043d\u0435\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0438 \u0434\u043b\u044f \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043d\u0438 \u0434\u043b\u044f a11y); <code>UI.modal()<\/code> \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u0433\u0430\u0441\u0438\u0442 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441-\u0442\u043e\u0441\u0442 (defence-in-depth \u043e\u0442 \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043b\u043e\u0451\u0432).<\/p>\n<p>\u041f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 SSE \u043d\u0430 \u0432\u044c\u044e\u0445\u0435 \u0441\u043a\u0430\u043d\u0430: <code>runScanAll<\/code> \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 live-\u043f\u043e\u043b\u043b\u0438\u043d\u0433 \u043a\u0430\u0436\u0434\u044b\u0435 2.5 \u0441 \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 refresh \u0447\u0435\u0440\u0435\u0437 300 \u043c\u0441 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e done \u2014 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043a\u0430\u043d\u0430 \u0431\u0435\u0437 \u0440\u0443\u0447\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041b\u043e\u0433-\u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0441\u043a\u0430\u043d\u0430 \u2014 <code>aria-live role=log<\/code>, \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u043d\u043e-\u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0440\u0443\u0435\u043c\u0430\u044f; \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u043d\u043e\u043d\u0441\u044b \u0432\u044b\u0432\u0435\u0434\u0435\u043d\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 assertive-\u0440\u0435\u0433\u0438\u043e\u043d, \u0447\u0442\u043e\u0431\u044b \u0432\u0430\u0436\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0435 \u0442\u043e\u043d\u0443\u043b\u0438 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 \u043b\u043e\u0433\u0430. Run-state \u0434\u0438\u0437\u0435\u0439\u0431\u043b\u0438\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 Scan \u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>aria-busy<\/code>; Stop \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 EventSource; \u043f\u0440\u0438 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u0435 \u2014 persistent <code>role=alert<\/code>-\u0431\u0430\u043d\u043d\u0435\u0440 \u0441 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435\u043c Retry.<\/p>\n<h4>\u041b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435<\/h4>\n<p>i18n \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 <code>i18n.js<\/code> + \u0441\u043b\u043e\u0432\u0430\u0440\u0438 <code>i18n-dict.&lt;locale&gt;.js<\/code> (13 \u043b\u043e\u043a\u0430\u043b\u0435\u0439, per-locale split-\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0442\u044f\u043d\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u043e\u0439 \u0441\u043b\u043e\u0432\u0430\u0440\u044c, \u0430 \u043d\u0435 \u0432\u0441\u0435 \u0442\u0440\u0438\u043d\u0430\u0434\u0446\u0430\u0442\u044c). <code>setLang<\/code> \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>document.documentElement.lang<\/code> \u043f\u0440\u0438 boot \u0438 \u043f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u044f\u0437\u044b\u043a\u0430, \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0442 <code>navigator.language<\/code> \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435, \u0438 \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0438\u0442 \u0432\u044b\u0431\u043e\u0440 \u0432 <code>localStorage['career-ops-ui:lang']<\/code>. \u0414\u043b\u044f <code>ar<\/code> \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>dir=\"rtl\"<\/code> \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f <code>[dir=\"rtl\"]<\/code>-\u0431\u043b\u043e\u043a CSS, \u0437\u0435\u0440\u043a\u0430\u043b\u044f\u0449\u0438\u0439 \u0445\u0440\u043e\u043c; \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 \u043b\u044e\u0431\u0443\u044e LTR-\u043b\u043e\u043a\u0430\u043b\u044c dir \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 <code>\"ltr\"<\/code>. \u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043a\u0438 \u2014 <code>Intl.RelativeTimeFormat<\/code> \u0441 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u044e: \u00ab2 \u0447\u0430\u0441\u0430 \u043d\u0430\u0437\u0430\u0434\u00bb \u043d\u0430 ru, \u00abvor 2 Stunden\u00bb-\u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u044b \u043d\u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u2014 \u0431\u0435\u0437 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u044b\u0445 \u043f\u043b\u044e\u0440\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439.<\/p>\n<h4>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043a\u044d\u0448 \u0438 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u2014 \u0432 localStorage: <code>lang<\/code>, <code>theme<\/code>, <code>career-ops-ui:scan:favorites<\/code> (\u0438\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u043f\u043e URL), <code>career-ops-ui:scan:saved-searches<\/code> (\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0431\u043e\u0440\u044b \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432). \u041f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u0430 <code>scan-prefs.js<\/code> \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442 \u043a\u044d\u0448 \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0438: \u043f\u043e\u0432\u0440\u0435\u0436\u0434\u0451\u043d\u043d\u044b\u0439 \u0438\u043b\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 JSON \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0443\u0441\u0442\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0430 \u043d\u0435 \u0440\u043e\u043d\u044f\u0435\u0442 \u0432\u044c\u044e\u0445\u0443 \u2014 localStorage \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0447\u0435\u0440\u0435\u0437 DevTools, \u0437\u043d\u0430\u0447\u0438\u0442 \u044d\u0442\u043e \u043d\u0435\u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0439 \u0432\u0445\u043e\u0434. \u041a\u044d\u0448 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0441\u043a\u0430\u043d\u0430 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u0441\u043a\u0430\u043d\u0430 \u0438 \u0434\u043e\u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u0445\u043e\u0434\u0443. \u0414\u0435\u0442\u0435\u043a\u0446\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u044b \u0434\u043b\u044f country-\u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u2014 <code>countries.js<\/code>, \u043a\u043e\u043d\u0441\u0435\u0440\u0432\u0430\u0442\u0438\u0432\u043d\u0430\u044f (\u043d\u0435 \u0443\u0433\u0430\u0434\u044b\u0432\u0430\u0435\u0442; pure-remote \u0438 \u043d\u0435\u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0435 \u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0434 \u00abAll countries\u00bb \u2014 \u043b\u043e\u0436\u043d\u043e\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0430 \u0445\u0443\u0436\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439). \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u2014 \u0445\u0435\u043b\u043f\u0435\u0440\u044b <code>skills.js<\/code> (<code>salaryInRange<\/code>, <code>detectTech<\/code>, <code>detectLevel<\/code>, <code>rowMatches<\/code>, <code>computeFacets<\/code>).<\/p>\n<h4>\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u0438 CSP<\/h4>\n<p>\u0412\u0441\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u2014 <code>addEventListener<\/code>; \u0438\u043d\u043b\u0430\u0439\u043d\u043e\u0432\u044b\u0445 <code>on*=<\/code>-\u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043d\u0435\u0442, \u0447\u0442\u043e \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u0440\u0436\u0430\u0442\u044c <code>script-src 'self'<\/code> \u0431\u0435\u0437 <code>unsafe-inline<\/code>. \u0422\u0435\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u043d\u0430 CSS custom properties (\u0434\u0438\u0437\u0430\u0439\u043d-\u0442\u043e\u043a\u0435\u043d\u044b), \u0430 \u043d\u0435 \u043d\u0430 \u0445\u0430\u0440\u0434\u043a\u043e\u0434-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445; light\/dark \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0438\u0442\u0441\u044f, <code>prefers-reduced-motion<\/code> \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f. \u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u0434\u0440\u0430\u0432\u0435\u0440 (&lt;900px) \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e: \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0441 \u0430\u0432\u0442\u043e\u0440\u0441\u043a\u0438\u043c <code>display:flex|grid<\/code> \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <code>[hidden]<\/code> \u2014 no-op, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u044f\u0432\u043d\u043e\u0435 <code>.sel[hidden]{display:none}<\/code>. \u0422\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b: <code>th[scope=col]<\/code>, \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u2014 button-in-th \u0441 <code>aria-sort<\/code> \u0438 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u25b2\/\u25bc (<code>aria-hidden<\/code>). \u0422\u0430\u0447-\u0442\u0430\u0440\u0433\u0435\u0442\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 WCAG 2.5.5\/2.5.8, \u0444\u043e\u043a\u0443\u0441 \u2014 <code>:focus-visible<\/code>, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u043e\u043a\u0443\u0441\u0430 \u043d\u0435 \u0440\u0438\u0441\u0443\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u0439 ring.<\/p>\n<h3>\u0411\u044d\u043a\u0435\u043d\u0434<\/h3>\n<p>Node.js, ESM. <code>server\/index.mjs<\/code> \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0440\u043e\u0443\u0442\u044b <code>server\/lib\/routes\/*<\/code> (scan, pipeline, tracker, llm, openrouter, reports, runners, config, health, help, activity). \u041f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u044b <code>server\/lib\/<\/code>: <code>safe-fetch.mjs<\/code> (DNS-pinned egress), <code>security.mjs<\/code>, <code>scan-sanitize.mjs<\/code>, <code>rate-limit.mjs<\/code>, <code>file-lock.mjs<\/code>, <code>http-json.mjs<\/code>, <code>runner.mjs<\/code> (<code>runNodeScript<\/code>\/<code>streamNodeScript<\/code>), <code>paths.mjs<\/code> (PATHS \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u2014 \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 \u0431\u0430\u0433\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u0438\u0434\u0438\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u043a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430). PDF \u2014 <code>generate-pdf.mjs<\/code> (headless-chromium, A4, embedded-\u0448\u0440\u0438\u0444\u0442\u044b, ATS-\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0438\u043f\u043e\u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u2014 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0437\u044e\u043c\u0435 \u043e\u0431\u044f\u0437\u0430\u043d\u043e \u043f\u0430\u0440\u0441\u0438\u0442\u044c\u0441\u044f \u0440\u043e\u0431\u043e\u0442\u0430\u043c\u0438-\u0441\u043a\u0440\u0438\u043d\u0435\u0440\u0430\u043c\u0438, \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c). CI \u2014 GitHub Actions, \u043c\u0430\u0442\u0440\u0438\u0446\u0430 Node 18\/20\/22 + CodeQL; \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 hard gate \u2014 <code>ci.yml<\/code>.<\/p>\n<h3>\u0421\u043a\u0430\u043d\u0435\u0440: \u0434\u0432\u0430 \u0440\u0435\u0435\u0441\u0442\u0440\u0430 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u0432 \u0438 \u0434\u0432\u0443\u0445\u0444\u0430\u0437\u043d\u044b\u0439 SSE<\/h3>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/94\/56\/bf\/9456bff657c50c48ce3fd203d4f73726.png\" alt=\"\u0420\u0438\u0441. 2. \u041a\u043e\u043d\u0432\u0435\u0439\u0435\u0440: scan \u2192 evaluate \u2192 apply \u2192 track. \u041d\u0430\u0434 \u043d\u0438\u043c \u2014 \u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440 \u0440\u0435\u043f\u043e\u0441\u0442\u043e\u0432, re-apply cooldown, compensation \u2192 pipeline.md.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/94\/56\/bf\/9456bff657c50c48ce3fd203d4f73726.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/94\/56\/bf\/9456bff657c50c48ce3fd203d4f73726.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441. 2. \u041a\u043e\u043d\u0432\u0435\u0439\u0435\u0440: scan \u2192 evaluate \u2192 apply \u2192 track. \u041d\u0430\u0434 \u043d\u0438\u043c \u2014 \u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440 \u0440\u0435\u043f\u043e\u0441\u0442\u043e\u0432, re-apply cooldown, compensation \u2192 pipeline.md.<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0441\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0435\u0434\u0438\u043d\u044b\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440: normalize \u2192 filter (<code>title_filter.positive<\/code>\/<code>negative<\/code>) \u2192 dedup \u043f\u0440\u043e\u0442\u0438\u0432 <code>data\/scan-history.tsv<\/code> + <code>data\/pipeline.md<\/code> + <code>data\/applications.md<\/code> \u2192 append \u0432 <code>data\/pipeline.md<\/code>. \u0414\u0435\u0434\u0443\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0442\u0438\u0432 \u0442\u0440\u0451\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0440\u0430\u0437\u0443 \u0440\u0435\u0448\u0430\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u0431\u043e\u043b\u044c: \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0443\u0436\u0435 \u0431\u044b\u043b \u043e\u0442\u043a\u043b\u0438\u043a, \u043d\u0435 \u0432\u0441\u043f\u043b\u044b\u0432\u0451\u0442 \u043a\u0430\u043a \u00ab\u043d\u043e\u0432\u0430\u044f\u00bb, \u043f\u043e\u0434 \u043a\u0430\u043a\u0438\u043c \u0431\u044b URL \u0435\u0451 \u043d\u0438 \u043f\u0435\u0440\u0435\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043b\u0438.<\/p>\n<h4>\u0420\u0435\u0435\u0441\u0442\u0440 auto-discovery \u0438 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 fetch-\u0440\u0435\u0435\u0441\u0442\u0440<\/h4>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0440\u0430\u0437\u0432\u0435\u0434\u0435\u043d\u044b \u043d\u0430 \u0434\u0432\u0430 \u0440\u0435\u0435\u0441\u0442\u0440\u0430. <code>server\/lib\/sources\/registry.mjs<\/code> \u2014 auto-discovery \u043f\u043e meta-\u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0443: \u0434\u0440\u0430\u0439\u0432\u0438\u0442 \u0434\u0440\u043e\u043f\u0434\u0430\u0443\u043d <code>#\/scan<\/code>, <code>GET \/api\/scan\/sources<\/code> \u0438 RU-\u0434\u0438\u0441\u043f\u0430\u0442\u0447. <code>server\/lib\/portals\/registry.mjs<\/code> (<code>ALL_ADAPTERS<\/code>, hand-maintained) \u2014 \u0442\u043e, \u0447\u0442\u043e EN-\u0441\u043a\u0430\u043d\u0435\u0440 \u043e\u0431\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0444\u0435\u0442\u0447\u0435: <code>matches \u2192 buildEndpoint \u2192 fetch<\/code>. \u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442: <code>buildEndpoint(company)<\/code> \u043e\u0431\u044f\u0437\u0430\u043d \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443-URL; falsy-\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>resolveAdapter<\/code> \u0442\u0440\u0430\u043a\u0442\u0443\u0435\u0442 \u043a\u0430\u043a \u00ab\u043d\u0435\u0442 \u043c\u0430\u0442\u0447\u0430\u00bb \u0438 \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0437 \u043e\u0431\u0445\u043e\u0434\u0430.<\/p>\n<blockquote>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u0435\u0444\u0435\u043a\u0442\u0430: \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 meta-\u0440\u0435\u0435\u0441\u0442\u0440\u0435 (\u0432\u0438\u0434\u0435\u043d \u0432 \u0434\u0440\u043e\u043f\u0434\u0430\u0443\u043d\u0435), \u043d\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 <code>ALL_ADAPTERS<\/code> \u2014 \u0438 \u043d\u0435 \u0444\u0435\u0442\u0447\u0438\u0442\u0441\u044f. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a, \u0441\u043a\u0430\u043d \u00ab\u0443\u0441\u043f\u0435\u0448\u043d\u043e\u00bb \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f, \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 \u043d\u0435\u0442 \u2014 worst case \u0442\u0438\u0445\u043e\u0439 \u0434\u0435\u0433\u0440\u0430\u0434\u0430\u0446\u0438\u0438. \u0418\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d <code>adapter-registry.test.mjs<\/code>: \u0434\u043b\u0438\u043d\u0430 <code>ALL_ADAPTERS<\/code>, sorted-id, assert \u043f\u043e\u043b\u043d\u043e\u0433\u043e EN-\u043d\u0430\u0431\u043e\u0440\u0430. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e EN-\u0431\u043e\u0440\u0434\u0430 \u0431\u0435\u0437 \u043f\u0440\u0430\u0432\u043a\u0438 \u043e\u0431\u043e\u0438\u0445 \u0440\u0435\u0435\u0441\u0442\u0440\u043e\u0432 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043a\u0440\u0430\u0441\u043d\u043e\u043c\u0443 CI.<\/p>\n<\/blockquote>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/5c\/e2\/b4\/5ce2b47172c82ce6f83e159a44d5fe2a.png\" alt=\"\u0420\u0438\u0441. 3. sources\/registry (dropdown, auto-discovery) \u0438 portals\/registry ALL_ADAPTERS (fetch, hand-maintained).\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/5c\/e2\/b4\/5ce2b47172c82ce6f83e159a44d5fe2a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/5c\/e2\/b4\/5ce2b47172c82ce6f83e159a44d5fe2a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441. 3. sources\/registry (dropdown, auto-discovery) \u0438 portals\/registry ALL_ADAPTERS (fetch, hand-maintained).<\/figcaption><\/div>\n<\/figure>\n<h4>\u0414\u0432\u0443\u0445\u0444\u0430\u0437\u043d\u044b\u0439 SSE \u0441 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435\u043c<\/h4>\n<p><code>GET \/api\/stream\/scan<\/code> \u044d\u043c\u0438\u0442\u0438\u0442 <code>start \/ log \/ progress \/ done \/ error<\/code>. \u041f\u0440\u0438 <code>source=both<\/code> \u0444\u0430\u0437\u0430 ATS \u0438 \u0444\u0430\u0437\u0430 \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u0440\u0442\u0430\u043b\u043e\u0432 \u0438\u0434\u0443\u0442 \u043e\u0434\u043d\u0438\u043c \u0441\u0442\u0440\u0438\u043c\u043e\u043c; \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0444\u043b\u0430\u0433\u043e\u043c <code>final<\/code> \u0432 done:<\/p>\n<pre><code>source=both:  done { final:false }   \/\/ \u043a\u043e\u043d\u0435\u0446 ATS-\u0444\u0430\u0437\u044b, \u043f\u043e\u0442\u043e\u043a \u041d\u0415 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f  start                  \/\/ ru-scanner \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u041f\u041e\u0421\u041b\u0415 done ATS  done { final:true }    \/\/ \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043a\u043b\u0438\u0435\u043d\u0442 API.stream:  done.final === false  -&gt; EventSource \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c  done \u0431\u0435\u0437 \u043f\u043e\u043b\u044f final   -&gt; \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 (backward-compat \u0441\u043e \u0441\u0442\u0430\u0440\u044b\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442 \u0434\u0435\u0444\u0435\u043a\u0442, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043a\u043b\u0438\u0435\u043d\u0442 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u043b EventSource \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c done \u0438 \u043e\u0431\u0440\u044b\u0432\u0430\u043b \u0432\u0442\u043e\u0440\u0443\u044e \u0444\u0430\u0437\u0443: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u0442\u043e\u043b\u044c\u043a\u043e EN-\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0438 \u043d\u0435 \u0437\u043d\u0430\u043b, \u0447\u0442\u043e RU-\u0444\u0430\u0437\u0430 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0430\u0441\u044c. \u0412\u0435\u0442\u043a\u0430 \u00abdone \u0431\u0435\u0437 final\u00bb \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0430 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u2014 \u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043e\u0431\u044f\u0437\u0430\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u0438\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441\u0442\u0430\u0440\u043e\u0439. \u041c\u0435\u0436\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u043f\u0430\u0443\u0437\u044b \u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0447\u0435\u0440\u0435\u0437 abort-aware <code>delay(ms, signal)<\/code>: \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0438 <code>{once:true}<\/code>-\u043b\u0438\u0441\u0442\u0435\u043d\u0435\u0440 \u043d\u0430 AbortSignal \u0441\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043c\u0443 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0432\u0448\u0435\u043c\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u044e (\u043d\u0435\u0442 orphan-\u0442\u0430\u0439\u043c\u0435\u0440\u043e\u0432 \u043f\u0440\u0438 Stop).<\/p>\n<h4>\u041f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u044f \u0438 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0444\u0435\u0442\u0447\u0430<\/h4>\n<p>\u0421\u0438\u043c\u0432\u043e\u043b <code>MAX_STORED_RESULTS<\/code> \u0443\u0434\u0430\u043b\u0451\u043d: \u0441\u043a\u0430\u043d\u0435\u0440 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432\u0435\u0441\u044c \u043c\u0430\u0442\u0447-\u0441\u0435\u0442 \u2014 \u043e\u0431\u0440\u0435\u0437\u043a\u0430 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043e\u0437\u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u044b, \u0447\u0442\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u043e \u0443\u0441\u0435\u0447\u0451\u043d\u043d\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c. <code>scan.js<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>pager.slice(sortedAll)<\/code> \u0441 PAGE_SIZE=200 \u043f\u043e \u043f\u043e\u043b\u043d\u043e\u043c\u0443 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u043d\u0430\u0431\u043e\u0440\u0443 (\u043d\u0435 <code>rows.slice(0,200)<\/code>); \u0444\u0438\u043b\u044c\u0442\u0440 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u0430\u0433\u0438\u043d\u0430\u0442\u043e\u0440 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 1. \u0424\u0435\u0442\u0447 fail-soft \u2014 \u043e\u0434\u0438\u043d \u0443\u043f\u0430\u0432\u0448\u0438\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043d\u0435 \u0441\u0440\u044b\u0432\u0430\u0435\u0442 \u0441\u043a\u0430\u043d \u043f\u043e 40 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c: <code>fetchJson<\/code> \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043d\u0435-JSON 2xx \u043a\u0430\u043a <code>non-JSON 2xx response from &lt;url&gt;<\/code>; Workday CXS \u043d\u0430 403\/429\/HTML \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>[]<\/code> \u0441 \u043f\u0440\u0438\u0447\u0438\u043d\u043e\u0439 (<code>strict:true<\/code> \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 throw); <code>title_filter<\/code> \u043c\u0430\u0442\u0447\u0438\u0442 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0435 \u0430\u043a\u0440\u043e\u043d\u0438\u043c\u044b \u043f\u043e word-boundary (\u043d\u0435\u0433\u0430\u0442\u0438\u0432 <code>coo<\/code> \u043d\u0435 \u0434\u0440\u043e\u043f\u0430\u0435\u0442 \u00abCoordinator\u00bb), \u043f\u0443\u0441\u0442\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0442\u0440\u0438\u043c\u043c\u044f\u0442\u0441\u044f \u0434\u043e length-\u0447\u0435\u043a\u0430.<\/p>\n<h3>SSRF-envelope \u0438 \u0441\u0430\u043d\u0438\u0442\u0430\u0439\u0437\u0435\u0440\u044b<\/h3>\n<p>\u0421\u0435\u0440\u0432\u0435\u0440 \u043f\u043e \u0441\u0432\u043e\u0435\u0439 \u043f\u0440\u0438\u0440\u043e\u0434\u0435 \u0444\u0435\u0442\u0447\u0438\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 URL \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 pipeline \u2014 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c SSRF. <code>isValidJobUrl()<\/code> \u0433\u0435\u0439\u0442\u0438\u0442 <code>\/api\/pipeline<\/code> \u0438 <code>...\/preview<\/code>: \u0440\u0435\u0434\u0436\u0435\u043a\u0442\u0438\u0442 127\/8, RFC1918, CGNAT 100.64\/10, link-local + IMDS 169.254.169.254, 0.0.0.0, IPv6 loopback\/ULA\/link-local, \u0441\u0445\u0435\u043c\u044b <code>file:<\/code>\/<code>data:<\/code>\/<code>javascript:<\/code>, \u043f\u0430\u0440\u043d\u044b\u0435 \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b <code>${...}<\/code>\/<code>{{...}}<\/code>. Egress \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 <code>safeGet()<\/code>:<\/p>\n<pre><code>safeGet(url):  1. \u043e\u0434\u0438\u043d DNS-lookup; \u0440\u0435\u0437\u043e\u043b\u0432 \u0432 private\/loopback\/IMDS -&gt; reject (fail-CLOSED)  2. PIN: \u043a\u043e\u043d\u043d\u0435\u043a\u0442 \u043d\u0430 \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 IP \u2014 \u043d\u0435\u0442 TOCTOU-rebind \u043c\u0435\u0436\u0434\u0443 lookup \u0438 connect  3. \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0435 \u0446\u0435\u043b\u044c \u0440\u0435-\u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u0441\u044f \u0438 \u0440\u0435-\u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f; cap 3 \u0445\u043e\u043f\u0430  4. \u0442\u0435\u043b\u043e \u0443\u0441\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e opts.maxBytes (streaming-cap)\u0432\u0441\u0435 41 fetcher: redirect:'error'; per-tenant ATS \u043f\u0438\u043d\u044f\u0442 host \u0430\u043d\u043a\u043e\u0440\u0435\u043d\u043d\u044b\u043c regex \u0434\u043e \u0444\u0435\u0442\u0447\u0430<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>DNS-pinning \u0437\u0434\u0435\u0441\u044c \u2014 \u043d\u0435 \u043f\u0430\u0440\u0430\u043d\u043e\u0439\u044f: \u0431\u0435\u0437 \u043f\u0438\u043d\u0430 \u043c\u0435\u0436\u0434\u0443 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u044e\u0449\u0438\u043c lookup \u0438 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c connect \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u0434\u043b\u044f rebind-\u0430\u0442\u0430\u043a\u0438, \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u043c\u0435\u043d \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u0441\u044f \u0432 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 IP \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0438 \u0432 169.254.169.254 \u043d\u0430 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0435.<\/p>\n<p>\u0421\u0430\u043d\u0438\u0442\u0430\u0439\u0437\u0435\u0440\u044b \u0440\u0430\u0437\u043d\u0435\u0441\u0435\u043d\u044b \u043f\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u043c: XSS-ingress \u2014 <code>stripDangerousMarkdown()<\/code> + <code>UI.md()<\/code> (CV\/markdown), <code>sanitizeJobDescription()<\/code> (JD), <code>sanitizePathName()<\/code> (slug: \u0441\u0442\u0440\u0438\u043f leading-dots, drop slashes\/NUL\/control, 200-char cap). Egress \u0432 <code>scan-history.tsv<\/code>: <code>normalizeScanScalar<\/code> \u0441\u0445\u043b\u043e\u043f\u044b\u0432\u0430\u0435\u0442 <code>\\r \\n \\t \\v \\f<\/code> U+2028 U+2029; <code>sanitizeTsvField<\/code> \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0438\u043d\u044a\u0435\u043a\u0446\u0438\u044e TSV-\u0441\u0442\u0440\u043e\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 newline \u0438 \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u0438\u0437\u0443\u0435\u0442 formula-injection-\u043f\u0440\u0435\u0444\u0438\u043a\u0441\u044b (<code>= + - @<\/code>) \u2014 \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0441\u043a\u0430\u043d\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0432 Excel, \u0430 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044f \u0441 \u0442\u0430\u0439\u0442\u043b\u043e\u043c <code>=HYPERLINK(...)<\/code> \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0438\u0437 \u043d\u0435\u0434\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430.<\/p>\n<blockquote>\n<p>\u0413\u0440\u0430\u043d\u0438\u0446\u0430 \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0441\u043f\u0435\u043a\u0435 \u043a\u0430\u043a \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442: <code>cleanLlmMarkdown<\/code> \u2014 \u043d\u0435 XSS-\u0441\u0430\u043d\u0438\u0442\u0430\u0439\u0437\u0435\u0440; scan-sanitize \u2014 egress, \u0430 \u043d\u0435 XSS-\u0433\u0440\u0430\u043d\u0438\u0446\u0430. \u0421\u043c\u0435\u0448\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c (\u00ab\u044d\u0442\u043e\u0442 \u0432\u0445\u043e\u0434 \u0443\u0436\u0435 \u043f\u043e\u0447\u0438\u0449\u0435\u043d\u00bb \u2014 \u0442\u0435\u043c \u0441\u0430\u043d\u0438\u0442\u0430\u0439\u0437\u0435\u0440\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0447\u0438\u0441\u0442\u0438\u0442 \u0434\u0440\u0443\u0433\u043e\u0435), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u0430\u0436\u0434\u0430\u044f \u0433\u0440\u0430\u043d\u0438\u0446\u0430 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0430 \u0438 \u043f\u043e\u043a\u0440\u044b\u0442\u0430 \u0442\u0435\u0441\u0442\u043e\u043c.<\/p>\n<\/blockquote>\n<p>HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438: <code>script-src 'self'<\/code> (\u0431\u0435\u0437 unsafe-*), <code>frame-ancestors 'none'<\/code>, <code>object-src 'none'<\/code>, nosniff, <code>X-Frame-Options: DENY<\/code>, <code>Referrer-Policy: same-origin<\/code>; \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 CSP \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430 loopback, ::1, localhost, 0.0.0.0 (<code>security-headers.test.mjs<\/code>). <code>llmRateLimit<\/code> \u2014 no-op \u043d\u0430 loopback, \u0430\u043a\u0442\u0438\u0432\u0435\u043d \u043f\u0440\u0438 <code>HOST=0.0.0.0<\/code> (11-\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u2192 429, \u0431\u0430\u043a\u0435\u0442\u044b \u043f\u043e IP): \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043b\u0438\u043c\u0438\u0442\u044b \u043d\u0435 \u043d\u0443\u0436\u043d\u044b, \u0430 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0432 LAN \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0443\u0436\u0435 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0437\u0430\u0449\u0438\u0442\u0435. \u0417\u0430\u043f\u0438\u0441\u044c \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u2014 \u043f\u043e\u0434 <code>withFileLock<\/code> (\u0442\u0435\u0441\u0442 \u043d\u0430 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c).<\/p>\n<h3>i18n: 13 \u043b\u043e\u043a\u0430\u043b\u0435\u0439, RTL \u0438 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441\u043f\u0440\u0430\u0432\u043a\u0438<\/h3>\n<p>\u041b\u043e\u043a\u0430\u043b\u0438: en, es, pt-BR, ko, ja, ru, zh-CN, zh-TW, fr, pl, uk, da, ar. \u0413\u0435\u0439\u0442\u044b \u043f\u0430\u0440\u0438\u0442\u0435\u0442\u0430: i18n-locale-files (snapshot + key parity), i18n-coverage, i18n-no-latin-leaks, i18n-no-personal-data (\u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0438 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0443\u0442\u0435\u0447\u044c \u043d\u0438 \u043e\u0434\u0438\u043d \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0437\u044e\u043c\u0435), lang-switcher-rtl. \u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u2014 13 markdown-\u0431\u0430\u043d\u0434\u043b\u043e\u0432 (<code>GET \/api\/help\/&lt;lang&gt;<\/code>) \u0441 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c 19 H2 \/ 75 H3 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c (canonical-docs-coverage + help-ui), \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u0435\u0434\u0438\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u043f\u0440\u0430\u0432\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u044f\u0437\u044b\u043a\u0430\u043c\u0438: \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0430 \u043c\u043e\u043b\u0447\u0430 \u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b.<\/p>\n<blockquote>\n<p>\u041d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u0435\u0444\u0435\u043a\u0442: \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b health \u0432 pl\/da \u0444\u043e\u043b\u0431\u044d\u0447\u0438\u043b \u0432 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0439 (\u00abHealth\u00bb \u0432\u043c\u0435\u0441\u0442\u043e \u00abKondycja\u00bb\/\u00abSystemtilstand\u00bb). \u0413\u0435\u0439\u0442 no-latin-leaks \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043d\u0435\u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0445 \u043b\u043e\u043a\u0430\u043b\u044f\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0435 pl\/da \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b\u0438 \u0435\u0433\u043e \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u043a\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u043e \u0441\u043b\u0435\u043f\u0430 \u043a \u044d\u0442\u043e\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443 \u0443\u0442\u0435\u0447\u0435\u043a. \u0427\u0430\u0441\u0442\u044c i18n-\u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0443\u0447\u043d\u043e\u0439 \u0441\u0432\u0435\u0440\u043a\u0438 \u0441 \u044d\u0442\u0430\u043b\u043e\u043d\u043e\u043c.<\/p>\n<\/blockquote>\n<h3>Spec-Driven Development<\/h3>\n<p>\u041c\u0435\u0442\u043e\u0434: \u043f\u0435\u0440\u0432\u043e\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u2014 \u0441\u043f\u0435\u043a\u0430, \u043d\u0435 \u043a\u043e\u0434. <strong>SDD (Spec-Driven Development)<\/strong> \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u044d\u0442\u043e \u0440\u0435\u043b\u0438\u0437\u043d\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442, \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u043c\u044b\u0435 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b (\u00ab\u0447\u0442\u043e \u0438 \u0433\u0434\u0435 \u0432\u0438\u0434\u0438\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u00bb) \u0438 \u0433\u0435\u0439\u0442\u044b. \u041a\u043e\u0434 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0442\u0435\u0441\u0442-\u043b\u043e\u043a, \u0440\u0435\u043b\u0438\u0437 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0437\u0435\u043b\u0451\u043d\u044b\u0445 \u0433\u0435\u0439\u0442\u0430\u0445. \u0414\u043b\u044f solo-\u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044d\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0433\u043e \u0440\u0435\u0432\u044c\u044e: \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u043a\u043e\u043b\u043b\u0435\u0433\u0438, \u0437\u0434\u0435\u0441\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u043a\u043e\u0439. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u043f\u0435\u043a\u0438 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0430:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0421\u0435\u043a\u0446\u0438\u044f<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u00a70 Gates<\/p>\n<\/td>\n<td>\n<p align=\"left\">npm test \u2265 N \u00b7 coverage \u2265 floor \u00b7 Playwright locale-sweep \u00d713 \u00b7 E2E \u00b7 CI-\u043c\u0430\u0442\u0440\u0438\u0446\u0430<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u00a71 Footguns<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u043c\u0435\u0442\u043e\u0434\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0442\u0435\u0441\u0442\u0430 (grep \u043c\u0430\u0441\u043a\u0438\u0440\u0443\u0435\u0442 exit-code; PATHS-once; raw-path SSRF \u2014 \u0447\u0435\u0440\u0435\u0437 curl <code>--path-as-is<\/code>)<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u00a72 Deltas<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u043b\u0438\u0437\u0430; \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u0430 \u043a \u044d\u043a\u0440\u0430\u043d\u0443\/\u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0443<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u00a73 Security<\/p>\n<\/td>\n<td>\n<p align=\"left\">CSP, SSRF, XSS-\u0433\u0440\u0430\u043d\u0438\u0446\u044b, rate-limit, file-lock<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u00a74\u2013\u00a76<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u00b7 cross-cutting controls \u00b7 i18n-\u043f\u0440\u0438\u0451\u043c\u043a\u0430 \u00d713<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u00a77\u2013\u00a78<\/p>\n<\/td>\n<td>\n<p align=\"left\">docs\/branding\/release mechanics \u00b7 exit criteria<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<blockquote>\n<p>\u0418\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043c\u0435\u0442\u043e\u0434\u0430: \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043f\u0435\u043a\u0438 \u043e\u0431\u044f\u0437\u0430\u043d\u0430 \u0431\u044b\u0442\u044c <strong>\u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u043e\u0439, \u0430 \u043d\u0435 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439<\/strong>. \u0424\u043e\u0440\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u043a\u0430 \u00abEnter \u043d\u0430 non-URL \u2192 #\/scan \u0441 \u043f\u0440\u0435\u0434\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u043c; \u0435\u0441\u043b\u0438 \u0430\u043a\u0442\u0438\u0432\u0435\u043d #\/scan \u2014 \u0444\u043e\u0440\u0441-\u0440\u0435-\u0440\u0435\u043d\u0434\u0435\u0440, \u0447\u0442\u043e\u0431\u044b one-shot-prefill \u043d\u0435 \u0443\u0442\u0451\u043a \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0438\u0442\u00bb \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u0430 \u0438 \u0432\u0435\u0440\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c\u0430. \u0421\u0442\u0440\u043e\u043a\u0438 \u0432\u0438\u0434\u0430 \u00ab\u043f\u043e\u0438\u0441\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e\u00bb \u0432 \u0441\u043f\u0435\u043a\u0443 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u2014 \u0438\u0445 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043d\u0438 \u0437\u0430\u043a\u043e\u0434\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e, \u043d\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c.<\/p>\n<\/blockquote>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/09\/b8\/03\/09b8038d9f2c373767d0a44221ce18cc.png\" alt=\"\u0420\u0438\u0441. 4. \u0426\u0438\u043a\u043b SDD: \u0441\u043f\u0435\u043a\u0430 \u2192 \u043a\u043e\u0434 \u2192 \u0442\u0435\u0441\u0442-\u043b\u043e\u043a \u2192 \u0433\u0435\u0439\u0442\u044b \u2192 \u0440\u0435\u043b\u0438\u0437 \u2192 \u0434\u0435\u043b\u044c\u0442\u0430.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/09\/b8\/03\/09b8038d9f2c373767d0a44221ce18cc.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/09\/b8\/03\/09b8038d9f2c373767d0a44221ce18cc.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441. 4. \u0426\u0438\u043a\u043b SDD: \u0441\u043f\u0435\u043a\u0430 \u2192 \u043a\u043e\u0434 \u2192 \u0442\u0435\u0441\u0442-\u043b\u043e\u043a \u2192 \u0433\u0435\u0439\u0442\u044b \u2192 \u0440\u0435\u043b\u0438\u0437 \u2192 \u0434\u0435\u043b\u044c\u0442\u0430.<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u043e\u043a\u0442\u0440\u0438\u043d\u0430 \u0440\u0435\u043b\u0438\u0437\u043e\u0432 \u2014 one-fix-per-release (\u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 HIGH \u2192 MEDIUM \u2192 LOW): \u043c\u0430\u043b\u044b\u0439 diff \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0432\u044c\u044e\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0438\u0439 \u2014 \u043f\u0440\u0438 \u043e\u0442\u043a\u0430\u0442\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u043e\u0442\u043a\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u043e\u0432\u043d\u043e \u043e\u0434\u0438\u043d \u0444\u0438\u043a\u0441, \u0430 \u043d\u0435 \u043f\u0430\u0447\u043a\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u041f\u0440\u0438\u043c\u0435\u0440: \u0444\u043e\u043b\u0431\u044d\u043a health.title \u043d\u0430 pl\/da \u0437\u0430\u043a\u0440\u044b\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u043b\u0438\u0437\u043e\u043c \u0441 \u0442\u0435\u0441\u0442\u043e\u043c-\u043b\u043e\u043a\u043e\u043c. \u041f\u0435\u0440\u043c\u0430\u043d\u0435\u043d\u0442\u043d\u044b\u0435 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u0432 ledger <code>REGRESSION-FINAL.md<\/code>, \u043f\u0435\u0440\u0435\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u043b\u0438\u0437\u044b: \u0441\u043f\u0435\u043a\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0434\u0435\u043b\u044c\u0442\u0443, ledger \u2014 \u0442\u043e, \u0447\u0442\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0430 \u0441\u043b\u043e\u043c\u0430\u0442\u044c\u0441\u044f \u043d\u0438\u043a\u043e\u0433\u0434\u0430.<\/p>\n<h3>\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u043f\u0438\u0440\u0430\u043c\u0438\u0434\u0430: 1543 \u043a\u0435\u0439\u0441\u0430 \u0438 \u0430\u0433\u0435\u043d\u0442\u043d\u044b\u0439 E2E<\/h3>\n<p>v1.84.0: <strong>1543 node:test<\/strong> (~180 \u0444\u0430\u0439\u043b\u043e\u0432), \u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 ~96% \u0441\u0442\u0440\u043e\u043a \/ ~87% \u0432\u0435\u0442\u043e\u043a, Playwright (85 \u043a\u0435\u0439\u0441\u043e\u0432), 20 smoke + 23 comprehensive E2E, CI-\u043c\u0430\u0442\u0440\u0438\u0446\u0430 Node 18\/20\/22 + CodeQL. \u041c\u0430\u043f\u043f\u0438\u043d\u0433 \u00ab\u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441\u043f\u0435\u043a\u0438 \u2192 \u0442\u0435\u0441\u0442-\u043b\u043e\u043a\u00bb \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u044b\u0439: \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u2014 <code>sources-&lt;slug&gt;.test.mjs<\/code>; SSRF \u2014 url-validation + ssrf-redirect-rebind; \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044f \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0430 \u2014 paths-once + test-root-isolation (CI-\u0442\u0435\u0441\u0442 \u0431\u0443\u0442\u0441\u0442\u0440\u0430\u043f\u0438\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 <code>CAREER_OPS_ROOT<\/code> \u0438 \u0433\u0440\u0443\u0437\u0438\u0442 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0438 <code>paths.mjs<\/code> \u0447\u0435\u0440\u0435\u0437 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 <code>import()<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 <code>before()<\/code> \u2014 \u0442\u0435\u0441\u0442\u044b \u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u043f\u0440\u0430\u0432\u0430 \u0432\u0438\u0434\u0435\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f).<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/79\/ce\/86\/79ce86f480601ee6a7e35c1a55be23ed.png\" alt=\"\u0420\u0438\u0441. 5. node:test \u2192 Playwright (locale-sweep \u00d713) \u2192 \u0430\u0433\u0435\u043d\u0442\u043d\u044b\u0439 E2E.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/79\/ce\/86\/79ce86f480601ee6a7e35c1a55be23ed.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/79\/ce\/86\/79ce86f480601ee6a7e35c1a55be23ed.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441. 5. node:test \u2192 Playwright (locale-sweep \u00d713) \u2192 \u0430\u0433\u0435\u043d\u0442\u043d\u044b\u0439 E2E.<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0441\u043b\u043e\u0439 \u2014 \u0430\u0433\u0435\u043d\u0442\u043d\u044b\u0439 E2E, \u0438 \u044d\u0442\u043e \u0441\u0430\u043c\u0430\u044f \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043f\u0438\u0440\u0430\u043c\u0438\u0434\u044b. \u0421\u043f\u0435\u043a\u0430-\u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f AI-\u0430\u0433\u0435\u043d\u0442\u0443, \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0435\u043c\u0443 \u0435\u0451 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: \u043e\u0431\u0445\u043e\u0434 \u0432\u0441\u0435\u0445 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u043d\u0430 13 \u043b\u043e\u043a\u0430\u043b\u044f\u0445 (\u043c\u0430\u0442\u0440\u0438\u0446\u0430 \u00ab23 \u00d7 13 = 299 \u044f\u0447\u0435\u0435\u043a\u00bb), \u0434\u0435\u0442\u0435\u043a\u0442 \u043d\u0435\u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u0441 \u0434\u0438\u0437\u0430\u043c\u0431\u0438\u0433\u0443\u0430\u0446\u0438\u0435\u0439 \u043b\u043e\u0436\u043d\u043e\u0433\u043e \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u0435 <code>profile.yml<\/code>, live-\u0441\u043a\u0430\u043d \u0441 maxPerSource, \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 (\u0441\u0442\u0440\u0430\u043d\u0430 \u00d7 \u0444\u043e\u0440\u043c\u0430\u0442), \u043f\u0430\u043d\u0435\u043b\u044c \u0440\u0435\u043f\u043e\u0441\u0442\u043e\u0432, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 SSRF-\u0433\u0435\u0439\u0442\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c\u0438 fetch \u043d\u0430 loopback\/IMDS \u2014 \u0441 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0442\u0447\u0451\u0442\u0430 \u0438 \u0432\u0435\u0440\u0434\u0438\u043a\u0442\u0430 GO\/NO-GO. Playwright \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u0430\u0432\u0442\u043e\u0440 \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0441\u044f \u0437\u0430\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0430\u0442\u044c; \u0430\u0433\u0435\u043d\u0442, \u0438\u0434\u0443\u0449\u0438\u0439 \u043f\u043e \u0441\u043f\u0435\u043a\u0435, \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0442\u043e, \u0447\u0435\u0433\u043e \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u0445 \u043d\u0435\u0442. \u042d\u0442\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043e\u043d\u0442\u0443\u0440 \u0440\u0435\u0432\u044c\u044e, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0443 solo-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 footguns, \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0435 \u0432 \u00a71 \u0441\u043f\u0435\u043a\u0438: grep \u043c\u0430\u0441\u043a\u0438\u0440\u0443\u0435\u0442 exit-code (capture <code>$?<\/code>); <code>[hidden]<\/code> \u2014 no-op \u043f\u0440\u043e\u0442\u0438\u0432 \u0430\u0432\u0442\u043e\u0440\u0441\u043a\u043e\u0433\u043e <code>display:flex|grid<\/code>; \u0442\u0435\u043b\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 English-by-policy; cross-realm vm-\u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0441\u043f\u0440\u0435\u0434\u0438\u0442\u044c <code>[...]<\/code> \u043f\u0435\u0440\u0435\u0434 deepEqual; query-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u043a\u043d\u0430 \u0440\u0435\u043f\u043e\u0441\u0442\u043e\u0432 \u2014 <code>window<\/code>, \u0430 \u043d\u0435 <code>windowDays<\/code> (\u043f\u0440\u0430\u0432\u0438\u043b\u043e: assert behaviour, not filenames). \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0443\u043d\u043a\u0442 \u2014 \u043e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0439 \u0434\u0435\u0444\u0435\u043a\u0442\u043e\u043c \u0443\u0440\u043e\u043a, \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043b\u0430\u0442\u0438\u0442\u044c \u0434\u0432\u0430\u0436\u0434\u044b.<\/p>\n<h3>\u042d\u0432\u043e\u043b\u044e\u0446\u0438\u044f \u0440\u0435\u043b\u0438\u0437\u043e\u0432: 19 \u2192 41 \u0430\u0434\u0430\u043f\u0442\u0435\u0440<\/h3>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/1d\/e7\/b9\/1de7b9a84c256e7d96e72af4af069e3e.png\" alt=\"\u0420\u0438\u0441. 6. \u041a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u2014 \u0437\u0435\u043b\u0451\u043d\u044b\u0439 \u0433\u0435\u0439\u0442.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/1d\/e7\/b9\/1de7b9a84c256e7d96e72af4af069e3e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/1d\/e7\/b9\/1de7b9a84c256e7d96e72af4af069e3e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0438\u0441. 6. \u041a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u2014 \u0437\u0435\u043b\u0451\u043d\u044b\u0439 \u0433\u0435\u0439\u0442.<\/figcaption><\/div>\n<\/figure>\n<p>v1.76 (6 ATS + \u0441\u043d\u044f\u0442\u0438\u0435 \u043b\u0438\u043c\u0438\u0442\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432) \u2192 v1.77 (\u0434\u0430\u0442\u0441\u043a\u0438\u0439, 13-\u044f \u043b\u043e\u043a\u0430\u043b\u044c) \u2192 v1.78.x (country-\u0444\u0438\u043b\u044c\u0442\u0440, \u0440\u0435\u0431\u0440\u0435\u043d\u0434\u0438\u043d\u0433, scan auto-refresh, \u0444\u0438\u043a\u0441 health.title pl\/da) \u2192 v1.79\u20131.82 (We Work Remotely, Teamtailor, NoDesk \u2192 <strong>41 \u0430\u0434\u0430\u043f\u0442\u0435\u0440<\/strong>) \u2192 v1.83 (repost-\u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440, \u0437\u0430\u0447\u0438\u0441\u0442\u043a\u0430 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f \u0438\u0437 parentVersion) \u2192 v1.84 (re-apply cooldown, compensation \u2192 pipeline.md).<\/p>\n<p>\u0420\u043e\u0430\u0434\u043c\u0430\u043f \u2014 v1.59 \u2192 v2.13: \u043e\u043d\u0431\u043e\u0440\u0434\u0438\u043d\u0433 \u0438 CV\u2192profile auto-fill, \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430-\u00ab\u044d\u043a\u0440\u0430\u043d \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u00bb, two-pager \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u0439 (\u043f\u0438\u0442\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u0438\u043d\u0433), \u043c\u043e\u043a-\u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e, human-approved \u0430\u0432\u0442\u043e-\u043e\u0442\u043a\u043b\u0438\u043a\u0438 (\u0447\u0435\u043b\u043e\u0432\u0435\u043a \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u2014 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u00ab\u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0430\u0432\u0442\u043e-\u0441\u0430\u0431\u043c\u0438\u0442\u043e\u0432\u00bb \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f), Chrome-\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 (Notion\/calendar\/email), CV Studio \u0441 Word-\u044d\u043a\u0441\u043f\u043e\u0440\u0442\u043e\u043c \u0438 anti-robotic-\u0447\u0435\u043a\u043e\u043c (\u043e\u0442\u0432\u0435\u0442 \u043d\u0430 issue #1 \u0434\u0432\u0438\u0436\u043a\u0430), scam-\u0441\u043a\u0440\u0438\u043d\u0438\u043d\u0433, persistent-agent \u0441 \u043f\u0430\u043c\u044f\u0442\u044c\u044e.<\/p>\n<h3>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/h3>\n<p>\u041a\u043e\u043a\u043f\u0438\u0442 \u0432 \u0441\u0432\u0435\u0442\u043b\u043e\u0439 \u0442\u0435\u043c\u0435 (\u043b\u043e\u043a\u0430\u043b\u044c ru). \u0414\u0430\u0448\u0431\u043e\u0440\u0434 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430; \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u043a\u0430\u043d\u0430 \u043d\u0435\u0441\u0451\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432; \u043f\u0430\u043d\u0435\u043b\u044c \u0434\u0435\u0442\u0435\u043a\u0442\u043e\u0440\u0430 \u0440\u0435\u043f\u043e\u0441\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0440\u0445 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0441\u043a\u0430\u043d\u043e\u0432.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/71\/2d\/3f\/712d3f126827519ce49edb3102ca3c46.png\" alt=\"\u0414\u0430\u0448\u0431\u043e\u0440\u0434 \u00ab\u041a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u0439 \u0446\u0435\u043d\u0442\u0440\u00bb: \u0441\u0442\u0430\u0442-\u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 (\u0437\u0430\u044f\u0432\u043a\u0438 \/ pipeline \/ \u043e\u0442\u0447\u0451\u0442\u044b \/ \u0441\u0440\u0435\u0434\u043d\u0438\u0439 score), \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0441 \u0431\u0435\u0439\u0434\u0436\u0435\u043c Enter.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/71\/2d\/3f\/712d3f126827519ce49edb3102ca3c46.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/71\/2d\/3f\/712d3f126827519ce49edb3102ca3c46.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0430\u0448\u0431\u043e\u0440\u0434 \u00ab\u041a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u0439 \u0446\u0435\u043d\u0442\u0440\u00bb: \u0441\u0442\u0430\u0442-\u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 (\u0437\u0430\u044f\u0432\u043a\u0438 \/ pipeline \/ \u043e\u0442\u0447\u0451\u0442\u044b \/ \u0441\u0440\u0435\u0434\u043d\u0438\u0439 score), \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0441 \u0431\u0435\u0439\u0434\u0436\u0435\u043c Enter.<\/figcaption><\/div>\n<\/figure>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/de\/10\/54\/de1054278b656b323aed0164f15788f7.png\" alt=\"\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u043a\u0430\u043d\u0430: \u043f\u0430\u043d\u0435\u043b\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 (\u043f\u043e\u0438\u0441\u043a \u00b7 \u0444\u043e\u0440\u043c\u0430\u0442 \u00b7 \u0437\u0430\u0440\u043f\u043b\u0430\u0442\u0430 \u00b7 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u00b7 \u0441\u0442\u0440\u0430\u043d\u0430 \u00b7 \u00ab\u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e \u0437\u0430\u00bb), \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u043f\u043e\u0438\u0441\u043a\u0438, \u0438\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435, summary-\u0447\u0438\u043f\u044b \u00abN new \/ M matching\u00bb, \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0441 \u0431\u0435\u0439\u0434\u0436\u0430\u043c\u0438 \u00ab\u2191 \u0431\u0443\u0441\u0442\u00bb.\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/de\/10\/54\/de1054278b656b323aed0164f15788f7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/de\/10\/54\/de1054278b656b323aed0164f15788f7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u043a\u0430\u043d\u0430: \u043f\u0430\u043d\u0435\u043b\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 (\u043f\u043e\u0438\u0441\u043a \u00b7 \u0444\u043e\u0440\u043c\u0430\u0442 \u00b7 \u0437\u0430\u0440\u043f\u043b\u0430\u0442\u0430 \u00b7 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u00b7 \u0441\u0442\u0440\u0430\u043d\u0430 \u00b7 \u00ab\u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e \u0437\u0430\u00bb), \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0435 \u043f\u043e\u0438\u0441\u043a\u0438, \u0438\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435, summary-\u0447\u0438\u043f\u044b \u00abN new \/ M matching\u00bb, \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0441 \u0431\u0435\u0439\u0434\u0436\u0430\u043c\u0438 \u00ab\u2191 \u0431\u0443\u0441\u0442\u00bb.<\/figcaption><\/div>\n<\/figure>\n<h3>\u0412\u044b\u0432\u043e\u0434\u044b<\/h3>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0439: \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043d\u0430\u0439\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u0443, \u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0435\u0448\u0430\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u043f\u043b\u043e\u0445\u043e. \u041d\u043e \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043e\u043d \u0441\u0442\u0430\u043b \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439: \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0431\u0435\u0437 virtual DOM \u0441 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 i18n \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u043c \u0444\u043e\u043a\u0443\u0441\u043e\u043c; \u0447\u0438\u0441\u0442\u0430\u044f \u0433\u0440\u0430\u043d\u0438\u0446\u0430 engine\/UI \u043f\u043e\u0432\u0435\u0440\u0445 read-only-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430; \u0431\u0443\u0442\u0441\u0442\u0440\u0430\u043f \u0434\u0432\u0443\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0441 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c; \u0434\u0432\u0430 \u0440\u0435\u0435\u0441\u0442\u0440\u0430 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u0432 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c; SSRF-envelope \u043d\u0430 DNS-pinning; \u0440\u0430\u0437\u043d\u0435\u0441\u0451\u043d\u043d\u044b\u0435 \u0441\u0430\u043d\u0438\u0442\u0430\u0439\u0437\u0435\u0440\u044b \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0430\u043d\u0438\u0446\u0435; \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u0432\u0443\u0445\u0444\u0430\u0437\u043d\u044b\u0439 SSE; \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 13 \u043b\u043e\u043a\u0430\u043b\u0435\u0439 \u0441 RTL; \u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u043f\u0438\u0440\u0430\u043c\u0438\u0434\u0430 \u0438\u0437 1543 \u043a\u0435\u0439\u0441\u043e\u0432 \u043f\u043e\u0434 \u0441\u043f\u0435\u043a\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c.<\/p>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 \u2014 \u043c\u0435\u0442\u043e\u0434\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439. SDD + one-fix-per-release + \u0430\u0433\u0435\u043d\u0442\u043d\u044b\u0439 E2E \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0437\u0430\u043c\u0435\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0434\u043b\u044f solo-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438: \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0436\u0438\u0432\u0443\u0442 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0435, \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u0443 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0433\u0435\u0439\u0442\u044b, \u0432\u0442\u043e\u0440\u0443\u044e \u043f\u0430\u0440\u0443 \u0433\u043b\u0430\u0437 \u2014 \u0430\u0433\u0435\u043d\u0442. \u041d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441, \u043d\u043e \u043d\u0430 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0435 \u0434\u0432\u0430\u0434\u0446\u0430\u0442\u0438 \u0441 \u043b\u0438\u0448\u043d\u0438\u043c \u0440\u0435\u043b\u0438\u0437\u043e\u0432 \u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0438\u0439, \u0434\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u0434\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0435 \u0431\u044b\u043b\u043e.<\/p>\n<h3>\u0412\u043e\u043f\u0440\u043e\u0441\u044b \u043a \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044e<\/h3>\n<ol>\n<li>\n<p>\u0414\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 fetch-\u0440\u0435\u0435\u0441\u0442\u0440 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u043e\u0432 \u2014 \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043d\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 (display vs fetch) \u0438\u043b\u0438 smell, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0438\u0439 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0438\u0441\u0442\u0438\u043d\u044b?<\/p>\n<\/li>\n<li>\n<p>SDD + one-fix-per-release \u0434\u043b\u044f solo-\u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u2014 \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043d\u0430\u044f \u0434\u0438\u0441\u0446\u0438\u043f\u043b\u0438\u043d\u0430 \u0438\u043b\u0438 \u043e\u0432\u0435\u0440\u0438\u043d\u0436\u0438\u043d\u0438\u0440\u0438\u043d\u0433?<\/p>\n<\/li>\n<li>\n<p>Companion-\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u0432\u0435\u0440\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e read-only-\u0434\u0432\u0438\u0436\u043a\u0430 \u2014 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d; \u043a\u0430\u043a \u0441\u0442\u0440\u0430\u0445\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0434\u0440\u0435\u0439\u0444\u0430 upstream-\u0441\u0445\u0435\u043c\u044b?<\/p>\n<\/li>\n<li>\n<p>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u043d\u0430 \u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u043e\u0431\u044a\u0451\u043c\u0435 UI \u2014 \u043e\u0431\u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u043d \u0438\u043b\u0438 \u0442\u0435\u0445\u0434\u043e\u043b\u0433?<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a\u0438\u0435 \u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u044b \u0431\u044b \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0438\u043d\u0430\u0447\u0435?<\/p>\n<\/li>\n<\/ol>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1055280\/\">https:\/\/habr.com\/ru\/articles\/1055280\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0420\u0430\u0437\u0431\u043e\u0440 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0438 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f, senior backend-\u0438\u043d\u0436\u0435\u043d\u0435\u0440, \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u2014 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u0441\u043a\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 job-\u0431\u043e\u0440\u0434\u044b \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u0442\u0440\u0443\u0434\u043e\u0451\u043c\u043a\u043e\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439. \u0412\u043d\u0443\u0442\u0440\u0438: \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0431\u0435\u0437 virtual DOM, \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u043c \u0444\u043e\u043a\u0443\u0441\u043e\u043c, \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 API-\u0441\u043b\u043e\u0439 \u043f\u043e\u0432\u0435\u0440\u0445 SSE, \u0434\u0432\u0443\u0445\u0444\u0430\u0437\u043d\u044b\u0439 \u0441\u043a\u0430\u043d\u0435\u0440 \u0441 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435\u043c, SSRF-envelope \u043d\u0430 DNS-pinning, \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 13 \u043b\u043e\u043a\u0430\u043b\u0435\u0439 \u0441 RTL, \u0437\u0430\u043f\u0443\u0441\u043a \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u043f\u0438\u0440\u0430\u043c\u0438\u0434\u0430 \u0438\u0437 1543 \u043a\u0435\u0439\u0441\u043e\u0432. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u2014 \u043c\u0435\u0442\u043e\u0434 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438: Spec-Driven Development \u0438 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0442\u0435\u0441\u0442\u0430\u043c\u0438.\u041f\u0440\u043e\u0435\u043a\u0442: github.com\/Fighter90\/career-ops-ui\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a: github.com\/santifer\/career-ops\u0420\u043e\u0430\u0434\u043c\u0430\u043f (Issue #29): github.com\/Fighter90\/career-ops-ui\/issues\/29\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438: \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0435\u043d\u044c\u043e\u0440 \u043f\u0438\u0448\u0435\u0442 \u0441\u0435\u0431\u0435 job-\u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440\u042f backend-\u0438\u043d\u0436\u0435\u043d\u0435\u0440 (PHP, Go). \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0432 \u043f\u043e\u0437\u0438\u0446\u0438\u0438, \u0437\u043d\u0430\u043a\u043e\u043c\u043e\u0439 \u043c\u043d\u043e\u0433\u0438\u043c: \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438 \u043f\u043e\u043b\u043d\u043e\u0439 \u0437\u0430\u043d\u044f\u0442\u043e\u0441\u0442\u0438. \u0418 \u0431\u044b\u0441\u0442\u0440\u043e \u0443\u043f\u0451\u0440\u0441\u044f \u0432 \u0442\u043e, \u0447\u0442\u043e \u0441\u0430\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u0438\u0441\u043a\u0430 \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u2014 \u043d\u0435 \u00ab\u043c\u043e\u0440\u0430\u043b\u044c\u043d\u043e \u0442\u044f\u0436\u0435\u043b\u043e\u00bb, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e.\u0412\u043e\u0437\u044c\u043c\u0451\u043c \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043d\u0430 hh.ru. \u041f\u043e\u0438\u0441\u043a\u043e\u0432\u0430\u044f \u0432\u044b\u0434\u0430\u0447\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u043b\u0435\u0432\u0430\u043d\u0442\u043d\u044b\u0435 \u0440\u043e\u043b\u0438 \u0441 \u0448\u0443\u043c\u043e\u043c: \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441 \u00abSenior PHP\u00bb \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u044e\u0442 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u0434\u0436\u0443\u043d\u043e\u0432, \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435\u0440\u043e\u0432 \u0438 \u00abPHP-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e \u0437\u043d\u0430\u043d\u0438\u0435\u043c 1\u0421\u00bb. \u041e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u043e\u0434 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 URL \u2014 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u00ab\u043e\u0441\u0432\u0435\u0436\u0430\u0435\u0442\u00bb \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044e, \u0438 \u043e\u043d\u0430 \u0441\u043d\u043e\u0432\u0430 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u0435\u0442 \u0432 \u0432\u044b\u0434\u0430\u0447\u0435 \u043a\u0430\u043a \u043d\u043e\u0432\u0430\u044f; \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0440\u0435\u043f\u043e\u0441\u0442 \u0440\u043e\u043b\u0438, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0442\u044b \u0443\u0436\u0435 \u043e\u0442\u043a\u043b\u0438\u043a\u0430\u043b\u0441\u044f \u043c\u0435\u0441\u044f\u0446 \u043d\u0430\u0437\u0430\u0434, \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0417\u0430\u0440\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u0432\u0438\u043b\u043a\u0438 \u0441\u043a\u0440\u044b\u0442\u044b \u0438\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u0430\u043b\u044e\u0442\u0430\u0445 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445. \u0410 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 hh.ru \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u044c \u0440\u044b\u043d\u043a\u0430: \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u043f\u043e\u0437\u0438\u0446\u0438\u0439 \u0436\u0438\u0432\u0451\u0442 \u0432 ATS \u0437\u0430\u043f\u0430\u0434\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 (Greenhouse, Ashby, Lever, Workable, SmartRecruiters, Workday), \u043d\u0430 Habr Career, \u0432 GetMatch, GeekJob, Trudvsem \u2014 \u0438 \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0441\u0432\u043e\u0439 API, \u0441\u0432\u043e\u044f \u0441\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u0432\u043e\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0437\u0430\u0440\u043f\u043b\u0430\u0442\u044b \u0438 \u043b\u043e\u043a\u0430\u0446\u0438\u0438.\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u2014 \u0418\u0418, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 2026 \u0433\u043e\u0434\u0443 \u0441\u0442\u043e\u0438\u0442 \u043f\u043e \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432\u043e\u0440\u043e\u043d\u043a\u0438 \u043d\u0430\u0439\u043c\u0430 \u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0435\u0451 \u044d\u0442\u0430\u043f\u0435. \u0421\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0440\u0430\u0431\u043e\u0442\u043e\u0434\u0430\u0442\u0435\u043b\u044f \u0440\u0435\u0437\u044e\u043c\u0435 \u043f\u0435\u0440\u0432\u044b\u043c \u0447\u0438\u0442\u0430\u0435\u0442 \u043d\u0435 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0430 ATS-\u0441\u043a\u0440\u0438\u043d\u0435\u0440: \u043e\u043d \u043f\u0430\u0440\u0441\u0438\u0442 PDF, \u043c\u0430\u0442\u0447\u0438\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0438 \u0440\u0435\u0436\u0435\u0442 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0435\u043a\u0440\u0443\u0442\u0451\u0440 \u0432\u043e\u043e\u0431\u0449\u0435 \u0443\u0432\u0438\u0434\u0438\u0442 \u043e\u0442\u043a\u043b\u0438\u043a, \u2014 \u0437\u043d\u0430\u0447\u0438\u0442, \u0440\u0435\u0437\u044e\u043c\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043c\u0430\u0448\u0438\u043d\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c (\u0442\u0438\u043f\u043e\u0433\u0440\u0430\u0444\u0438\u043a\u0430, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u044d\u043c\u0431\u0435\u0434\u0434\u0438\u043d\u0433 \u0448\u0440\u0438\u0444\u0442\u043e\u0432), \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c. \u0421\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u0432 \u0440\u044b\u043d\u043e\u043a \u0437\u0430\u0445\u043b\u0435\u0441\u0442\u043d\u0443\u043b\u0430 \u0432\u043e\u043b\u043d\u0430 \u043c\u0430\u0441\u0441\u043e\u0432\u044b\u0445 AI-\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432: \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0446\u0438\u044f \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0438\u0441\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0442\u043d\u044f\u043c\u0438 \u0437\u0430\u044f\u0432\u043e\u043a, \u0430 \u0440\u0435\u043a\u0440\u0443\u0442\u0451\u0440\u044b \u0432 \u043e\u0442\u0432\u0435\u0442 \u0437\u0430\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u044e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0443\u0447\u0430\u0442\u0441\u044f \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u00ab\u0440\u043e\u0431\u043e\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435\u00bb \u0440\u0435\u0437\u044e\u043c\u0435 \u2014 \u0433\u0435\u043d\u0435\u0440\u0438\u0447\u043d\u044b\u0439 AI-\u0442\u0435\u043a\u0441\u0442 \u0431\u0435\u0437 \u0444\u0430\u043a\u0442\u0443\u0440\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430 (\u044d\u0442\u0430 \u0431\u043e\u043b\u044c \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043f\u0440\u044f\u043c\u043e \u0432 issue #1 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430). \u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u043e \u0432\u043e\u0440\u043e\u043d\u043a\u0435 \u2014 AI-\u0441\u043a\u0440\u0438\u043d\u0438\u043d\u0433\u043e\u0432\u044b\u0435 \u0437\u0432\u043e\u043d\u043a\u0438, \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u043d\u0436\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0430\u0432\u0442\u043e\u043e\u0442\u0432\u0435\u0442\u044b-\u043e\u0442\u043a\u0430\u0437\u044b \u0431\u0435\u0437 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438. \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439 \u043d\u0435\u043b\u044c\u0437\u044f, \u043d\u043e \u0438 \u0441\u043b\u0435\u043f\u043e \u00ab\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435\u00bb \u2014 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0448\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f. \u0420\u0430\u0437\u0443\u043c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0418\u0418 \u043d\u0435 \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0441\u0442\u0438, \u0430 \u0434\u043b\u044f \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438: \u0441\u043a\u043e\u0440\u0438\u043d\u0433 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u043f\u0440\u043e\u0442\u0438\u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0440\u0435\u0437\u044e\u043c\u0435 \u0434\u043e \u043e\u0442\u043a\u043b\u0438\u043a\u0430, \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044f \u0440\u0435\u0437\u044e\u043c\u0435 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e JD \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0444\u0430\u043a\u0442\u0443\u0440\u044b, \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u043f\u0435\u0440\u0435\u0434 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e \u2014 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0442\u043a\u043b\u0438\u043a \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0440\u0443\u0447\u043d\u044b\u043c \u0438 \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0430.\u0415\u0441\u043b\u0438 \u0434\u0435\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0447\u0435\u0441\u0442\u043d\u043e, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0438\u043f\u043e\u0432\u043e\u0439 ETL-\u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u043d\u0430\u0434 \u043d\u0435\u043e\u0434\u043d\u043e\u0440\u043e\u0434\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438: \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044f \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439 \u0438\u0437 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 job-board API \u0438 ATS, \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0434\u0435\u0434\u0443\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u0440\u0430\u0437\u043d\u043e\u0440\u043e\u0434\u043d\u044b\u0445 \u0441\u0445\u0435\u043c \u0432 \u0435\u0434\u0438\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c, \u0441\u043a\u043e\u0440\u0438\u043d\u0433 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043f\u0440\u043e\u0442\u0438\u0432 \u0440\u0435\u0437\u044e\u043c\u0435 \u0438 \u0442\u0440\u0435\u043a\u0438\u043d\u0433 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0442\u043a\u043b\u0438\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0420\u043e\u0432\u043d\u043e \u0442\u043e, \u0447\u0442\u043e backend-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b \u0441\u0442\u0440\u043e\u044f\u0442 \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0435 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0434 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u0442\u0440\u0443\u0434\u043e\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435.\u0413\u043e\u0442\u043e\u0432\u044b\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u043d\u0430 \u0440\u044b\u043d\u043a\u0435 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0442. \u042d\u0442\u043e \u043b\u0438\u0431\u043e \u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437\u043d\u044b\u0435 ATS, \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0440\u0435\u043a\u0440\u0443\u0442\u0451\u0440\u0430, \u0430 \u043d\u0435 \u043d\u0430 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0430, \u043b\u0438\u0431\u043e \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043b\u0435\u043d\u0442\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0431\u043e\u0440\u0434\u043e\u0432 \u2014 \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043a\u0430\u0431\u0438\u043d\u0435\u0442\u043e\u043c, \u0431\u0435\u0437 \u0441\u043a\u0432\u043e\u0437\u043d\u043e\u0439 \u0434\u0435\u0434\u0443\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0431\u0435\u0437 \u0441\u043a\u043e\u0440\u0438\u043d\u0433\u0430 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u0440\u0435\u0437\u044e\u043c\u0435. \u041a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u0443 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f Excel-\u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u0438 \u0434\u0435\u0441\u044f\u0442\u043e\u043a \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a. \u041c\u0435\u043d\u044f \u043a\u0430\u043a \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430 \u0442\u0430\u043a\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0435\u043b \u043d\u0435 \u0443\u0441\u0442\u0440\u043e\u0438\u043b\u043e \u2014 \u0438 \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u0434 \u0441\u0435\u0431\u044f.career-ops-ui \u2014 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442 41 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0432 \u0435\u0434\u0438\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0446\u0435\u043d\u043a\u0443 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u043f\u043e\u0434 \u0440\u0435\u0437\u044e\u043c\u0435, \u0432\u0435\u0434\u0451\u0442 \u0432\u043e\u0440\u043e\u043d\u043a\u0443 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 PDF. \u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043d\u043e\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u2014 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u044c: \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043b\u0443\u0448\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e loopback (127.0.0.1:4317); PII (\u0440\u0435\u0437\u044e\u043c\u0435, \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432, \u0437\u0430\u0440\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f) \u043d\u0435 \u043f\u043e\u043a\u0438\u0434\u0430\u0435\u0442 \u043c\u0430\u0448\u0438\u043d\u0443. \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u0432, \u0442\u0435\u043b\u0435\u043c\u0435\u0442\u0440\u0438\u0438 \u0438 \u0430\u0432\u0442\u043e-\u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432. \u041a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u043a\u0430\u043a companion \u043f\u043e\u0432\u0435\u0440\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430 santifer\/career-ops \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0441\u0442\u0438\u043d\u044b. \u0414\u0430\u043b\u044c\u0448\u0435 \u2014 \u0440\u0430\u0437\u0431\u043e\u0440 \u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c, \u0441 \u0430\u043a\u0446\u0435\u043d\u0442\u043e\u043c \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434.\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a: \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043c\u0443\u043b\u044c\u0442\u0438-CLI\u0412 \u043e\u0441\u043d\u043e\u0432\u0435 \u2014 santifer\/career-ops, \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 AI-\u0434\u0432\u0438\u0436\u043e\u043a \u043f\u043e\u0438\u0441\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b (\u043f\u043e\u0434 \u0448\u0435\u0441\u0442\u044c\u0434\u0435\u0441\u044f\u0442 \u0442\u044b\u0441\u044f\u0447 \u0437\u0432\u0451\u0437\u0434 \u043d\u0430 GitHub; \u0441\u0430\u043c\u043e\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u2014 \u00ab14 skill modes, Go dashboard, PDF generation, batch processing\u00bb). \u0414\u0432\u0438\u0436\u043e\u043a \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0443\u044e \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044e \u043f\u0440\u043e\u0442\u0438\u0432 \u0440\u0435\u0437\u044e\u043c\u0435 \u043f\u043e \u0448\u0435\u0441\u0442\u0438\u043c\u0435\u0440\u043d\u043e\u0439 \u0440\u0443\u0431\u0440\u0438\u043a\u0435 0.0\u20135.0, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 PDF-\u0440\u0435\u0437\u044e\u043c\u0435 \u0438 \u0432\u0435\u0434\u0451\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0435\u043a\u0435\u0440 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432.\u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e: \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u043f\u043b\u043e\u0441\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445. \u0420\u0435\u0437\u044e\u043c\u0435 \u2014 cv.md, \u043f\u0440\u043e\u0444\u0438\u043b\u044c (\u0446\u0435\u043b\u0435\u0432\u044b\u0435 \u0440\u043e\u043b\u0438, \u043b\u043e\u043a\u0430\u0446\u0438\u044f, \u0434\u0438\u043b-\u0431\u0440\u0435\u0439\u043a\u0435\u0440\u044b) \u2014 config\/profile.yml, \u0442\u0440\u0435\u043a\u0435\u0440 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u2014 data\/applications.md. \u0421\u0423\u0411\u0414 \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u043e\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u2014 \u0438 \u044d\u0442\u043e \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0430 \u043d\u0435 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435: \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 git-friendly \u0438 \u0434\u0438\u0444\u0444\u0443\u0435\u043c\u043e (\u043b\u044e\u0431\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0435\u0440\u0430 \u0432\u0438\u0434\u043d\u043e \u0432 git diff), \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c\u043e \u043c\u0435\u0436\u0434\u0443 \u043c\u0430\u0448\u0438\u043d\u0430\u043c\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u0447\u0438\u0442\u0430\u0435\u043c\u043e \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u043c \u0431\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430; \u0438\u043d\u0434\u0435\u043a\u0441 (\u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438) \u2014 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u043d\u044b\u0439 \u043a\u044d\u0448, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432.\u0414\u0432\u0438\u0436\u043e\u043a CLI-\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u043d: \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043b\u0435\u0436\u0430\u0442 \u0438\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0435 \u0441\u043a\u0438\u043b\u043b-\u043f\u0430\u043a\u0438 \u043f\u043e\u0434 .claude, .qwen, .grok, .kimi, .opencode. \u042d\u0442\u0443 \u043c\u043e\u0434\u0435\u043b\u044c-\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0451\u043b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u043e\u0446\u0435\u043d\u043a\u0438: Anthropic, Gemini, OpenAI, Qwen, OpenRouter, GitHub Models \u2014 \u0432\u044b\u0431\u043e\u0440 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f: LLM-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u2014 \u044d\u0442\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0441 \u0441\u0430\u043c\u044b\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u043c \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0432\u0435\u043d\u0434\u043e\u0440\u0443 \u0432 2026 \u0433\u043e\u0434\u0443 \u043d\u0435\u0440\u0430\u0437\u0443\u043c\u043d\u043e.\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0436\u0451\u0441\u0442\u043a\u043e: \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u2014 read-only. \u041a\u043b\u0438\u0435\u043d\u0442 \u0447\u0438\u0442\u0430\u0435\u0442 \u0442\u0435 \u0436\u0435 \u0444\u0430\u0439\u043b\u044b, \u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e \u044f\u0432\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044e (POST \/api\/pipeline, POST \/api\/tracker, PUT \/api\/cv); \u043d\u0438 \u043e\u0434\u0438\u043d \u0444\u043e\u043d\u043e\u0432\u044b\u0439 code-path \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u043d\u0435 \u043f\u0438\u0448\u0435\u0442. \u042d\u0442\u043e \u0437\u0430\u0449\u0438\u0449\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043f\u043e\u0432\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u044f \u0431\u0430\u0433\u043e\u043c \u0444\u043e\u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u043c: \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f \u2014 \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c.\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u2014 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 issue \u0434\u0432\u0438\u0436\u043a\u0430: ATS-\u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f AI-\u0440\u0435\u0437\u044e\u043c\u0435 (#1), \u043e\u0442\u043a\u0430\u0437 \u043c\u0435\u0439\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0432\u0435\u0431-\u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b \u0432 \u044f\u0434\u0440\u043e (#12, \u044f\u0434\u0440\u043e \u0441\u043e\u0437\u043d\u0430\u0442\u0435\u043b\u044c\u043d\u043e terminal-first), \u0441\u043f\u0440\u043e\u0441 \u043d\u0430 \u043c\u0443\u043b\u044c\u0442\u0438-CLI (#14). #12 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u0430 \u043d\u0435 \u043f\u0430\u0442\u0447\u0438\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a: \u0444\u043e\u0440\u043a \u0441 \u0432\u0435\u0431-\u043c\u043e\u0440\u0434\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0435\u0447\u0451\u043d \u043d\u0430 \u0432\u0435\u0447\u043d\u044b\u0439 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442 \u0441 upstream, \u0430 companion-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0436\u0438\u0432\u0451\u0442 \u0441\u0432\u043e\u0438\u043c \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c.\u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 engine\/UI\u0413\u0440\u0430\u043d\u0438\u0446\u0430 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0430 \u044f\u0432\u043d\u043e: \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u2014 \u0434\u043e\u043c\u0435\u043d\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0438 LLM-\u0440\u0435\u0436\u0438\u043c\u044b; \u043a\u043b\u0438\u0435\u043d\u0442 \u2014 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432, \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0441\u043a\u0430\u043d\u0430 \u0438 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u044f. \u041e\u0431\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0447\u0438\u0442\u0430\u044e\u0442 \u043e\u0431\u0449\u0438\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u0439\u0442; \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c read-only. \u042d\u0442\u043e \u0434\u0430\u0451\u0442 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b (\u0434\u0432\u0438\u0436\u043e\u043a \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f terminal-first, \u043a\u043b\u0438\u0435\u043d\u0442 \u0440\u0435\u043b\u0438\u0437\u0438\u0442\u0441\u044f \u0432 \u0441\u0432\u043e\u0451\u043c \u0442\u0435\u043c\u043f\u0435) \u0438 \u0435\u0434\u0438\u043d\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0441\u0442\u0438\u043d\u044b \u0431\u0435\u0437 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0411\u0414 \u2014 \u043a\u043b\u0430\u0441\u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u00ab\u0440\u0430\u0441\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0434\u0432\u0435 \u043a\u043e\u043f\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u00bb \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044e.\u0420\u0438\u0441. 1. \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 engine\/UI: \u043e\u0431\u0449\u0438\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0438\u0441\u0442\u0438\u043d\u044b, \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a read-only, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 loopback.\u0417\u0430\u043f\u0443\u0441\u043a \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e developer experience \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 (\u0434\u0432\u0438\u0436\u043e\u043a + \u043a\u043b\u0438\u0435\u043d\u0442), \u0438 \u00ab\u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0439 \u043e\u0434\u043d\u043e, \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0439 \u0432\u0442\u043e\u0440\u043e\u0435 \u0432\u043d\u0443\u0442\u0440\u044c, \u043d\u0430\u0441\u0442\u0440\u043e\u0439 \u043a\u043b\u044e\u0447\u0438\u00bb \u2014 \u044d\u0442\u043e \u0431\u0430\u0440\u044c\u0435\u0440 \u0432\u0445\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0441\u0435\u043a\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u0436\u0435 \u0448\u0430\u0433\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0435\u0441\u044c \u0431\u0443\u0442\u0441\u0442\u0440\u0430\u043f \u0441\u0432\u0435\u0434\u0451\u043d \u043a \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435:curl -fsSL https:\/\/raw.githubusercontent.com\/Fighter90\/career-ops-ui\/main\/bin\/setup.sh | bash\u0421\u043a\u0440\u0438\u043f\u0442 \u043a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f (\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 career-ops \u0438 career-ops-ui \u0432\u043d\u0443\u0442\u0440\u044c \u043d\u0435\u0433\u043e), \u0441\u0442\u0430\u0432\u0438\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443 (doctor) \u0438 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 http:\/\/127.0.0.1:4317 \u2014 \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u043d\u0438\u0439 \u043f\u043b\u0430\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 (\u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f NO_OPEN=1 \u0434\u043b\u044f headless\/CI).\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433, \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d \u043d\u0430 \u0433\u043b\u0430\u0433\u043e\u043b\u044b CLI:git clone https:\/\/github.com\/Fighter90\/career-ops-uicd career-ops-uinpm link                 # \u0434\u0430\u0451\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 `career-ops-ui` (\u0438\u043b\u0438 npx career-ops-ui &lt;verb&gt;)career-ops-ui setup      # \u0431\u0443\u0442\u0441\u0442\u0440\u0430\u043f: deps \u2192 doctor \u2192 run (SKIP_START=1 \u2014 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430)career-ops-ui init       # \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0432\u0438\u0437\u0430\u0440\u0434: \u0432\u044b\u0431\u043e\u0440 LLM-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 + \u043a\u043b\u044e\u0447 \u2192 \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 .envcareer-ops-ui doctor     # \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 Node \/ \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \/ \u043a\u043b\u044e\u0447\u0435\u0439 \/ Playwright (exit 0 \u21d4 \u0432\u0441\u0451 required \u0437\u0435\u043b\u0451\u043d\u043e\u0435)career-ops-ui run        # \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 http:\/\/127.0.0.1:4317career-ops-ui open       # \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0438 \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430init \u0437\u0430\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u0431\u0437\u0430\u0446\u0430, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0441\u0435\u043a\u0440\u0435\u0442\u043e\u0432. \u0412\u0438\u0437\u0430\u0440\u0434 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0432\u044b\u0431\u043e\u0440 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 (Claude \/ Gemini \/ Codex-OpenCode \/ Auto \u0441 \u0444\u043e\u043b\u0431\u044d\u043a\u043e\u043c Anthropic \u2192 Gemini); \u043a\u043b\u044e\u0447 \u0432\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0441 \u043f\u043e\u0434\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c echo \u2014 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0441\u0435\u0434\u0430\u0435\u0442 \u0432 \u0441\u043a\u0440\u043e\u043b\u043b\u0431\u044d\u043a\u0435 \u0448\u0435\u043b\u043b\u0430 \u2014 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 career-ops\/.env \u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0442 \u0436\u0435 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u043a\u043b\u0430\u0434\u043a\u0430 API-\u043a\u043b\u044e\u0447\u0435\u0439 \u0432 #\/config. \u0414\u043b\u044f CI \u0435\u0441\u0442\u044c \u043d\u0435\u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 (career-ops-ui init &#8212;provider claude &#8212;anthropic-key \u2026 &#8212;yes). \u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 LLM_PROVIDER, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0432\u0430\u0436\u0430\u044e\u0442 \u0432\u0441\u0435 live-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043e\u0446\u0435\u043d\u043a\u0438; \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u0437 UI \u0431\u0435\u0437 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.\u0421\u043c\u044b\u0441\u043b \u044d\u0442\u043e\u0439 \u043e\u0431\u0432\u044f\u0437\u043a\u0438 \u043d\u0435 \u0432 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0435 \u0440\u0430\u0434\u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430: \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 doctor \u0441 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c exit-\u043a\u043e\u0434\u043e\u043c \u2014 \u044d\u0442\u043e \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u0447\u0442\u043e \u0438 \u0432 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043b\u0438\u0431\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0435\u043b\u0451\u043d\u0430\u044f, \u043b\u0438\u0431\u043e \u044f\u0432\u043d\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u043b\u043e\u043c\u0430\u043d\u043e.\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434: \u0440\u0430\u043d\u0442\u0430\u0439\u043c \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0431\u0435\u0437 virtual DOM\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0443 \u043f\u0440\u0438\u043d\u044f\u0442\u043e \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 \u0432\u0430\u043d\u0438\u043b\u044c\u043d\u043e\u0433\u043e ES-\u043c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0433\u043e JavaScript \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438: \u043c\u043e\u0434\u0443\u043b\u0438 \u043e\u0442\u0434\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0438\u043a\u043e\u0439, \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 bundler, \u0442\u0440\u0430\u043d\u0441\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0438 runtime-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a. \u041e\u0431\u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u0435, \u0430 \u043d\u0435 \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435, \u0438 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0442\u0440\u0451\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432.\u041f\u0435\u0440\u0432\u044b\u0439 \u2014 \u0430\u0443\u0434\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c. \u041a\u043b\u0438\u0435\u043d\u0442 \u043e\u043f\u0435\u0440\u0438\u0440\u0443\u0435\u0442 PII \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 egress \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b; \u043a\u043e\u0434\u043e\u0432\u0430\u044f \u0431\u0430\u0437\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0430\u044f \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0447\u0438\u0442\u0430\u0435\u043c\u0430 \u043a\u0430\u043a \u0435\u0441\u0442\u044c, \u0431\u0435\u0437 \u0441\u043b\u043e\u0451\u0432&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-486081","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/486081","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=486081"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/486081\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=486081"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=486081"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=486081"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}