revise July and August 2018 articles
Build and deploy / deploy (push) Successful in 14s

This commit is contained in:
2026-07-31 09:41:53 +03:00
parent a84cb93208
commit 7c53ffe6bc
12 changed files with 1679 additions and 1 deletions
@@ -0,0 +1,66 @@
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 960 540" role="img" aria-labelledby="title desc">
<title id="title">Бюджет времени для одного HTTP-запроса</title>
<desc id="desc">Шкала шести секунд: DNS и соединение ограничены полутора секундами, ожидание начала ответа и передача тела используют оставшийся общий лимит. Отдельно показано, что повтор возможен только после проверки семантики операции.</desc>
<defs>
<linearGradient id="back" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#101c35"/>
<stop offset="1" stop-color="#14284a"/>
</linearGradient>
<filter id="shadow" x="-10%" y="-15%" width="120%" height="140%">
<feDropShadow dx="0" dy="8" stdDeviation="9" flood-color="#071226" flood-opacity=".28"/>
</filter>
</defs>
<rect width="960" height="540" rx="28" fill="url(#back)"/>
<text x="54" y="70" fill="#f7fbff" font-family="Arial, sans-serif" font-size="30" font-weight="700">Один запрос: сначала бюджет, затем cURL</text>
<text x="54" y="104" fill="#b9cce4" font-family="Arial, sans-serif" font-size="18">Пример для интеграции, которая должна закончиться не позже чем за 6 секунд</text>
<rect x="54" y="154" width="852" height="92" rx="16" fill="#0b162b" filter="url(#shadow)"/>
<rect x="74" y="176" width="105" height="48" rx="10" fill="#5f7eea"/>
<rect x="187" y="176" width="108" height="48" rx="10" fill="#37b4a1"/>
<rect x="303" y="176" width="202" height="48" rx="10" fill="#f3a348"/>
<rect x="513" y="176" width="162" height="48" rx="10" fill="#d96b7d"/>
<rect x="683" y="176" width="203" height="48" rx="10" fill="#5d8fc9"/>
<text x="94" y="205" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">DNS</text>
<text x="202" y="205" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">TCP/TLS</text>
<text x="329" y="205" fill="#172038" font-family="Arial, sans-serif" font-size="16" font-weight="700">запрос ушёл</text>
<text x="536" y="205" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">первый байт</text>
<text x="727" y="205" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">тело ответа</text>
<line x1="74" y1="278" x2="886" y2="278" stroke="#8ea9ca" stroke-width="3"/>
<g fill="#dbe9f8" font-family="Arial, sans-serif" font-size="15">
<text x="68" y="307">0 с</text>
<text x="196" y="307">1 с</text>
<text x="330" y="307">2 с</text>
<text x="464" y="307">3 с</text>
<text x="598" y="307">4 с</text>
<text x="732" y="307">5 с</text>
<text x="866" y="307">6 с</text>
</g>
<g stroke="#8ea9ca" stroke-width="2">
<line x1="74" y1="270" x2="74" y2="287"/>
<line x1="209" y1="270" x2="209" y2="287"/>
<line x1="344" y1="270" x2="344" y2="287"/>
<line x1="479" y1="270" x2="479" y2="287"/>
<line x1="614" y1="270" x2="614" y2="287"/>
<line x1="749" y1="270" x2="749" y2="287"/>
<line x1="886" y1="270" x2="886" y2="287"/>
</g>
<rect x="54" y="340" width="258" height="138" rx="16" fill="#1b335a" stroke="#5f7eea"/>
<text x="76" y="373" fill="#fff" font-family="Arial, sans-serif" font-size="19" font-weight="700">Connect: до 1,5 с</text>
<text x="76" y="405" fill="#c9dcf4" font-family="Arial, sans-serif" font-size="16">DNS, TCP и TLS входят</text>
<text x="76" y="429" fill="#c9dcf4" font-family="Arial, sans-serif" font-size="16">в эту фазу. Лимит общего</text>
<text x="76" y="453" fill="#c9dcf4" font-family="Arial, sans-serif" font-size="16">времени всё равно короче.</text>
<rect x="350" y="340" width="258" height="138" rx="16" fill="#45364b" stroke="#d96b7d"/>
<text x="372" y="373" fill="#fff" font-family="Arial, sans-serif" font-size="19" font-weight="700">Total: до 6 с</text>
<text x="372" y="405" fill="#f0d6dc" font-family="Arial, sans-serif" font-size="16">Останавливает всю передачу:</text>
<text x="372" y="429" fill="#f0d6dc" font-family="Arial, sans-serif" font-size="16">не только ожидание ответа,</text>
<text x="372" y="453" fill="#f0d6dc" font-family="Arial, sans-serif" font-size="16">но и соединение с ним.</text>
<rect x="646" y="340" width="260" height="138" rx="16" fill="#30405a" stroke="#f3a348"/>
<text x="668" y="373" fill="#fff" font-family="Arial, sans-serif" font-size="19" font-weight="700">Повтор: не по таймеру</text>
<text x="668" y="405" fill="#f9dfbc" font-family="Arial, sans-serif" font-size="16">Нужны метод, состояние</text>
<text x="668" y="429" fill="#f9dfbc" font-family="Arial, sans-serif" font-size="16">операции и оставшийся</text>
<text x="668" y="453" fill="#f9dfbc" font-family="Arial, sans-serif" font-size="16">бюджет времени.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

@@ -0,0 +1,60 @@
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="590" viewBox="0 0 960 590" role="img" aria-labelledby="title desc">
<title id="title">Разбор зависшего HTTP-запроса по стадиям</title>
<desc id="desc">Дерево диагностики: сначала фиксируется curl error и HTTP-код, затем сравниваются времена DNS, соединения, TLS, первого байта и общего запроса. Для каждой наблюдаемой точки указан следующий шаг без автоматического повтора небезопасной операции.</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#15233d"/>
<stop offset="1" stop-color="#102038"/>
</linearGradient>
<marker id="a" markerWidth="10" markerHeight="10" refX="7" refY="3" orient="auto">
<path d="M0,0 L0,6 L8,3 z" fill="#a7c7e8"/>
</marker>
</defs>
<rect width="960" height="590" rx="28" fill="url(#bg)"/>
<text x="48" y="64" fill="#fff" font-family="Arial, sans-serif" font-size="26" font-weight="700">Зависшая интеграция: не угадывать, на какой стадии ждать</text>
<text x="48" y="98" fill="#c7d9eb" font-family="Arial, sans-serif" font-size="18">Один лог запроса показывает границу следующей проверки</text>
<rect x="346" y="132" width="268" height="66" rx="14" fill="#5f7eea"/>
<text x="382" y="160" fill="#fff" font-family="Arial, sans-serif" font-size="18" font-weight="700">curl_exec завершился</text>
<text x="394" y="184" fill="#eaf0ff" font-family="Arial, sans-serif" font-size="15">error + HTTP-код + времена</text>
<line x1="480" y1="198" x2="208" y2="255" stroke="#a7c7e8" stroke-width="3" marker-end="url(#a)"/>
<line x1="480" y1="198" x2="480" y2="255" stroke="#a7c7e8" stroke-width="3" marker-end="url(#a)"/>
<line x1="480" y1="198" x2="752" y2="255" stroke="#a7c7e8" stroke-width="3" marker-end="url(#a)"/>
<rect x="62" y="270" width="292" height="116" rx="16" fill="#263e64" stroke="#7fa8d5"/>
<text x="87" y="303" fill="#fff" font-family="Arial, sans-serif" font-size="19" font-weight="700">Нет HTTP-кода</text>
<text x="87" y="332" fill="#d7e8f7" font-family="Arial, sans-serif" font-size="16">Смотрим name lookup,</text>
<text x="87" y="355" fill="#d7e8f7" font-family="Arial, sans-serif" font-size="16">connect, appconnect.</text>
<text x="87" y="378" fill="#a9c7ea" font-family="Arial, sans-serif" font-size="15">Граница: сеть или TLS.</text>
<rect x="334" y="270" width="292" height="116" rx="16" fill="#5a3a51" stroke="#df8192"/>
<text x="359" y="303" fill="#fff" font-family="Arial, sans-serif" font-size="19" font-weight="700">Первый байт поздний</text>
<text x="359" y="332" fill="#f2d9df" font-family="Arial, sans-serif" font-size="16">connect завершён,</text>
<text x="359" y="355" fill="#f2d9df" font-family="Arial, sans-serif" font-size="16">starttransfer растёт.</text>
<text x="359" y="378" fill="#f3b4c0" font-family="Arial, sans-serif" font-size="15">Граница: партнёр или очередь.</text>
<rect x="606" y="270" width="292" height="116" rx="16" fill="#5b4b37" stroke="#f1b15f"/>
<text x="631" y="303" fill="#fff" font-family="Arial, sans-serif" font-size="19" font-weight="700">Тело идёт слишком долго</text>
<text x="631" y="332" fill="#fff0d6" font-family="Arial, sans-serif" font-size="16">starttransfer есть,</text>
<text x="631" y="355" fill="#fff0d6" font-family="Arial, sans-serif" font-size="16">total упирается в лимит.</text>
<text x="631" y="378" fill="#ffd99b" font-family="Arial, sans-serif" font-size="15">Граница: размер или скорость.</text>
<line x1="208" y1="386" x2="208" y2="426" stroke="#a7c7e8" stroke-width="3" marker-end="url(#a)"/>
<line x1="480" y1="386" x2="480" y2="426" stroke="#a7c7e8" stroke-width="3" marker-end="url(#a)"/>
<line x1="752" y1="386" x2="752" y2="426" stroke="#a7c7e8" stroke-width="3" marker-end="url(#a)"/>
<rect x="62" y="442" width="292" height="112" rx="14" fill="#18314f"/>
<text x="87" y="476" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">Проверить адрес, DNS и CA</text>
<text x="87" y="524" fill="#c7d9eb" font-family="Arial, sans-serif" font-size="15">Не лечить ростом общего лимита.</text>
<rect x="334" y="442" width="292" height="112" rx="14" fill="#18314f"/>
<text x="359" y="476" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">Передать время и ID</text>
<text x="359" y="497" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">партнёру</text>
<text x="359" y="524" fill="#c7d9eb" font-family="Arial, sans-serif" font-size="15">Повтор только по контракту операции.</text>
<rect x="606" y="442" width="292" height="112" rx="14" fill="#18314f"/>
<text x="631" y="476" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">Проверить объём ответа</text>
<text x="631" y="497" fill="#fff" font-family="Arial, sans-serif" font-size="16" font-weight="700">и низкую скорость</text>
<text x="631" y="524" fill="#c7d9eb" font-family="Arial, sans-serif" font-size="15">Отдельно считать неполный ответ.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

@@ -0,0 +1,38 @@
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="560" viewBox="0 0 960 560" role="img" aria-labelledby="title desc">
<title id="title">Три ограничения ожидания в libcurl</title>
<desc id="desc">Схема сопоставляет connect timeout, общий timeout и пару low speed limit плюс low speed time. Общий лимит охватывает соединение, а low speed отслеживает среднюю скорость передачи ниже заданного порога.</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#14213d"/>
<stop offset="1" stop-color="#1d3557"/>
</linearGradient>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="7" refY="3" orient="auto">
<path d="M0,0 L0,6 L8,3 z" fill="#a8c7e8"/>
</marker>
</defs>
<rect width="960" height="560" rx="28" fill="url(#bg)"/>
<text x="54" y="68" fill="#fff" font-family="Arial, sans-serif" font-size="30" font-weight="700">Три условия остановки у одного cURL-вызова</text>
<text x="54" y="103" fill="#c8daec" font-family="Arial, sans-serif" font-size="18">Они отвечают на разные вопросы и не заменяют друг друга</text>
<rect x="62" y="148" width="836" height="108" rx="18" fill="#0e1b30" stroke="#6b93bd" stroke-width="2"/>
<text x="88" y="184" fill="#7de0cf" font-family="Arial, sans-serif" font-size="20" font-weight="700">CURLOPT_CONNECTTIMEOUT</text>
<text x="88" y="216" fill="#d7e8f7" font-family="Arial, sans-serif" font-size="17">До соединения: DNS → TCP → TLS.</text>
<text x="88" y="239" fill="#d7e8f7" font-family="Arial, sans-serif" font-size="17">После него connect timeout уже не действует.</text>
<rect x="698" y="172" width="168" height="58" rx="12" fill="#1c6b61"/>
<text x="723" y="207" fill="#fff" font-family="Arial, sans-serif" font-size="18" font-weight="700">например, 2 с</text>
<line x1="480" y1="274" x2="480" y2="310" stroke="#a8c7e8" stroke-width="3" marker-end="url(#arrow)"/>
<rect x="62" y="322" width="836" height="108" rx="18" fill="#0e1b30" stroke="#d96b7d" stroke-width="2"/>
<text x="88" y="358" fill="#ffa7b5" font-family="Arial, sans-serif" font-size="20" font-weight="700">CURLOPT_TIMEOUT</text>
<text x="88" y="390" fill="#d7e8f7" font-family="Arial, sans-serif" font-size="17">Весь перенос от старта до конца.</text>
<text x="88" y="413" fill="#d7e8f7" font-family="Arial, sans-serif" font-size="17">Connect timeout находится внутри этого потолка.</text>
<rect x="698" y="346" width="168" height="58" rx="12" fill="#963f53"/>
<text x="723" y="381" fill="#fff" font-family="Arial, sans-serif" font-size="18" font-weight="700">например, 8 с</text>
<rect x="62" y="462" width="400" height="58" rx="14" fill="#2b4e70" stroke="#f3a348"/>
<text x="84" y="498" fill="#fff" font-family="Arial, sans-serif" font-size="18" font-weight="700">LOW_SPEED_LIMIT + LOW_SPEED_TIME</text>
<rect x="490" y="462" width="408" height="58" rx="14" fill="#2b4e70" stroke="#f3a348"/>
<text x="514" y="487" fill="#ffdfb0" font-family="Arial, sans-serif" font-size="16">Пример: ниже 100 Б/с 15 секунд</text>
<text x="514" y="509" fill="#d7e8f7" font-family="Arial, sans-serif" font-size="15">Это граница низкой скорости, не отдельный API read timeout.</text>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

@@ -0,0 +1,53 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 680" role="img" aria-labelledby="title desc">
<title id="title">Цепочка TLS-доверия и SNI</title>
<desc id="desc">PHP cURL отправляет URL hostname в SNI серверу. Сервер выдаёт конечный и промежуточный сертификаты. Клиент соединяет цепочку с корнем в CA bundle и отдельно проверяет имя хоста.</desc>
<defs>
<linearGradient id="background" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a203d"/>
<stop offset="1" stop-color="#1c4560"/>
</linearGradient>
<marker id="arr" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto">
<path d="M1 1 L11 6 L1 11 Z" fill="#8ae6d8"/>
</marker>
</defs>
<rect width="1200" height="680" rx="28" fill="url(#background)"/>
<text x="65" y="78" fill="#f7fbff" font-family="Arial, sans-serif" font-size="34" font-weight="700">TLS: кто выбирает сертификат и кто ему доверяет</text>
<text x="65" y="116" fill="#bed8e6" font-family="Arial, sans-serif" font-size="21">SNI выбирает виртуальный хост. CA bundle и hostname check принимают решение у клиента.</text>
<g font-family="Arial, sans-serif">
<rect x="65" y="202" width="270" height="180" rx="20" fill="#ecf4ff"/>
<text x="100" y="251" fill="#183145" font-size="28" font-weight="700">PHP cURL</text>
<text x="100" y="292" fill="#355468" font-size="20">URL:</text>
<text x="100" y="322" fill="#355468" font-size="20">api.partner.example</text>
<text x="100" y="349" fill="#355468" font-size="18">CA bundle +</text>
<text x="100" y="374" fill="#355468" font-size="18">hostname check</text>
<rect x="465" y="190" width="270" height="205" rx="20" fill="#e6fff9"/>
<text x="500" y="243" fill="#183145" font-size="28" font-weight="700">TLS-сервер</text>
<text x="500" y="286" fill="#355468" font-size="20">virtual host по SNI</text>
<text x="500" y="323" fill="#355468" font-size="20">leaf certificate</text>
<text x="500" y="353" fill="#355468" font-size="20">intermediate certificate</text>
<rect x="865" y="202" width="270" height="180" rx="20" fill="#fff7de"/>
<text x="900" y="251" fill="#183145" font-size="28" font-weight="700">CA bundle</text>
<text x="900" y="292" fill="#355468" font-size="20">доверенные root CA</text>
<text x="900" y="325" fill="#355468" font-size="20">не leaf сайта</text>
<text x="900" y="355" fill="#355468" font-size="18">локальный trust store</text>
<rect x="280" y="492" width="640" height="115" rx="18" fill="#182a43" stroke="#8ae6d8" stroke-width="3"/>
<text x="325" y="538" fill="#f8fcff" font-size="25" font-weight="700">Решение клиента</text>
<text x="325" y="575" fill="#cfe5ee" font-size="21">1. Цепочка leaf → intermediate → trusted root строится</text>
<text x="325" y="603" fill="#cfe5ee" font-size="21">2. Имя в сертификате подходит hostname из URL</text>
</g>
<g fill="none" stroke="#8ae6d8" stroke-width="5" marker-end="url(#arr)">
<path d="M345 252 C382 252 414 252 448 252"/>
<path d="M745 286 C785 286 815 286 848 286"/>
<path d="M997 395 C997 450 860 465 770 487"/>
<path d="M600 405 V478"/>
<path d="M200 393 C220 440 350 455 430 485"/>
</g>
<g font-family="Arial, sans-serif" font-size="18" fill="#8ae6d8">
<text x="365" y="226">ClientHello: SNI</text>
<text x="790" y="260">root CA</text>
<text x="640" y="447">серверная цепочка</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@@ -0,0 +1,82 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 650" role="img" aria-labelledby="title desc">
<title id="title">Диагностика TLS-ошибки в PHP cURL</title>
<desc id="desc">Шесть шагов: сохранить код ошибки, определить версии клиента, проверить путь CA bundle, получить сертификаты с SNI, проверить цепочку и повторить PHP-запрос с включённой проверкой.</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#10243b"/>
<stop offset="1" stop-color="#183f59"/>
</linearGradient>
<filter id="shadow" x="-10%" y="-20%" width="120%" height="140%">
<feDropShadow dx="0" dy="8" stdDeviation="8" flood-color="#07131f" flood-opacity=".35"/>
</filter>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto">
<path d="M1 1 L11 6 L1 11 Z" fill="#78dce8"/>
</marker>
</defs>
<rect width="1200" height="650" rx="28" fill="url(#bg)"/>
<text x="70" y="85" fill="#f5fbff" font-family="Arial, sans-serif" font-size="34" font-weight="700">TLS-ошибка в PHP: не меняем false, пока не знаем причину</text>
<text x="70" y="125" fill="#b8d3e6" font-family="Arial, sans-serif" font-size="22">Каждый шаг оставляет проверяемый артефакт для следующей ветки.</text>
<g font-family="Arial, sans-serif">
<g filter="url(#shadow)">
<rect x="70" y="185" width="285" height="145" rx="18" fill="#fff8df"/>
<circle cx="112" cy="228" r="22" fill="#e59b36"/>
<text x="104" y="236" fill="#fff" font-size="22" font-weight="700">1</text>
<text x="150" y="224" fill="#183145" font-size="21" font-weight="700">Зафиксировать</text>
<text x="150" y="250" fill="#183145" font-size="21" font-weight="700">отказ</text>
<text x="105" y="282" fill="#355468" font-size="18">curl_errno + curl_error</text>
<text x="105" y="308" fill="#355468" font-size="18">до curl_close</text>
</g>
<g filter="url(#shadow)">
<rect x="457" y="185" width="285" height="145" rx="18" fill="#e7f7fa"/>
<circle cx="499" cy="228" r="22" fill="#3da8ba"/>
<text x="491" y="236" fill="#fff" font-size="22" font-weight="700">2</text>
<text x="537" y="224" fill="#183145" font-size="21" font-weight="700">Определить</text>
<text x="537" y="250" fill="#183145" font-size="21" font-weight="700">клиент</text>
<text x="492" y="282" fill="#355468" font-size="18">curl_version(): libcurl</text>
<text x="492" y="308" fill="#355468" font-size="18">и TLS-библиотека PHP</text>
</g>
<g filter="url(#shadow)">
<rect x="845" y="185" width="285" height="145" rx="18" fill="#eaf4e7"/>
<circle cx="887" cy="228" r="22" fill="#5da878"/>
<text x="879" y="236" fill="#fff" font-size="22" font-weight="700">3</text>
<text x="925" y="224" fill="#183145" font-size="21" font-weight="700">Проверить</text>
<text x="925" y="250" fill="#183145" font-size="21" font-weight="700">CA file</text>
<text x="880" y="282" fill="#355468" font-size="18">путь, чтение, версию</text>
<text x="880" y="308" fill="#355468" font-size="18">bundle</text>
</g>
<g filter="url(#shadow)">
<rect x="70" y="425" width="285" height="145" rx="18" fill="#e9ebff"/>
<circle cx="112" cy="468" r="22" fill="#6d7bd6"/>
<text x="104" y="476" fill="#fff" font-size="22" font-weight="700">4</text>
<text x="150" y="464" fill="#183145" font-size="21" font-weight="700">Снять</text>
<text x="150" y="490" fill="#183145" font-size="21" font-weight="700">цепочку</text>
<text x="105" y="522" fill="#355468" font-size="18">s_client -servername</text>
<text x="105" y="548" fill="#355468" font-size="18">-showcerts</text>
</g>
<g filter="url(#shadow)">
<rect x="457" y="425" width="285" height="145" rx="18" fill="#f8eaf4"/>
<circle cx="499" cy="468" r="22" fill="#b96799"/>
<text x="491" y="476" fill="#fff" font-size="22" font-weight="700">5</text>
<text x="537" y="464" fill="#183145" font-size="21" font-weight="700">Построить</text>
<text x="537" y="490" fill="#183145" font-size="21" font-weight="700">цепочку</text>
<text x="492" y="522" fill="#355468" font-size="18">verify: leaf + intermediate</text>
<text x="492" y="548" fill="#355468" font-size="18">против CA bundle</text>
</g>
<g filter="url(#shadow)">
<rect x="845" y="425" width="285" height="145" rx="18" fill="#f4eee3"/>
<circle cx="887" cy="468" r="22" fill="#c18442"/>
<text x="879" y="476" fill="#fff" font-size="22" font-weight="700">6</text>
<text x="925" y="464" fill="#183145" font-size="21" font-weight="700">Повторить</text>
<text x="925" y="490" fill="#183145" font-size="21" font-weight="700">PHP</text>
<text x="880" y="522" fill="#355468" font-size="18">VERIFYPEER=true</text>
<text x="880" y="548" fill="#355468" font-size="18">VERIFYHOST=2</text>
</g>
</g>
<g stroke="#78dce8" stroke-width="5" fill="none" marker-end="url(#arrow)">
<path d="M365 258 H438"/>
<path d="M752 258 H826"/>
<path d="M988 342 V400 H212 V405"/>
<path d="M365 498 H438"/>
<path d="M752 498 H826"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1,67 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 640" role="img" aria-labelledby="title desc">
<title id="title">Контролируемое обновление CA bundle для PHP cURL</title>
<desc id="desc">План из пяти этапов: определить активный CA store, подготовить версионный bundle, проверить цепочку на стенде, переключить одну настройку и подтвердить PHP-запрос с включённой проверкой.</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#28334a"/>
<stop offset="1" stop-color="#255768"/>
</linearGradient>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto">
<path d="M1 1 L11 6 L1 11 Z" fill="#f4ca76"/>
</marker>
</defs>
<rect width="1200" height="640" rx="28" fill="url(#bg)"/>
<text x="65" y="78" fill="#fffdf8" font-family="Arial, sans-serif" font-size="34" font-weight="700">CA bundle меняем как релизный артефакт</text>
<text x="65" y="116" fill="#d8e7ec" font-family="Arial, sans-serif" font-size="21">Новый файл сначала доказывает нужную цепочку, затем становится конфигурацией PHP.</text>
<g font-family="Arial, sans-serif">
<g>
<rect x="65" y="218" width="195" height="225" rx="18" fill="#f8f3e7"/>
<circle cx="104" cy="260" r="21" fill="#d68b3b"/>
<text x="97" y="268" fill="#fff" font-size="21" font-weight="700">1</text>
<text x="93" y="310" fill="#254052" font-size="21" font-weight="700">Найти</text>
<text x="93" y="337" fill="#254052" font-size="21" font-weight="700">источник</text>
<text x="93" y="375" fill="#466477" font-size="18">CAINFO, php.ini</text>
<text x="93" y="403" fill="#466477" font-size="18">или system store</text>
</g>
<g>
<rect x="285" y="218" width="195" height="225" rx="18" fill="#e8f5fb"/>
<circle cx="324" cy="260" r="21" fill="#4694b1"/>
<text x="317" y="268" fill="#fff" font-size="21" font-weight="700">2</text>
<text x="313" y="316" fill="#254052" font-size="23" font-weight="700">Кандидат</text>
<text x="313" y="352" fill="#466477" font-size="18">версионный PEM</text>
<text x="313" y="380" fill="#466477" font-size="18">из trusted source</text>
</g>
<g>
<rect x="505" y="218" width="195" height="225" rx="18" fill="#e9f6e9"/>
<circle cx="544" cy="260" r="21" fill="#5d9b68"/>
<text x="537" y="268" fill="#fff" font-size="21" font-weight="700">3</text>
<text x="533" y="316" fill="#254052" font-size="23" font-weight="700">Проверка</text>
<text x="533" y="352" fill="#466477" font-size="18">openssl verify</text>
<text x="533" y="380" fill="#466477" font-size="18">leaf + intermediate</text>
</g>
<g>
<rect x="725" y="218" width="195" height="225" rx="18" fill="#f4eafa"/>
<circle cx="764" cy="260" r="21" fill="#9b6cba"/>
<text x="757" y="268" fill="#fff" font-size="21" font-weight="700">4</text>
<text x="753" y="316" fill="#254052" font-size="20" font-weight="700">Переключить</text>
<text x="753" y="352" fill="#466477" font-size="18">одну настройку</text>
<text x="753" y="380" fill="#466477" font-size="18">и перезапустить</text>
</g>
<g>
<rect x="945" y="218" width="190" height="225" rx="18" fill="#fff2e7"/>
<circle cx="984" cy="260" r="21" fill="#cf7750"/>
<text x="977" y="268" fill="#fff" font-size="21" font-weight="700">5</text>
<text x="973" y="316" fill="#254052" font-size="23" font-weight="700">Подтвердить</text>
<text x="973" y="352" fill="#466477" font-size="18">PHP cURL при</text>
<text x="973" y="380" fill="#466477" font-size="18">VERIFYPEER=true</text>
</g>
</g>
<g fill="none" stroke="#f4ca76" stroke-width="5" marker-end="url(#arrow)">
<path d="M270 330 H274"/>
<path d="M490 330 H494"/>
<path d="M710 330 H714"/>
<path d="M930 330 H934"/>
</g>
<rect x="155" y="510" width="890" height="64" rx="14" fill="#182d43" stroke="#f4ca76" stroke-width="2"/>
<text x="190" y="551" fill="#f8fcff" font-family="Arial, sans-serif" font-size="21">Фиксируем: версию bundle, путь, проверяемый hostname и способ отката.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB