diff --git a/editorial/reviews/2019-05-draft.md b/editorial/reviews/2019-05-draft.md
index 2e17d59..f322e89 100644
--- a/editorial/reviews/2019-05-draft.md
+++ b/editorial/reviews/2019-05-draft.md
@@ -22,6 +22,7 @@
| no-cache допускает хранение, но требует проверки перед повторным использованием; no-store — иной запрет | [RFC 7234, 5.2](https://www.rfc-editor.org/rfc/rfc7234#section-5.2) | Директивы объяснены для HTTP-кэшей; они не названы защитой от логов, истории и утечек в произвольных слоях |
| Vary связывает сохранённый вариант с полями запроса, повлиявшими на представление | [RFC 7234, 4.1](https://www.rfc-editor.org/rfc/rfc7234#section-4.1) | Для CDN прямо сохранена оговорка: конкретный cache key нужно сверить с документацией и конфигурацией поставщика |
| ETag и If-None-Match позволяют условную проверку с ответом 304 | [RFC 7234, 4.3](https://www.rfc-editor.org/rfc/rfc7234#section-4.3) и [MDN: HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching) | Не утверждается, что ETag обязан быть криптографическим хешем или что каждый origin всегда даст 304 |
+| Entity-tag в заголовке If-None-Match сохраняет кавычки | [RFC 7232, 2.3](https://www.rfc-editor.org/rfc/rfc7232#section-2.3) | В примерах используется конкретный entity-tag; реальный ETag нужно взять из ответа своего тестового origin |
| add_header — директива nginx, а не готовый контракт приложения | [ngx_http_headers_module](https://nginx.org/en/docs/http/ngx_http_headers_module.html) | Конфигурационный фрагмент отмечен как учебный; наследование заголовков, ошибки и CDN остаются проверкой конкретного проекта |
- Источники RFC 7234 существовали к 2019 году и подходят историческому
@@ -36,7 +37,9 @@
- В первом самостоятельном синтаксическом проходе был найден неверно
экранированный перенос строки в учебной curl-команде. Он устранён до
draft-gate: команды сделаны однострочными, а повторный node --check
- прошёл.
+ прошёл. Дополнительный факт-проход нашёл отсутствие кавычек вокруг entity-tag
+ в двух командах If-None-Match; после сверки с RFC 7232 кавычки
+ возвращены, а source list дополнен первичным источником.
Вердикт: **пройдено**. У каждого тезиса есть ограничение, а код показывает
проверку, не выдавая её за измерение в этом workspace.
@@ -92,3 +95,15 @@ slug прошли объём 8 068 / 8 174 / 8 949 знаков, figure, таб
Выпусковой вердикт: **принят к публикации**. articles.json не
менялся; registry заменяет только редакционные поля по стабильному slug.
+
+## 4. Корректировка после публикации — пройдена
+
+После публикации дополнительный факт-проход заметил, что два учебных примера
+передавали значение If-None-Match без обязательных кавычек
+entity-tag. Ошибка не меняла архитектурный вывод, но делала копируемую команду
+неточной. Примеры исправлены на "catalog-v42" и
+"catalog-ru-v18", а в источники добавлен RFC 7232, раздел 2.3.
+
+Повторно прошли node --check, draft-gate, строгий аудит трёх slug,
+XML-проверка SVG и production build на 374 страницы. Корректировка принята
+отдельным выпускным коммитом поверх существующей истории.
diff --git a/web/scripts/upgrade-2019-05.mjs b/web/scripts/upgrade-2019-05.mjs
index 65ef221..78c8eb1 100644
--- a/web/scripts/upgrade-2019-05.mjs
+++ b/web/scripts/upgrade-2019-05.mjs
@@ -74,6 +74,12 @@ const rfcValidation = {
note: 'условные запросы, ETag, If-None-Match и ответ 304 как повторная проверка сохранённого представления',
};
+const rfcEntityTag = {
+ title: 'RFC 7232, раздел 2.3: ETag',
+ url: 'https://www.rfc-editor.org/rfc/rfc7232#section-2.3',
+ note: 'синтаксис entity-tag и связь валидатора с конкретным представлением ресурса',
+};
+
const rfcVary = {
title: 'RFC 7234, раздел 4.1: Vary',
url: 'https://www.rfc-editor.org/rfc/rfc7234#section-4.1',
@@ -150,7 +156,7 @@ const practiceArticle = createRevision(
'curl -sS -D - -o /dev/null https://example.test/catalog',
'',
'# Затем подставить значение ETag из первого ответа.',
- 'curl -sS -D - -o /dev/null -H "If-None-Match: catalog-v42" https://example.test/catalog',
+ "curl -sS -D - -o /dev/null -H 'If-None-Match: \"catalog-v42\"' https://example.test/catalog",
]),
paragraph('Команда выше не доказывает, что ваш CDN использует те же правила, что и браузер. Она делает границу наблюдаемой: на origin или на тестовом домене можно увидеть, поддерживает ли представление условный запрос. Для CDN нужен второй контролируемый путь с той же конфигурацией кэширования. Сравнивать нужно не только код 200 или 304, но и ключевые заголовки на каждом слое.'),
heading('ETag нужен для повторной проверки, а не как украшение'),
@@ -175,7 +181,7 @@ const practiceArticle = createRevision(
'HTML, asset и API требуют разных контрактов, даже если проходят через один домен.',
]),
],
- [rfcFreshness, rfcCacheControl, rfcValidation, mdnCaching, nginxHeaders],
+ [rfcFreshness, rfcCacheControl, rfcValidation, rfcEntityTag, mdnCaching, nginxHeaders],
);
const mechanismArticle = createRevision(
@@ -315,7 +321,7 @@ const fieldArticle = createRevision(
paragraph('Второй тип сбоя выглядит иначе: варианты различаются правильно, но после изменения перевода один из них долго остаётся старым. Здесь проверяем валидатор. Сохраняем ETag русского варианта, ждём или на тестовом стенде настраиваем короткий срок свежести, затем посылаем If-None-Match для того же языка. Если тело не менялось, допустим 304; если менялось — ожидаем новый 200 и новый ETag. Нельзя проверять русский валидатор английским запросом: это уже другой вариант.'),
codeBlock([
'# Значение взять из ответа русского варианта, не подставлять личные токены.',
- 'curl -sS -D - -o /dev/null -H "Accept-Language: ru" -H "If-None-Match: catalog-ru-v18" https://www.example.test/catalog',
+ "curl -sS -D - -o /dev/null -H \"Accept-Language: ru\" -H 'If-None-Match: \"catalog-ru-v18\"' https://www.example.test/catalog",
]),
paragraph('Если ответ всегда 200, это не повод отключить кэш. Сначала выясняем, меняется ли ETag на каждом запросе из-за времени, случайного идентификатора или неустойчивого порядка данных. Валидатор должен описывать представление, а не шум вокруг него. Если сервер всегда 304 после реального изменения текста, наоборот, валидатор слишком грубый. Оба случая проверяются на маленьком контролируемом изменении, а не на общей очистке всей зоны.'),
heading('Матрица решения по наблюдению'),
@@ -349,7 +355,7 @@ const fieldArticle = createRevision(
'Небольшой повторяемый сценарий с headers и телом быстрее локализует сбой, чем очистка всего кэша.',
]),
],
- [rfcCacheControl, rfcValidation, rfcVary, mdnCaching, mdnVary],
+ [rfcCacheControl, rfcValidation, rfcEntityTag, rfcVary, mdnCaching, mdnVary],
);
export const revisions = [practiceArticle, mechanismArticle, fieldArticle];