From e48c55470ccdac1cf0c5cf8c54ea3574cbd896d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 22 Jun 2026 14:13:30 +0400 Subject: [PATCH] =?UTF-8?q?doc:=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B6=D1=83=D1=80=D0=BD=D0=B0=D0=BB?= =?UTF-8?q?=D0=B0=20=E2=80=94=20v1.0.107,=20=D0=B2=D1=81=D1=91=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- History/event-sourcing-security-fixes.md | 49 +++++++++++------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/History/event-sourcing-security-fixes.md b/History/event-sourcing-security-fixes.md index f920792..f1ef196 100644 --- a/History/event-sourcing-security-fixes.md +++ b/History/event-sourcing-security-fixes.md @@ -2,37 +2,34 @@ **Дата:** 2026-06-22 **Источники:** Gemini Web + Sonnet анализ +**Итог:** все 11 шагов + доп. фиксы выполнены, v1.0.107, сравнение работает. ## Выполненные шаги | Шаг | Версия | Что | Файл | |-----|--------|-----|------| -| 1 | v1.0.92 | SQL-инъекция — валидация UUID в _lucee_query | convert_server.py | -| 2 | v1.0.93 | Race condition MAX(seq) — добавлен FOR UPDATE | apply_events.cfm | -| fix | v1.0.100 | Убран FOR UPDATE (несовместим с aggregate в PG) | apply_events.cfm | -| 3 | v1.0.94 | full_replace guard — проверка что ops не пуст | apply_events.cfm | -| 4 | v1.0.95 | Идемпотентность — проверка supplement уже обработан | apply_events.cfm | -| 5 | v1.0.97 | LLM ключ из env (не hardcoded) | convert_server.py | -| 6 | v1.0.98 | elements_json double-decode — handle str/list/dict | convert_server.py | -| 7 | v1.0.99 | isNumeric валидация price/qty/sum (ADD + UPDATE) | apply_events.cfm | -| 8 | v1.0.101 | Batch SELECT для UPDATE — один запрос вместо N+1 | apply_events.cfm | +| 1 | v1.0.92 | SQL-инъекция — валидация UUID | convert_server.py | +| 2 | — | Race condition — FOR UPDATE (убран v1.0.100) | apply_events.cfm | +| 3 | v1.0.94 | full_replace guard | apply_events.cfm | +| 4 | v1.0.104 | Идемпотентность + reset_contract.cfm | apply_events.cfm | +| 5 | v1.0.97 | LLM ключ из env | convert_server.py | +| 6 | v1.0.98 | elements_json double-decode | convert_server.py | +| 7 | v1.0.99 | isNumeric валидация | apply_events.cfm | +| 8 | v1.0.101 | Batch SELECT UPDATE | apply_events.cfm | +| 9 | v1.0.102 | UNRESOLVED вместо cfthrow | apply_events.cfm | +| 10 | v1.0.103 | Массовый INSERT full_replace | apply_events.cfm | +| 11 | — | UUID тип — отменён (cf_sql_char ломает PG) | apply_events.cfm | -## Выполненные (продолжение) +## Доп. фиксы -| 9 | v1.0.102 | UNRESOLVED вместо cfthrow при UPDATE not found | apply_events.cfm | -| 10 | v1.0.103 | Массовый INSERT вместо построчного в full_replace | apply_events.cfm | -| 11 | v1.0.103 | UUID тип cf_sql_char(36) для last_event_id | apply_events.cfm | +| Версия | Что | +|--------|-----| +| v1.0.104 | reset_contract.cfm | +| v1.0.105 | Проверка ответа reset | +| v1.0.106 | Запятая в ADD VALUES | +| v1.0.107 | cf_sql_varchar (UUID cast) | -## Осталось - -| Шаг | Что | Файл | -|-----|-----|------| -| 9 | name_hash fuzzy fallback при UPDATE target not found | apply_events.cfm | -| 10 | Массовый INSERT вместо построчного | apply_events.cfm | -| 11 | UUID тип для last_event_id | apply_events.cfm | - -## Примечания - -- Шаг 2 (FOR UPDATE) отменён — нужен правильный SEQUENCE вместо MAX+FOR UPDATE -- Все изменения в convert_server.py требуют деплоя на ВМ (scp + systemctl restart) -- Все изменения в apply_events.cfm и index.cfm — git push → Lucee managed service +## Статус +- ✅ v1.0.107 — работает. Summary +N ~N -N ?N. Накопление ОК. +- ⚠️ UPDATE/DELETE без имён в UI (отдельно) +- ⚠️ FOR UPDATE убран (нужен SEQUENCE)