{"id":484775,"date":"2026-06-23T22:06:22","date_gmt":"2026-06-23T22:06:22","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=484775"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=484775","title":{"rendered":"Browser Policy Manager: \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0430"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a14\/77d\/8ea\/a1477d8eaafb680e4cc3ef5975755ee3.png\" width=\"4508\" height=\"1888\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a14\/77d\/8ea\/a1477d8eaafb680e4cc3ef5975755ee3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a14\/77d\/8ea\/a1477d8eaafb680e4cc3ef5975755ee3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f\u0445 \u044f \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b, \u0437\u0430\u0447\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f Browser Policy Manager, \u043f\u043e\u0447\u0435\u043c\u0443 \u044f \u043d\u0430\u0447\u0430\u043b \u0441 Firefox Enterprise Policies \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 \u0441\u0442\u0430\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u00ab\u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 <code>policies.json<\/code>\u00bb. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u0431\u043e\u043b\u0435\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f. \u0417\u0434\u0435\u0441\u044c \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c, \u043a\u0430\u043a Browser Policy Manager \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 0.8.8.<\/p>\n<p>\u0412\u0435\u0440\u0441\u0438\u044f 0.8.8 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u0430\u0436\u043d\u0430 \u0442\u0435\u043c, \u0447\u0442\u043e \u0432 \u043d\u0435\u0439 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043b\u043e\u0436\u0438\u043b\u0430\u0441\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430:<\/p>\n<ul>\n<li>\n<p>\u0435\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c All settings \u043a\u0430\u043a \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0447\u0430\u044f \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 JSON-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0433\u043e Firefox Enterprise <code>policies.json<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Firefox ESR 140.12 \u0438 Firefox Release 152;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u0448\u0435\u0441\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u0435\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u0442\u044c \u0441\u043b\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a, \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439, \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u043b\u043e\u043a \u2014 \u0432\u0435\u0440\u0441\u0438\u044f 0.9.0: \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 DITA-OT, \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430, \u0431\u043e\u043b\u0435\u0435 \u0446\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u0430 \u043f\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0434\u043e 1.0.<\/p>\n<p>\u041d\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u00ab\u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c\u00bb \u0441\u0430\u043c \u043f\u0440\u043e\u0434\u0443\u043a\u0442: \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 \u043d\u0451\u043c \u0435\u0441\u0442\u044c, \u0433\u0434\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0433\u0440\u0430\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0438 <code>policies.json<\/code>, \u043f\u043e\u0447\u0435\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u0438 \u043a\u0430\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u044d\u0442\u043e \u043d\u0435 \u0440\u0430\u0437\u0432\u0430\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0441\u0445\u0435\u043c Firefox.<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Browser Policy Manager \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438<\/h3>\n<p>Browser Policy Manager \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 FastAPI \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u043b\u0438\u0442\u0438\u043a Firefox.<\/p>\n<p>\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0442\u0435\u043a:<\/p>\n<ul>\n<li>\n<p>Python 3.14+;<\/p>\n<\/li>\n<li>\n<p>FastAPI;<\/p>\n<\/li>\n<li>\n<p>Pydantic v2;<\/p>\n<\/li>\n<li>\n<p>SQLAlchemy 2.x;<\/p>\n<\/li>\n<li>\n<p>Alembic;<\/p>\n<\/li>\n<li>\n<p>SQLite \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e;<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 PostgreSQL;<\/p>\n<\/li>\n<li>\n<p>Jinja2 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b;<\/p>\n<\/li>\n<li>\n<p>Monaco Editor \u0434\u043b\u044f JSON-\u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438;<\/p>\n<\/li>\n<li>\n<p>jsonschema \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u043b\u0438\u0442\u0438\u043a;<\/p>\n<\/li>\n<li>\n<p>pytest, Ruff, mypy, Selenium\/Chromium-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 live-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 Firefox.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/307\/e77\/9aa\/307e779aa982e2e6395e7372bb7e6176.png\" width=\"3224\" height=\"1653\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/307\/e77\/9aa\/307e779aa982e2e6395e7372bb7e6176.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/307\/e77\/9aa\/307e779aa982e2e6395e7372bb7e6176.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e BPM \u2014 \u043d\u0435 \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u043a\u0440\u044b\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u044c\u044e, \u0430 \u043d\u0430\u0431\u043e\u0440 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0435\u0439:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041c\u0430\u0440\u0448\u0440\u0443\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>\/profiles<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044f\u043c\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>\/profiles\/compare<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u043e\u0448\u0430\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>\/profiles\/new<\/code>, <code>\/profiles\/{id}\/edit<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">All settings<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>\/profiles\/{id}\/settings<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">JSON-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>\/profiles\/{id}\/json<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u044f\u043c\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u043c<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u043d\u0435 \u0441\u0440\u0430\u0437\u0443. \u041d\u0430 \u0440\u0430\u043d\u043d\u0438\u0445 \u044d\u0442\u0430\u043f\u0430\u0445 \u0431\u044b\u043b\u043e \u0441\u043e\u0431\u043b\u0430\u0437\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435. \u041d\u043e \u043f\u0440\u0438 \u0440\u043e\u0441\u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0448\u0430\u043d\u0438\u043d\u0443: \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u2014 \u0437\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u2014 \u0437\u0430 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e, \u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0442\u0435\u0440\u044f\u0435\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0433\u0434\u0435 \u043e\u043d \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f.<\/p>\n<p>\u0412 \u0432\u0435\u0440\u0441\u0438\u0438 0.8.8 \u044f \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0432\u0451\u043b \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430\u043c. \u042d\u0442\u043e \u0434\u0430\u043b\u043e \u043f\u0440\u043e\u0441\u0442\u0443\u044e, \u043d\u043e \u0432\u0430\u0436\u043d\u0443\u044e \u0432\u0435\u0449\u044c: \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043b\u0435\u0432\u0430 \u0434\u0435\u0440\u0436\u0430\u0442\u044c All settings, \u0441\u043f\u0440\u0430\u0432\u0430 JSON-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440, \u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u2014 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u043c.<\/p>\n<h3>\u0422\u043e\u0447\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0444\u0430\u0431\u0440\u0438\u043a\u0443 <code>create_app()<\/code>. \u0412 \u043d\u0435\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f middleware, \u0441\u0442\u0430\u0442\u0438\u043a\u0430, API-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b, HTML-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0438 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">def create_app() -&gt; FastAPI:    app = FastAPI(        title=settings.APP_NAME,        version=settings.APP_VERSION,    )    app.add_middleware(SecurityHeadersMiddleware)    if settings.ENABLE_CORS:        app.add_middleware(            CORSMiddleware,            allow_origins=settings.CORS_ALLOW_ORIGINS,            allow_credentials=True,            allow_methods=[\"*\"],            allow_headers=[\"*\"],        )    app.mount(        \"\/static\",        StaticFiles(directory=str(settings.STATIC_DIR)),        name=\"static\",    )    app.include_router(web_profiles.router)    app.include_router(health.router)    app.include_router(profiles.router)    app.include_router(export.router)    app.include_router(validation.router)    @app.get(\"\/i18n\/{locale}.json\", include_in_schema=False)    async def locale_catalog(locale: str) -&gt; Response:        if locale not in settings.SUPPORTED_LOCALES:            raise HTTPException(status_code=404, detail=\"Locale not supported\")        locale_path = _resolve_path(settings.I18N_DIR) \/ f\"{locale}.json\"        if not locale_path.is_file():            raise HTTPException(status_code=404, detail=\"Locale file not found\")        return Response(            content=locale_path.read_text(encoding=\"utf-8\"),            media_type=\"application\/json\",        )    return app<\/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>\u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u2014 HTML-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438 API \u0436\u0438\u0432\u0443\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. BPM \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430 \u0434\u043b\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u0432 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0441\u0440\u0435\u0434\u0435 \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u2014 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0447\u0435\u0440\u0435\u0437 <code>\/i18n\/{locale}.json<\/code>, \u0430 \u043d\u0435 \u0432\u0448\u0438\u0442\u044b \u0445\u0430\u043e\u0442\u0438\u0447\u043d\u043e \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0438\u043b\u0438 JavaScript.<\/p>\n<p>\u0422\u0440\u0435\u0442\u0438\u0439 \u2014 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u0430 \u00ab\u043d\u0430 \u043f\u043e\u0442\u043e\u043c\u00bb. \u0415\u0441\u0442\u044c middleware, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 Content Security Policy. \u0414\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u0442\u0440\u0430\u043d\u043d\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c \u0430\u0442\u0430\u043a\u0438.<\/p>\n<h3>\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043a\u0430\u043a \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c<\/h3>\n<p>\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c BPM \u2014 \u043d\u0435 \u0444\u0430\u0439\u043b \u0438 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430, \u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u044c.<\/p>\n<p>\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u2014 \u044d\u0442\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Firefox Enterprise Policies \u0441 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u0441\u0445\u0435\u043c\u044b, \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u0438\u0442\u0438\u043a, \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0438 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0430\u044f ORM-\u043c\u043e\u0434\u0435\u043b\u044c:<\/p>\n<pre><code class=\"python\">class Profile(Base):    __tablename__ = \"profiles\"    id: Mapped[int] = mapped_column(        Integer,        primary_key=True,        autoincrement=True,    )    name: Mapped[str] = mapped_column(        String(255),        nullable=False,        index=True,        unique=True,    )    description: Mapped[str | None] = mapped_column(Text, nullable=True)    schema_version: Mapped[str] = mapped_column(        String(50),        nullable=False,        index=True,        default=DEFAULT_SCHEMA_CHANNEL,    )    flags: Mapped[dict[str, Any]] = mapped_column(        JSON,        nullable=False,        default=dict,    )    compliance: Mapped[dict[str, Any] | None] = mapped_column(        JSON,        nullable=True,    )    revision: Mapped[int] = mapped_column(        Integer,        nullable=False,        default=1,        server_default=\"1\",    )    created_at: Mapped[datetime] = mapped_column(        DateTime(timezone=True),        server_default=func.now(),        nullable=False,        index=True,    )    updated_at: Mapped[datetime] = mapped_column(        DateTime(timezone=True),        server_default=func.now(),        onupdate=func.now(),        nullable=False,        index=True,    )    deleted_at: Mapped[datetime | None] = mapped_column(        DateTime(timezone=True),        nullable=True,        index=True,    )    @property    def is_deleted(self) -&gt; bool:        return self.deleted_at is not None<\/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>\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043b\u0435 <code>flags<\/code>. \u041d\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0432\u0438\u0434\u0430:<\/p>\n<pre><code class=\"json\">{  \"policies\": {    \"DisableTelemetry\": true,    \"Preferences\": {      \"browser.tabs.warnOnClose\": {        \"Value\": true,        \"Status\": \"locked\"      }    }  }}<\/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>\u041d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043d\u0435 \u0432\u0435\u0441\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442, \u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <code>policies<\/code>.<\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 Firefox:<\/p>\n<pre><code class=\"json\">{  \"policies\": {    \"...\": \"...\"  }}<\/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>\u0410 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u043c\u043e\u0434\u0435\u043b\u044c BPM:<\/p>\n<pre><code class=\"json\">{  \"...\": \"...\"}<\/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>\u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a?<\/p>\n<p>\u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c, \u0430 \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0443, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435, All settings \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0443 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u043b\u0438\u0448\u043d\u0438\u0439 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440. \u0418\u043c \u043d\u0443\u0436\u043d\u0430 \u043a\u0430\u043d\u043e\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u0430\u0440\u0442\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044f. \u0410 \u0432\u043e\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0438 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u043e\u0431\u044f\u0437\u0430\u043d \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Firefox \u2014 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <code>policies.json<\/code> \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430.<\/p>\n<h3>Pydantic-\u0441\u0445\u0435\u043c\u044b: \u0433\u0440\u0430\u043d\u0438\u0446\u0430 API<\/h3>\n<p>Pydantic-\u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044f\u044e\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e ORM-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 API.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e:<\/p>\n<pre><code class=\"python\">class ProfileBase(BaseModel):    name: str = Field(..., max_length=255)    description: str | None = None    schema_version: str = Field(default=DEFAULT_SCHEMA_CHANNEL, max_length=50)    flags: dict[str, Any] = Field(default_factory=dict)    compliance: dict[str, Any] | None = Noneclass ProfileCreate(ProfileBase):    passclass ProfileUpdate(BaseModel):    description: str | None = None    schema_version: str | None = Field(default=None, max_length=50)    flags: dict[str, Any] | None = None    compliance: dict[str, Any] | None = None    expected_revision: int | None = Field(default=None, ge=1)class ProfileRead(ProfileBase):    id: int    revision: int    created_at: datetime    updated_at: datetime    deleted_at: datetime | None = None    is_deleted: bool    validation_state: str = \"not_validated\"    model_config = ConfigDict(from_attributes=True)<\/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>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u0435\u043d <code>expected_revision<\/code>. \u041e\u043d \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0437\u0430\u0449\u0438\u0442\u044b \u043e\u0442 \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f: \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043e\u0442\u043a\u0440\u044b\u0442 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u0445, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u0435\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0438.<\/p>\n<p>\u042d\u0442\u043e \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043d\u043e \u0443\u0436\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f.<\/p>\n<h3>\u0421\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439 \u0441\u043b\u043e\u0439: CRUD, \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438<\/h3>\n<p>\u0412 BPM \u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u043e\u0444\u0438\u043b\u044f\u043c\u0438. \u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u044b\u0431\u043e\u0440\u043a\u0443, \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e, \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u044b, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435, \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0431\u0435\u0437\u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442:<\/p>\n<pre><code class=\"python\">@dataclass(frozen=True, slots=True)class ProfileQuery:    q: str | None = None    schema_version: str | None = None    validation_state: str | None = None    lifecycle: str = \"active\"    include_deleted: bool = False    limit: int = 50    offset: int = 0    sort: str = \"updated_at\"    order: str = \"desc\"class ProfileService:    @staticmethod    def _validation_state(profile: Profile) -&gt; str:        if not profile.flags:            return \"not_validated\"        try:            validate_profile_payload_with_schema(                {                    \"channel\": profile.schema_version,                    \"policies\": profile.flags,                }            )        except (PolicyValidationError, ValueError):            return \"invalid\"        return \"valid\"<\/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>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 (<code>valid<\/code>, <code>invalid<\/code>, <code>not_validated<\/code>) \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0432 \u0431\u0430\u0437\u0435. \u041e\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u0445 <code>flags<\/code> \u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b Firefox.<\/p>\n<p>\u042d\u0442\u043e \u043e\u0441\u043e\u0437\u043d\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0415\u0441\u043b\u0438 \u0441\u0445\u0435\u043c\u0430 Firefox \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0430\u0441\u044c, \u0441\u0442\u0430\u0440\u043e\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>valid<\/code> \u043c\u043e\u0433\u043b\u043e \u0431\u044b \u0441\u0442\u0430\u0442\u044c \u043b\u043e\u0436\u043d\u044b\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u0437 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f9b\/cd4\/a42\/f9bcd4a4235796910bd26746bb6a3a49.png\" width=\"4508\" height=\"1702\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f9b\/cd4\/a42\/f9bcd4a4235796910bd26746bb6a3a49.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f9b\/cd4\/a42\/f9bcd4a4235796910bd26746bb6a3a49.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0416\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c;<\/p>\n<\/li>\n<li>\n<p>\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c;<\/p>\n<\/li>\n<li>\n<p>\u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0437 \u0430\u0440\u0445\u0438\u0432\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0431\u0435\u0437\u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0410\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437 <code>deleted_at<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u044d\u0442\u043e \u043c\u044f\u0433\u043a\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435. \u0412 0.8.8 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0431\u0435\u0437\u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441 \u044f\u0432\u043d\u044b\u043c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c. \u0414\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u044b\u043c, \u0430 \u043d\u0435\u043e\u0431\u0440\u0430\u0442\u0438\u043c\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u044f\u0432\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u043e.<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u0412\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c<\/h3>\n<p>\u0412\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u2014 \u0441\u0430\u043c\u0430\u044f \u0432\u0430\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438 0.8.8.<\/p>\n<p>\u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e: \u0432\u0437\u044f\u0442\u044c \u0441\u0445\u0435\u043c\u0443 Firefox, \u043f\u0440\u043e\u0439\u0442\u0438\u0441\u044c \u043f\u043e <code>properties<\/code>, \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u0438\u0442\u0438\u043a, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0424\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0440\u0435\u0448\u0435\u043d\u0430.<\/p>\n<p>\u041d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043f\u043b\u043e\u0445\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u044f.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u0441\u043c\u0435\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, CIS-\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438, \u0440\u0443\u0447\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u043a\u0438, \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043b\u0438\u043d\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433. \u0415\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 0.8.8 \u0440\u0430\u0437\u0434\u0435\u043b \u0412\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d \u043d\u0430 \u0442\u0440\u0438 \u0440\u0435\u0436\u0438\u043c\u0430:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0420\u0435\u0436\u0438\u043c<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0427\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0414\u043b\u044f \u0447\u0435\u0433\u043e \u043d\u0443\u0436\u0435\u043d<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0448\u0438\u0431\u043a\u0438, \u0441\u043f\u043e\u0440\u043d\u044b\u0435 \u043c\u0435\u0441\u0442\u0430, CIS \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u043d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435\/\u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435\/\u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435\/\u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0411\u044b\u0441\u0442\u0440\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u044f<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u043e, \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0432 \u043f\u0440\u043e\u0444\u0438\u043b\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0410\u043d\u0430\u043b\u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041a\u0430\u0442\u0430\u043b\u043e\u0433<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u043e\u0438\u0441\u043a \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u0438\u0442\u0438\u043a<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1fa\/d25\/418\/1fad2541870e3d139ce2ed469dfc7d34.png\" width=\"4544\" height=\"2060\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/1fa\/d25\/418\/1fad2541870e3d139ce2ed469dfc7d34.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1fa\/d25\/418\/1fad2541870e3d139ce2ed469dfc7d34.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bcf\/72e\/dcf\/bcf72edcf84a7c9ff60912b483a596ad.png\" width=\"4480\" height=\"1990\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/bcf\/72e\/dcf\/bcf72edcf84a7c9ff60912b483a596ad.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bcf\/72e\/dcf\/bcf72edcf84a7c9ff60912b483a596ad.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c4f\/a10\/729\/c4fa107295fde27d270c79e8ab7dc1e4.png\" width=\"3449\" height=\"2051\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c4f\/a10\/729\/c4fa107295fde27d270c79e8ab7dc1e4.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c4f\/a10\/729\/c4fa107295fde27d270c79e8ab7dc1e4.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u042d\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043d\u044b\u043c, \u043d\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043e\u043d\u043e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e\u0435. \u041d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0440\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0438, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434 \u043d\u0438\u043c\u0438 \u043d\u0435\u0442 \u043e\u0431\u0449\u0435\u0433\u043e \u0438\u043d\u0432\u0435\u043d\u0442\u0430\u0440\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.<\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043d\u0443\u0436\u0435\u043d \u043e\u0431\u0449\u0438\u0439 \u0441\u043b\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438\u0448\u043b\u0438 \u0438\u0437 \u0441\u0445\u0435\u043c\u044b Firefox;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u043f\u0440\u043e\u0444\u0438\u043b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u0438\u0448\u043b\u0438 \u0438\u0437 CIS-\u0441\u043b\u043e\u0451\u0432;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u0431\u044b\u043b\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0441\u0445\u0435\u043c\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u0443\u0441\u0442\u0430\u0440\u0435\u043b\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043f\u043e\u0438\u0441\u043a\u0430 \u043a \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c\u0443 \u043c\u0435\u0441\u0442\u0443 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f: \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u041d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0438 \u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u043c\u0435\u0442\u044c \u0442\u0440\u0438 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0418\u043d\u0430\u0447\u0435 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0440\u0441\u0438\u0439 \u043f\u043e\u044f\u0432\u044f\u0442\u0441\u044f \u0440\u0430\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f: \u0432 \u043e\u0434\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a, \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u0438\u043d\u0430\u0447\u0435, \u0432 \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u0437\u0430\u0431\u044b\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 0.8.8 \u0412\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u043e\u0431\u0449\u0435\u0433\u043e \u0438\u043d\u0432\u0435\u043d\u0442\u0430\u0440\u044f \u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u0435\u0442\u0430\u043b\u0435\u0439.<\/p>\n<h3>\u0421\u0445\u0435\u043c\u044b Firefox \u043a\u0430\u043a \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/h3>\n<p>BPM \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c \u043e\u0442 \u0432\u0435\u0440\u0441\u0438\u0439 Firefox. \u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f, \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f, \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u044e\u0442, \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Release, \u0447\u0430\u0441\u0442\u044c \u0434\u043e\u043b\u0436\u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043b\u0438 \u0438\u043d\u0430\u0447\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 ESR.<\/p>\n<p>\u0412 0.8.8 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0434\u0432\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043a\u0430\u043d\u0430\u043b\u0430 \u0441\u0445\u0435\u043c:<\/p>\n<pre><code class=\"python\">@dataclass(frozen=True, slots=True)class SchemaChannel:    value: str    label: str    filename: str    raw_dir: str    mozilla_version: str    family: str    is_default: bool = FalseSCHEMA_CHANNELS: tuple[SchemaChannel, ...] = (    SchemaChannel(        value=\"esr-140.12\",        label=\"ESR 140.12\",        filename=\"firefox-esr-140.12.json\",        raw_dir=\"esr14012\",        mozilla_version=\"140.12\",        family=\"esr\",        is_default=True,    ),    SchemaChannel(        value=\"release-152\",        label=\"Release 152\",        filename=\"firefox-release-152.json\",        raw_dir=\"release152\",        mozilla_version=\"152.0\",        family=\"release\",    ),)<\/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>\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b \u0432\u043b\u0438\u044f\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0449\u0435\u0439:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u0440\u043e\u0444\u0438\u043b\u044f;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0438\u043c\u043f\u043e\u0440\u0442 <code>policies.json<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0442\u0430\u0440\u044b\u0445 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u043a\u0440\u044b\u0442\u0438\u0435 All settings;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u0438\u0442\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0441\u0442\u044c \u0432 Release, \u043d\u043e \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f ESR.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a00\/17d\/864\/a0017d864010229392aeaca9cfa3b5b5.png\" width=\"3571\" height=\"816\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a00\/17d\/864\/a0017d864010229392aeaca9cfa3b5b5.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a00\/17d\/864\/a0017d864010229392aeaca9cfa3b5b5.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0438\u0434\u044f\u0442 \u043d\u0430 ESR. \u0415\u0441\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u0442 \u0432 \u0435\u0433\u043e \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Firefox, \u043e\u043d \u043d\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442, \u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0440\u0438\u0441\u043a \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<h3>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0445\u0435\u043c<\/h3>\n<p>\u0421\u0445\u0435\u043c\u044b Firefox \u0432 BPM \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c. \u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a \u0441\u0445\u0435\u043c \u0438\u0449\u0435\u0442 \u0444\u0430\u0439\u043b \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0442\u0430\u043c, \u0433\u0434\u0435 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0433\u043e JSON Schema.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442:<\/p>\n<pre><code class=\"python\">@lru_cache(maxsize=16)def load_schema(profile: str, *, allow_stub_fallback: bool = False) -&gt; dict[str, Any]:    if profile not in _PROFILE_FILES:        raise UnsupportedProfileError(            f\"Unsupported profile '{profile}'. Supported: {', '.join(_PROFILE_FILES)}\"        )    _ensure_dirs()    static_path = _STATIC_DIR \/ _PROFILE_FILES[profile]    mozilla_path = _mozilla_raw_schema_path(profile)    bundled_policy_path = _bundled_policy_schema_path(profile)    cache_path = _CACHE_DIR \/ _PROFILE_FILES[profile]    if static_path.exists():        return _read_json_file(static_path)    if mozilla_path.exists():        return _read_json_file(mozilla_path)    if bundled_policy_path.exists():        return _read_json_file(bundled_policy_path)    if cache_path.exists():        return _read_json_file(cache_path)    if not allow_stub_fallback:        raise SchemaNotFoundError(            f\"Schema file not found for profile '{profile}'\"        )    stub = _minimal_schema(f\"Firefox {profile} Policies (stub)\")    _write_json_file(cache_path, stub)    return stub<\/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>\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e, \u0447\u0442\u043e fallback \u043d\u0430 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0443 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u043c\u043e\u043b\u0447\u0430 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u043f\u043e \u043d\u0435\u043f\u043e\u043b\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u0435. \u0415\u0441\u043b\u0438 \u0441\u0445\u0435\u043c\u0430 \u043f\u043e\u0442\u0435\u0440\u044f\u043b\u0430\u0441\u044c \u043f\u0440\u0438 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0435 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438, \u044d\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438, \u0430 \u043d\u0435 \u043f\u043e\u0432\u043e\u0434 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0438\u0434, \u0447\u0442\u043e \u0432\u0441\u0451 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<h3>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u043b\u0438\u0442\u0438\u043a<\/h3>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043f\u043e\u0432\u0435\u0440\u0445 <code>jsonschema<\/code>, \u043d\u043e \u0441\u044b\u0440\u043e\u0439 <code>ValidationError<\/code> \u043d\u0435\u0443\u0434\u043e\u0431\u0435\u043d \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438 API. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435 \u0441\u0442\u0435\u043a \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b: \u043a\u0430\u043a\u0430\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430, \u043a\u0430\u043a\u043e\u0439 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0435 \u0442\u0430\u043a.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 \u0435\u0441\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043e\u0448\u0438\u0431\u043a\u0438:<\/p>\n<pre><code class=\"python\">@dataclassclass PolicyValidationIssue:    policy: str | None    path: list[str | int]    message: strclass PolicyValidationError(ValueError):    def __init__(self, issues: list[PolicyValidationIssue]) -&gt; None:        super().__init__(\"Policy validation failed\")        self.issues = issues<\/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>\u041f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0442\u043e\u0440\u0430 BPM \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0436\u0435\u0441\u0442\u043e\u0447\u0430\u0435\u0442 \u043a\u043e\u0440\u0435\u043d\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430:<\/p>\n<pre><code class=\"python\">def _normalize_policy_document_schema(schema: JsonSchema) -&gt; JsonSchema:    if schema.get(\"type\") != \"object\":        return schema    properties = schema.get(\"properties\")    if not isinstance(properties, dict) or not properties:        return schema    if schema.get(\"additionalProperties\") is False:        return schema    normalized = dict(schema)    normalized[\"additionalProperties\"] = False    return normalized<\/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>\u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 top-level \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043b\u0438 \u043a\u0430\u043a \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u0441\u043d\u0438\u043c\u043a\u0435 \u0441\u0445\u0435\u043c\u044b \u0431\u044b\u043b\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u044f\u0433\u043a\u043e\u0435 <code>additionalProperties<\/code>.<\/p>\n<p>\u0421\u0430\u043c \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">def validate_profile_payload_with_schema(payload: dict[str, Any]) -&gt; None:    channel = payload.get(\"channel\") or DEFAULT_RELEASE_SCHEMA_CHANNEL    policies = payload.get(\"policies\") or {}    if not isinstance(policies, dict):        raise PolicyValidationError(            [                PolicyValidationIssue(                    policy=None,                    path=[\"policies\"],                    message=\"Expected object with policy mappings\",                )            ]        )    validate_profile_policies_or_raise_for_channel(policies, channel)<\/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>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 <code>policies.json<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c API \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0432 All settings \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u044b\u0445 \u043c\u0435\u0441\u0442.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u043c\u043f\u043e\u0440\u0442 policies.json: \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438<\/h3>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442 Firefox Enterprise <code>policies.json<\/code> \u2014 \u044d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c.<\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0438\u043d\u043e\u0441\u0438\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442:<\/p>\n<pre><code class=\"json\">{  \"policies\": {    \"DisableTelemetry\": true,    \"DisablePrivateBrowsing\": false  }}<\/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>BPM \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u044d\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 Firefox, \u0430 \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 JSON. \u0415\u0441\u043b\u0438 \u0443 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \u043d\u0435\u0442 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>policies<\/code>, \u044d\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0430.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"python\">def parse_firefox_policies_document(document: Any) -&gt; dict[str, Any]:    if not isinstance(document, dict):        raise FirefoxPoliciesImportError(            [                FirefoxPoliciesImportIssue(                    path=[],                    message=\"Expected Firefox policies.json root object\",                )            ]        )    issues: list[FirefoxPoliciesImportIssue] = []    if \"policies\" not in document:        issues.append(            FirefoxPoliciesImportIssue(                path=[\"policies\"],                message=\"Missing required Firefox policies object\",            )        )    unsupported_keys = sorted(key for key in document if key != \"policies\")    for key in unsupported_keys:        issues.append(            FirefoxPoliciesImportIssue(                path=[key],                message=f\"Unsupported top-level key '{key}'\",            )        )    policies = document.get(\"policies\")    if \"policies\" in document and not isinstance(policies, dict):        issues.append(            FirefoxPoliciesImportIssue(                path=[\"policies\"],                message=\"Expected policies to be an object\",            )        )    if issues:        raise FirefoxPoliciesImportError(issues)    return dict(policies)<\/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>\u041f\u043e\u0441\u043b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u043a\u0430\u043d\u0430\u043b\u0443 Firefox:<\/p>\n<pre><code class=\"python\">def validate_firefox_policies_document(    document: Any,    channel: str,) -&gt; dict[str, Any]:    flags = parse_firefox_policies_document(document)    schema = load_policy_schema_for_channel(channel)    try:        validate_profile_policies_or_raise(flags, schema)    except PolicyValidationError as exc:        raise FirefoxPoliciesDocumentValidationError(            [                PolicyValidationIssue(                    policy=issue.policy,                    path=[\"policies\", *issue.path],                    message=issue.message,                )                for issue in exc.issues            ]        ) from exc    return flags<\/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>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <code>path=[\"policies\", *issue.path]<\/code>. \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u043a\u0430\u0440\u0442\u043e\u0439 \u043f\u043e\u043b\u0438\u0442\u0438\u043a, \u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0443\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e <code>policies.json<\/code>. \u0418\u043d\u0430\u0447\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0443\u0432\u0438\u0434\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u043f\u043b\u043e\u0445\u043e \u0441\u043e\u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0441 \u0444\u0430\u0439\u043b\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043d \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7ff\/33b\/e2c\/7ff33be2cc4876fa311b641082f04e2f.png\" width=\"4041\" height=\"2124\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/7ff\/33b\/e2c\/7ff33be2cc4876fa311b641082f04e2f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7ff\/33b\/e2c\/7ff33be2cc4876fa311b641082f04e2f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u042d\u043a\u0441\u043f\u043e\u0440\u0442: \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442 Firefox<\/h3>\n<p>\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435: \u0431\u0435\u0440\u0451\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 <code>flags<\/code> \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u0430\u043d\u043e\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 Firefox.<\/p>\n<pre><code class=\"python\">def render_firefox_policies_document(    flags: dict[str, Any] | None,) -&gt; dict[str, Any]:    if isinstance(flags, dict) and isinstance(flags.get(\"policies\"), dict):        return {\"policies\": dict(flags[\"policies\"])}    return {\"policies\": dict(flags or {})}<\/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>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0437\u0430\u0449\u0438\u0442\u043d\u0430\u044f \u0432\u0435\u0442\u043a\u0430 \u0441 <code>flags.get(\"policies\")<\/code> \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c\u0438 \u0441\u0442\u0430\u0440\u044b\u043c\u0438 \u0438\u043b\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438, \u0433\u0434\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0436\u0435 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b\u0442\u044c \u0432 \u043e\u0431\u0451\u0440\u0442\u043a\u0435 <code>policies<\/code>.<\/p>\n<p>API-\u043e\u0442\u0432\u0435\u0442 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430:<\/p>\n<pre><code class=\"python\">def _build_firefox_policies_json_response(    profile: ProfileRead,    *,    profile_id: int,    download: int = 0,    indent: int | None = None,    pretty: int = 0,) -&gt; Response:    if indent is None and pretty:        indent = 2    body_json = json.dumps(        render_firefox_policies_document(profile.flags),        indent=indent,    )    headers: dict[str, str] = {}    if download:        headers[\"Content-Disposition\"] = (            f'attachment; filename=\"profile-{profile_id}-policies.json\"'        )    return Response(        content=body_json,        media_type=\"application\/json\",        headers=headers,    )<\/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>\u0422\u043e \u0435\u0441\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438, \u043d\u043e \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 Firefox Enterprise <code>policies.json<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cd2\/7b2\/6d6\/cd27b26d6ee80cff1711e42577f421f4.png\" width=\"4393\" height=\"2291\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/cd2\/7b2\/6d6\/cd27b26d6ee80cff1711e42577f421f4.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cd2\/7b2\/6d6\/cd27b26d6ee80cff1711e42577f421f4.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>API: \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430<\/h3>\n<p>API \u0432 BPM \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0443\u0436\u0435\u043d \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u0430\u043a \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u043e\u043f\u043e\u0440\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u042d\u0442\u043e \u0435\u0449\u0451 \u0438 \u0431\u0443\u0434\u0443\u0449\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439:<\/p>\n<pre><code>GET    \/api\/profilesGET    \/api\/profiles\/statsGET    \/api\/profiles\/{id}POST   \/api\/profilesPATCH  \/api\/profiles\/{id}DELETE \/api\/profiles\/{id}POST   \/api\/profiles\/{id}\/restoreDELETE \/api\/profiles\/{id}\/hardDELETE \/api\/profiles\/reset<\/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>\u0418\u043c\u043f\u043e\u0440\u0442, \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430:<\/p>\n<pre><code>POST \/api\/profiles\/import\/firefox\/policies.jsonGET  \/api\/export\/profiles\/{id}\/firefox\/policies.jsonPOST \/api\/validate\/{profile}<\/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>\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u044d\u0442\u043e \u0443\u0436\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0432 BPM, \u0430 \u0437\u0430\u0442\u0435\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0437\u0430\u0431\u0438\u0440\u0430\u0442\u044c <code>policies.json<\/code> \u0438 \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 Ansible, Salt, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0430\u0433\u0435\u043d\u0442, MDM \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u043a\u043e\u043d\u0442\u0443\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043c\u0438.<\/p>\n<p>\u0412 0.9.0 \u044d\u0442\u043e \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438: \u043a\u0430\u043a\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044f \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u043c, \u0430 \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043a\u0430 \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c\u0438.<\/p>\n<h3>HTML-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b: \u043f\u043e\u0447\u0435\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d<\/h3>\n<p>HTML-\u0447\u0430\u0441\u0442\u044c \u0436\u0438\u0432\u0451\u0442 \u0432 <code>app\/web<\/code>. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 web-router \u043e\u0442\u0434\u0430\u0451\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0435\u0439.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e:<\/p>\n<pre><code class=\"python\">@router.get(\"\/profiles\", response_class=HTMLResponse)async def profiles_page(request: Request, session: AsyncSession) -&gt; HTMLResponse:    return templates.TemplateResponse(        request,        \"profiles_library.html\",        _build_profiles_page_context(            request,            title=f\"Library \u2014 {settings.APP_NAME}\",            route_mode=\"library\",        ),    )@router.get(\"\/profiles\/compare\", response_class=HTMLResponse)async def profiles_compare_page(request: Request) -&gt; HTMLResponse:    return templates.TemplateResponse(        request,        \"profiles_compare.html\",        _build_profiles_page_context(            request,            title=f\"Compare profile settings \u2014 {settings.APP_NAME}\",            route_mode=\"compare\",        ),    )@router.get(\"\/profiles\/{profile_id}\/settings\", response_class=HTMLResponse)async def profiles_settings_page(    request: Request,    profile_id: int,    session: AsyncSession,) -&gt; HTMLResponse:    profile = await ProfileService.get(session, profile_id)    if profile is None:        raise HTTPException(status_code=404, detail=\"Profile not found\")    return templates.TemplateResponse(        request,        \"profiles_settings.html\",        _build_profiles_page_context(            request,            title=f\"{profile.name} \u2014 All settings \u2014 {settings.APP_NAME}\",            route_mode=\"settings\",            editing_profile_id=profile_id,            editing_profile_schema_version=profile.schema_version,            editing_profile_initial=profile.model_dump(mode=\"json\"),        ),    )<\/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>\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e \u043d\u0435 \u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442. \u0412\u0441\u0435 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b: \u043b\u043e\u043a\u0430\u043b\u044c, \u0442\u0435\u043c\u0443, \u0432\u0435\u0440\u0441\u0438\u044e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f, \u0441\u0441\u044b\u043b\u043a\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043c\u0435\u0436\u0434\u0443 \u0440\u0435\u0436\u0438\u043c\u0430\u043c\u0438, \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0435.<\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441:<\/p>\n<ul>\n<li>\n<p>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d \u043d\u0430 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u0443\u044e \u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0435\u0436\u0438\u043c\u044b \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u0445;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d\u0438 \u043d\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043f\u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u043a \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0412 BPM \u0448\u0435\u0441\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043b\u043e\u043a\u0430\u043b\u0435\u0439:<\/p>\n<ul>\n<li>\n<p>English;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0443\u0441\u0441\u043a\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>Deutsch;<\/p>\n<\/li>\n<li>\n<p>\u7b80\u4f53\u4e2d\u6587;<\/p>\n<\/li>\n<li>\n<p>Fran\u00e7ais;<\/p>\n<\/li>\n<li>\n<p>Espa\u00f1ol.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/02c\/59b\/7e0\/02c59b7e01ec9bebbd396cd297bfeee8.png\" width=\"4668\" height=\"2236\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/02c\/59b\/7e0\/02c59b7e01ec9bebbd396cd297bfeee8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/02c\/59b\/7e0\/02c59b7e01ec9bebbd396cd297bfeee8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u044d\u0442\u043e \u043d\u0435 \u0443\u043a\u0440\u0430\u0448\u0435\u043d\u0438\u0435. \u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b \u043d\u0430 \u043f\u0430\u0440\u0438\u0442\u0435\u0442 \u043a\u043b\u044e\u0447\u0435\u0439, \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b, \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u044e.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0430\u0432\u0438\u043b\u0430: \u0432 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438, \u0431\u0440\u0435\u043d\u0434, API-\u0442\u0435\u0440\u043c\u0438\u043d, JSON-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u043d\u0435\u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442.<\/p>\n<p>\u0412 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u043c \u0441\u043c\u044b\u0441\u043b\u0435 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0434\u0435\u0441\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0435\u0449\u0451 \u043e\u0434\u043d\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e: \u043e\u043d\u0430 \u043b\u043e\u043c\u0430\u0435\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0445\u0440\u0443\u043f\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0415\u0441\u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0430, \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0438\u043b\u0438 \u0444\u0438\u043b\u044c\u0442\u0440 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e-\u0430\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438, \u0437\u043d\u0430\u0447\u0438\u0442, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0435\u0449\u0451 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432. \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u043d\u0435\u043c\u0435\u0446\u043a\u0438\u0439 \u0438\u043b\u0438 \u0444\u0440\u0430\u043d\u0446\u0443\u0437\u0441\u043a\u0438\u0439 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442, \u0433\u0434\u0435 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043f\u043b\u043e\u0445\u0430\u044f \u0441\u0435\u0442\u043a\u0430, \u0433\u0434\u0435 \u043d\u0435\u0432\u0435\u0440\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441.<\/p>\n<h3>\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 CSP<\/h3>\n<p>\u0423 BPM \u0435\u0441\u0442\u044c middleware \u0434\u043b\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"python\">class SecurityHeadersMiddleware:    def __init__(self, app: ASGIApp, *, csp: str | None = None) -&gt; None:        self.app = app        self.csp = csp or (            \"default-src 'self'; \"            \"script-src 'self'; \"            \"style-src 'self'; \"            \"img-src 'self' data:; \"            \"font-src 'self'; \"            \"connect-src 'self'; \"            \"worker-src 'self'; \"            \"child-src 'self'; \"            \"frame-ancestors 'none'; \"            \"base-uri 'self'; \"            \"form-action 'self'\"        )    async def __call__(self, scope: Scope, receive: Receive, send: Send) -&gt; None:        if scope[\"type\"] != \"http\":            await self.app(scope, receive, send)            return        async def send_with_security_headers(message: Message) -&gt; None:            if message[\"type\"] == \"http.response.start\":                headers = message.setdefault(\"headers\", [])                self._append_if_missing(headers, b\"x-frame-options\", b\"DENY\")                self._append_if_missing(headers, b\"x-content-type-options\", b\"nosniff\")                self._append_if_missing(headers, b\"referrer-policy\", b\"no-referrer\")                self._append_if_missing(                    headers,                    b\"permissions-policy\",                    b\"geolocation=(), microphone=(), camera=()\",                )                self._append_if_missing(                    headers,                    b\"content-security-policy\",                    self.csp.encode(\"utf-8\"),                )            await send(message)        await self.app(scope, receive, send_with_security_headers)<\/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>HSTS \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0451\u043d \u0436\u0451\u0441\u0442\u043a\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e BPM \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u0431\u0435\u0437 HTTPS. \u042d\u0442\u043e \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u00ab\u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430\u00bb \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0432\u0440\u0435\u0434\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c.<\/p>\n<p>\u0417\u0430\u0442\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u2014 \u0437\u0430\u043f\u0440\u0435\u0442 \u0444\u0440\u0435\u0439\u043c\u043e\u0432, \u0437\u0430\u043f\u0440\u0435\u0442 sniffing, <code>no-referrer<\/code>, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u2014 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b.<\/p>\n<h3>SQLite \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, PostgreSQL \u043a\u0430\u043a \u043f\u0443\u0442\u044c \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f<\/h3>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e BPM \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 SQLite. \u042d\u0442\u043e \u043f\u0440\u0430\u0433\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445;<\/p>\n<\/li>\n<li>\n<p>\u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u043e\u0434\u0438\u043d\u043e\u0447\u043d\u043e\u0433\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430, \u0441\u0442\u0435\u043d\u0434\u0430, \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438\u043b\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043d\u0435 \u0437\u0430\u0432\u044f\u0437\u0430\u043d\u0430 \u043d\u0430\u043c\u0435\u0440\u0442\u0432\u043e \u043d\u0430 SQLite. \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u0445 \u0435\u0441\u0442\u044c \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 PostgreSQL-\u043d\u0430\u0431\u043e\u0440, \u0430 \u0441\u043b\u043e\u0439 SQLAlchemy \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0432\u0438\u0433\u0430\u0442\u044c\u0441\u044f \u043a \u0431\u043e\u043b\u0435\u0435 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e\u043c\u0443 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<p>\u0412 \u0431\u0430\u0437\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043d\u0435 \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0430 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0441 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u0438 \u0440\u0435\u0432\u0438\u0437\u0438\u0435\u0439. \u0414\u043b\u044f \u0432\u0435\u0440\u0441\u0438\u0438 1.0 \u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u044d\u0442\u0430\u043f\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0438, \u0436\u0443\u0440\u043d\u0430\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0440\u043e\u0433\u043e\u043c \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439, \u043d\u043e \u0434\u043b\u044f 0.8.8 \u0432\u0430\u0436\u043d\u0435\u0435 \u0431\u044b\u043b\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c.<\/p>\n<h3>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u00ab\u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0443 \u043c\u0435\u043d\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435\u00bb \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a:<\/p>\n<pre><code class=\"bash\">make typecheckmake lintmake test-fastmake test-contractmake test-firefox-schema-contractmake test-locale-contractmake coveragemake test-uimake test-releasemake test-firefox-live<\/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>\u041e\u043d\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043d\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e.<\/p>\n<p>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u043a\u043e\u043d\u0442\u0443\u0440 \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0437\u0430\u0449\u0438\u0449\u0430\u044e\u0442 API, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f, \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0441\u0445\u0435\u043c\u044b \u0438 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430. UI-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 Chromium\/Selenium \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u043b\u0435\u0439, \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0441\u043f\u0438\u0441\u043a\u043e\u0432, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432. Live Firefox-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0443\u0436\u043d\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e: \u043e\u043d\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 BPM, \u0430 \u0442\u043e, \u0447\u0442\u043e \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <code>policies.json<\/code> \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 Firefox.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/393\/2ce\/212\/3932ce212b3ce93bde4bbd0887d4ef38.png\" width=\"3481\" height=\"2121\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/393\/2ce\/212\/3932ce212b3ce93bde4bbd0887d4ef38.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/393\/2ce\/212\/3932ce212b3ce93bde4bbd0887d4ef38.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 0.8.8 \u043f\u043e\u0441\u043b\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0435\u0440\u0435\u0440\u0430\u0431\u043e\u0442\u043a\u0438 All settings \u0432\u0430\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u0435\u043b\u0451\u043d\u044b\u043c\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b, \u043d\u043e \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438. \u0418\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043b\u043e\u043c\u0430\u044e\u0442 \u043d\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043a\u0430\u043a \u0442\u0430\u043a\u043e\u0432\u0443\u044e, \u0430 \u0441\u0432\u044f\u0437\u043a\u0443: \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u2192 \u043b\u043e\u043a\u0430\u043b\u044c \u2192 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u2192 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u2192 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u2192 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u2192 \u044d\u043a\u0441\u043f\u043e\u0440\u0442.<\/p>\n<h3>\u0427\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043a 0.8.8<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, 0.8.8 \u2014 \u044d\u0442\u043e \u0432\u0435\u0440\u0441\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 Browser Policy Manager \u0441\u0442\u0430\u043b \u043f\u043e\u0445\u043e\u0436 \u043d\u0435 \u043d\u0430 \u043d\u0430\u0431\u043e\u0440 \u044d\u043a\u0440\u0430\u043d\u043e\u0432, \u0430 \u043d\u0430 \u0446\u0435\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u0441\u0440\u0435\u0434\u0443.<\/p>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u2014 All settings. \u0422\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a Firefox, \u0430 \u0442\u0440\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0436\u0438\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043e\u0434\u043d\u0438\u043c \u0438\u043d\u0432\u0435\u043d\u0442\u0430\u0440\u0451\u043c:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u2014 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u2014 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0442\u043e, \u0447\u0442\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u2014 \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0442\u043e\u0440\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u2014 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0441\u0442\u0430\u043b \u043b\u0443\u0447\u0448\u0435 \u0432\u044b\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438. \u041f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u043f\u0438\u0441\u043a\u0438, \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430, \u0431\u043e\u043b\u0435\u0435 \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a, \u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u044f \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435, \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u043a \u0434\u043b\u0438\u043d\u043d\u044b\u043c \u043d\u0430\u0431\u043e\u0440\u0430\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u044f\u0436\u0451\u043b\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432.<\/p>\n<p>\u0422\u0440\u0435\u0442\u044c\u0435 \u2014 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0445\u0435\u043c \u0434\u043e Firefox Release 152 \u0438 ESR 140.12. \u0414\u043b\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044d\u0442\u043e \u043d\u0435 \u043a\u043e\u0441\u043c\u0435\u0442\u0438\u043a\u0430. \u041a\u0430\u0436\u0434\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, All settings, \u0438\u043c\u043f\u043e\u0440\u0442, \u044d\u043a\u0441\u043f\u043e\u0440\u0442, CIS-\u0441\u043b\u043e\u0438 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e.<\/p>\n<p>\u0427\u0435\u0442\u0432\u0451\u0440\u0442\u043e\u0435 \u2014 \u0431\u043e\u043b\u0435\u0435 \u0437\u0440\u0435\u043b\u044b\u0439 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043f\u0440\u043e\u0444\u0438\u043b\u044f: \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0431\u0435\u0437\u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435, \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u0427\u0442\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0434\u043e 0.9 \u0438 1.0<\/h3>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u044d\u0442\u0430\u043f \u2014 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f.<\/p>\n<p>\u042f \u0445\u043e\u0447\u0443 \u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0451 \u043d\u0435 \u043a\u0430\u043a \u043d\u0430\u0431\u043e\u0440 \u0440\u0430\u0437\u0440\u043e\u0437\u043d\u0435\u043d\u043d\u044b\u0445 Markdown-\u0444\u0430\u0439\u043b\u043e\u0432, \u0430 \u043a\u0430\u043a \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u0443\u044e \u0431\u0430\u0437\u0443 \u043d\u0430 DITA-OT. \u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f: \u0443 BPM \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u0439 \u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432.<\/p>\n<p>\u041d\u0443\u0436\u043d\u044b \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c:<\/p>\n<ul>\n<li>\n<p>\u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c Firefox Policies;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e CIS-\u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e API \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0445\u0435\u043c Firefox;<\/p>\n<\/li>\n<li>\n<p>\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0445, \u043e\u043d\u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0447\u043d\u0443\u0442 \u0440\u0430\u0441\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f. \u041e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443, \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d \u0432 \u0434\u0432\u0443\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0434\u0435\u0442\u0430\u043b\u044f\u043c\u0438, \u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0443\u0439\u0434\u0451\u0442 \u0432\u043f\u0435\u0440\u0451\u0434 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.<\/p>\n<p>DITA-OT \u0437\u0434\u0435\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u0430\u043a \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u0430\u0431\u043e\u0440 \u0441\u043c\u044b\u0441\u043b\u043e\u0432\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0438\u0437 \u043d\u0438\u0445 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 0.9.0 \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0434\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0434\u043e 1.0: \u0441\u0442\u0430\u0431\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u0432, \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0430, \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u2014 \u0431\u043e\u043b\u0435\u0435 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u0434 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u0438\u043b\u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043c\u0438.<\/p>\n<h3>\u0412\u043c\u0435\u0441\u0442\u043e \u0432\u044b\u0432\u043e\u0434\u0430<\/h3>\n<p>Browser Policy Manager \u043d\u0430\u0447\u0438\u043d\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f <code>policies.json<\/code>, \u043d\u043e \u043a \u0432\u0435\u0440\u0441\u0438\u0438 0.8.8 \u0441\u0442\u0430\u043b \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439.<\/p>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0438\u0434\u0435\u0439:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0432\u0430\u0436\u043d\u0435\u0435 \u0444\u0430\u0439\u043b\u0430;<\/p>\n<\/li>\n<li>\n<p><code>policies.json<\/code> \u2014 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442, \u0430 \u043d\u0435 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u043c\u043e\u0434\u0435\u043b\u044c;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043e\u0434\u043d\u0438\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445;<\/p>\n<\/li>\n<li>\n<p>\u0441\u0445\u0435\u043c\u044b Firefox \u2014 \u044d\u0442\u043e \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a;<\/p>\n<\/li>\n<li>\n<p>All settings \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f, \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433;<\/p>\n<\/li>\n<li>\n<p>\u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u2014 \u0447\u0430\u0441\u0442\u044c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u0439 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u0442\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044c\u044e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u0430 \u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043a \u043d\u0435\u043c\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u043f\u0440\u043e\u0435\u043a\u0442 \u043e\u0442\u043a\u0440\u044b\u0442, \u043a\u043e\u0434 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 GitHub: <a href=\"https:\/\/github.com\/Goudron\/browser-policy-manager\" rel=\"noopener noreferrer nofollow\">github.com\/Goudron\/browser-policy-manager<\/a>.<\/p>\n<p>\u041c\u043d\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u044c \u043e\u0442 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u0432, \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u0432 \u043f\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u0432 \u043f\u043e \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u043c\u0435\u0441\u0442\u0430\u043c \u0438 \u0442\u0435\u0445, \u043a\u0442\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0430\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u0432 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f\u0445:<\/p>\n<ul>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f Firefox \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0434\u043e\u0431\u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0447\u0435\u0433\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0432 \u0438\u043c\u043f\u043e\u0440\u0442\u0435, \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u0442\u0430\u043a\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0443\u0436\u043d\u0430 \u043b\u0438 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 \u0438 \u0432 \u043a\u0430\u043a\u043e\u043c \u0432\u0438\u0434\u0435.<\/p>\n<\/li>\n<\/ul>\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\/1051206\/\">https:\/\/habr.com\/ru\/articles\/1051206\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f\u0445 \u044f \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b, \u0437\u0430\u0447\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f Browser Policy Manager, \u043f\u043e\u0447\u0435\u043c\u0443 \u044f \u043d\u0430\u0447\u0430\u043b \u0441 Firefox Enterprise Policies \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 \u0441\u0442\u0430\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u00ab\u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 policies.json\u00bb. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u0431\u043e\u043b\u0435\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f. \u0417\u0434\u0435\u0441\u044c \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c, \u043a\u0430\u043a Browser Policy Manager \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 0.8.8.\u0412\u0435\u0440\u0441\u0438\u044f 0.8.8 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u0430\u0436\u043d\u0430 \u0442\u0435\u043c, \u0447\u0442\u043e \u0432 \u043d\u0435\u0439 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043b\u043e\u0436\u0438\u043b\u0430\u0441\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430:\u0435\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439;\u0435\u0441\u0442\u044c \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432;\u0435\u0441\u0442\u044c All settings \u043a\u0430\u043a \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0447\u0430\u044f \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a;\u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 JSON-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440;\u0435\u0441\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0433\u043e Firefox Enterprise policies.json;\u0435\u0441\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439;\u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Firefox ESR 140.12 \u0438 Firefox Release 152;\u0435\u0441\u0442\u044c \u0448\u0435\u0441\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u0435\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430;\u0435\u0441\u0442\u044c \u0441\u043b\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a, \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0439, \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a.\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u043b\u043e\u043a \u2014 \u0432\u0435\u0440\u0441\u0438\u044f 0.9.0: \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 DITA-OT, \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430, \u0431\u043e\u043b\u0435\u0435 \u0446\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u0430 \u043f\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0434\u043e 1.0.\u041d\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u00ab\u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c\u00bb \u0441\u0430\u043c \u043f\u0440\u043e\u0434\u0443\u043a\u0442: \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 \u043d\u0451\u043c \u0435\u0441\u0442\u044c, \u0433\u0434\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0433\u0440\u0430\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0438 policies.json, \u043f\u043e\u0447\u0435\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0451\u043d \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432 \u0438 \u043a\u0430\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u044d\u0442\u043e \u043d\u0435 \u0440\u0430\u0437\u0432\u0430\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0441\u0445\u0435\u043c Firefox.\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Browser Policy Manager \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438Browser Policy Manager \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 FastAPI \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u043b\u0438\u0442\u0438\u043a Firefox.\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0442\u0435\u043a:Python 3.14+;FastAPI;Pydantic v2;SQLAlchemy 2.x;Alembic;SQLite \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e;\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 PostgreSQL;Jinja2 \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432;\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b;Monaco Editor \u0434\u043b\u044f JSON-\u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438;jsonschema \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u043b\u0438\u0442\u0438\u043a;pytest, Ruff, mypy, Selenium\/Chromium-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 live-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 Firefox.\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u043e BPM \u2014 \u043d\u0435 \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u043a\u0440\u044b\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u044c\u044e, \u0430 \u043d\u0430\u0431\u043e\u0440 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0435\u0439:\u041f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c\u041c\u0430\u0440\u0448\u0440\u0443\u0442\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439\/profiles\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044f\u043c\u0438\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435\/profiles\/compare\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439\u041f\u043e\u0448\u0430\u0433\u043e\u0432\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\/profiles\/new, \/profiles\/{id}\/edit\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438All settings\/profiles\/{id}\/settings\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043aJSON-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\/profiles\/{id}\/json\u041f\u0440\u044f\u043c\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u043c\u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u043d\u0435 \u0441\u0440\u0430\u0437\u0443. \u041d\u0430 \u0440\u0430\u043d\u043d\u0438\u0445 \u044d\u0442\u0430\u043f\u0430\u0445 \u0431\u044b\u043b\u043e \u0441\u043e\u0431\u043b\u0430\u0437\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435. \u041d\u043e \u043f\u0440\u0438 \u0440\u043e\u0441\u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0448\u0430\u043d\u0438\u043d\u0443: \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u2014 \u0437\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u2014 \u0437\u0430 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e, \u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0442\u0435\u0440\u044f\u0435\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0433\u0434\u0435 \u043e\u043d \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f.\u0412 \u0432\u0435\u0440\u0441\u0438\u0438 0.8.8 \u044f \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0432\u0451\u043b \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430\u043c. \u042d\u0442\u043e \u0434\u0430\u043b\u043e \u043f\u0440\u043e\u0441\u0442\u0443\u044e, \u043d\u043e \u0432\u0430\u0436\u043d\u0443\u044e \u0432\u0435\u0449\u044c: \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043b\u0435\u0432\u0430 \u0434\u0435\u0440\u0436\u0430\u0442\u044c All settings, \u0441\u043f\u0440\u0430\u0432\u0430 JSON-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440, \u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u2014 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0441 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u044b\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u043c.\u0422\u043e\u0447\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0444\u0430\u0431\u0440\u0438\u043a\u0443 create_app(). \u0412 \u043d\u0435\u0439 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f middleware, \u0441\u0442\u0430\u0442\u0438\u043a\u0430, API-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b, HTML-\u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0438 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438.\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:def create_app() -&gt; FastAPI:    app = FastAPI(        title=settings.APP_NAME,        version=settings.APP_VERSION,    )    app.add_middleware(SecurityHeadersMiddleware)    if settings.ENABLE_CORS:        app.add_middleware(            CORSMiddleware,            allow_origins=settings.CORS_ALLOW_ORIGINS,            allow_credentials=True,            allow_methods=[&#171;*&#187;],            allow_headers=[&#171;*&#187;],        )    app.mount(        &#171;\/static&#187;,        StaticFiles(directory=str(settings.STATIC_DIR)),        name=&#187;static&#187;,    )    app.include_router(web_profiles.router)    app.include_router(health.router)    app.include_router(profiles.router)    app.include_router(export.router)    app.include_router(validation.router)    @app.get(&#171;\/i18n\/{locale}.json&#187;, include_in_schema=False)    async def locale_catalog(locale: str) -&gt; Response:        if locale not in settings.SUPPORTED_LOCALES:            raise HTTPException(status_code=404, detail=&#187;Locale not supported&#187;)        locale_path = _resolve_path(settings.I18N_DIR) \/ f&#187;{locale}.json&#187;        if not locale_path.is_file():            raise HTTPException(status_code=404, detail=&#187;Locale file not found&#187;)        return Response(            content=locale_path.read_text(encoding=&#187;utf-8&#8243;),            media_type=&#187;application\/json&#187;,        )    return app\u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432.\u041f\u0435\u0440\u0432\u044b\u0439 \u2014 HTML-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438 API \u0436\u0438\u0432\u0443\u0442 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. BPM \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430 \u0434\u043b\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043d\u044f\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u0432 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0441\u0440\u0435\u0434\u0435 \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.\u0412\u0442\u043e\u0440\u043e\u0439 \u2014 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0447\u0435\u0440\u0435\u0437 \/i18n\/{locale}.json, \u0430 \u043d\u0435 \u0432\u0448\u0438\u0442\u044b \u0445\u0430\u043e\u0442\u0438\u0447\u043d\u043e \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0438\u043b\u0438 JavaScript.\u0422\u0440\u0435\u0442\u0438\u0439 \u2014 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u0430 \u00ab\u043d\u0430 \u043f\u043e\u0442\u043e\u043c\u00bb. \u0415\u0441\u0442\u044c middleware, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0443 Content Security Policy. \u0414\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u0442\u0440\u0430\u043d\u043d\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u044c \u0430\u0442\u0430\u043a\u0438.\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043a\u0430\u043a \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c BPM \u2014 \u043d\u0435 \u0444\u0430\u0439\u043b \u0438 \u043d\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430, \u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u044c.\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u2014 \u044d\u0442\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Firefox Enterprise Policies \u0441 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u0441\u0445\u0435\u043c\u044b, \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u0438\u0442\u0438\u043a, \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0438 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c.\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0430\u044f ORM-\u043c\u043e\u0434\u0435\u043b\u044c:class Profile(Base):    __tablename__ = &#171;profiles&#187;    id: Mapped[int] = mapped_column(        Integer,        primary_key=True,        autoincrement=True,    )    name: Mapped[str] = mapped_column(        String(255),        nullable=False,        index=True,        unique=True,    )    description: Mapped[str | None] = mapped_column(Text, nullable=True)    schema_version: Mapped[str] = mapped_column(        String(50),        nullable=False,        index=True,        default=DEFAULT_SCHEMA_CHANNEL,    )    flags: Mapped[dict[str, Any]] = mapped_column(        JSON,        nullable=False,        default=dict,    )    compliance: Mapped[dict[str, Any] | None] = mapped_column(        JSON,        nullable=True,    )    revision: Mapped[int] = mapped_column(        Integer,        nullable=False,        default=1,        server_default=&#187;1&#8243;,    )    created_at: Mapped[datetime] = mapped_column(        DateTime(timezone=True),        server_default=func.now(),        nullable=False,        index=True,    )    updated_at: Mapped[datetime] = mapped_column(        DateTime(timezone=True),        server_default=func.now(),        onupdate=func.now(),        nullable=False,        index=True,    )    deleted_at: Mapped[datetime | None] = mapped_column(        DateTime(timezone=True),        nullable=True,        index=True,    )    @property    def is_deleted(self) -&gt; bool:        return self.deleted_at is not None\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043b\u0435 flags. \u041d\u0430 \u0433\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0432\u0438\u0434\u0430:{  &#171;policies&#187;: {    &#171;DisableTelemetry&#187;: true,    &#171;Preferences&#187;: {      &#171;browser.tabs.warnOnClose&#187;: {        &#171;Value&#187;: true,        &#171;Status&#187;: &#171;locked&#187;      }    }  }}\u041d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043d\u0435 \u0432\u0435\u0441\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442, \u0430 \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 policies.\u0422\u043e \u0435\u0441\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 Firefox:{  &#171;policies&#187;: {    &#171;&#8230;&#187;: &#171;&#8230;&#187;  }}\u0410 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u043c\u043e\u0434\u0435\u043b\u044c BPM:{  &#171;&#8230;&#187;: &#171;&#8230;&#187;}\u041f\u043e\u0447\u0435\u043c\u0443 \u0442\u0430\u043a?\u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c, \u0430 \u0441 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0443, \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435, All settings \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0443 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u043b\u0438\u0448\u043d\u0438\u0439 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440. \u0418\u043c \u043d\u0443\u0436\u043d\u0430 \u043a\u0430\u043d\u043e\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u0430\u0440\u0442\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044f. \u0410 \u0432\u043e\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0438 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u043e\u0431\u044f\u0437\u0430\u043d \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Firefox \u2014 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 policies.json \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430.Pydantic-\u0441\u0445\u0435\u043c\u044b: \u0433\u0440\u0430\u043d\u0438\u0446\u0430 APIPydantic-\u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044f\u044e\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e ORM-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 API.\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e:class ProfileBase(BaseModel):    name: str = Field(&#8230;, max_length=255)    description: str | None = None    schema_version: str = Field(default=DEFAULT_SCHEMA_CHANNEL, max_length=50)    flags: dict[str, Any] = Field(default_factory=dict)    compliance: dict[str, Any] | None = Noneclass ProfileCreate(ProfileBase):    passclass ProfileUpdate(BaseModel):    description: str | None = None    schema_version: str | None = Field(default=None, max_length=50)    flags: dict[str, Any] | None = None    compliance: dict[str, Any] | None = None    expected_revision: int | None = Field(default=None, ge=1)class ProfileRead(ProfileBase):    id: int    revision: int    created_at: datetime    updated_at: datetime    deleted_at: datetime | None = None    is_deleted: bool    validation_state: str = &#171;not_validated&#187;    model_config = ConfigDict(from_attributes=True)\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u0435\u043d expected_revision. \u041e\u043d \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0437\u0430\u0449\u0438\u0442\u044b \u043e\u0442 \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f: \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043e\u0442\u043a\u0440\u044b\u0442 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u0445, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u0435\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0438.\u042d\u0442\u043e \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043d\u043e \u0443\u0436\u0435 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f.\u0421\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439 \u0441\u043b\u043e\u0439: CRUD, \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438\u0412 BPM \u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u043e\u0444\u0438\u043b\u044f\u043c\u0438. \u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0432\u044b\u0431\u043e\u0440\u043a\u0443, \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e, \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u044b, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435, \u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0431\u0435\u0437\u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435.\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442:@dataclass(frozen=True, slots=True)class ProfileQuery:    q: str | None = None    schema_version: str | None = None    validation_state: str | None = None    lifecycle: str = &#171;active&#187;    include_deleted: bool = False    limit: int = 50    offset: int = 0    sort: str = &#171;updated_at&#187;    order: str = &#171;desc&#187;class ProfileService:    @staticmethod    def _validation_state(profile: Profile) -&gt; str:        if not&#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-484775","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/484775","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=484775"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/484775\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=484775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=484775"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=484775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}