[Fable 5][P3] JobSettingsPanel: правки JSON extra_config молча теряются, если textarea свёрнута при сохранении #1239

Closed
opened 2026-06-13 04:49:48 +00:00 by bot-backend · 0 comments
Collaborator

Из армейского ревью Claude Fable 5 (2026-06-11)

Confirmed by 2/2 адверсариальных верификатора, severity P3 (data-integrity), confidence 0.65.

Файл

frontend/src/components/admin/JobSettingsPanel.tsx:149

Evidence (цитата кода)

let extra_config: Record<string, unknown> | undefined;
if (expanded[job_type]) {
  try {
    const parsed = JSON.parse(draft.extra_config_text) as unknown;

Why bug

extra_config парсится и попадает в PUT только когда строка раскрыта (expanded). Сценарий: админ раскрыл JSON, отредактировал, свернул кнопкой «▼ скрыть», нажал «Сохранить» — запрос уходит без extra_config, сервер сохраняет старый, onSuccess вызывает toRowDraft(data) и перезаписывает локальный текст серверным значением. Правки JSON исчезают, при этом показывается toast «сохранено» — ложное подтверждение.

Suggested fix

Слать extra_config когда draft.extra_config_text отличается от JSON.stringify(server extra_config), независимо от expanded; либо блокировать сворачивание при невалидном/несохранённом JSON.

Verify notes

  • [real/P3] Трасса подтверждена: кнопка «▼ скрыть» меняет только expanded, правки остаются в drafts; handleSave при свёрнутой строке пропускает парсинг (line 149), extra_config не попадает в PUT (lines 179-181). Бэкенд (services/job_settings.py:223 if extra_config is not None) поле не трогает и возвращает старый JSON; onSuccess перезаписывает draft через toRowDraft(data) и показывает toast «сохранено». Правки теряются молча с ложным подтверждением. P3: admin-only UI, теряется лишь несохранённый текст.
  • [real/P3] Защита не найдена: toggle (строка 403) лишь флипает expanded — draft.extra_config_text не сбрасывается и не блокирует save; кнопка «Сохранить» видна всегда. PUT без extra_config + PATCH-семантика бэкенда (services/job_settings.py:223 if extra_config is not None) сохраняет старое значение, а onSuccess перезаписывает draft через toRowDraft(data) и показывает toast «сохранено». Правки теряются и на сервере, и локально. Admin-панель, восстановимо → P3.

Provenance

  • Finders: fe-rest
  • Confidence: 0.65
  • Originally batched at: main@d796027
## Из армейского ревью Claude Fable 5 (2026-06-11) Confirmed by 2/2 адверсариальных верификатора, severity **P3** (data-integrity), confidence 0.65. ## Файл [`frontend/src/components/admin/JobSettingsPanel.tsx:149`](frontend/src/components/admin/JobSettingsPanel.tsx:149) ## Evidence (цитата кода) ``` let extra_config: Record<string, unknown> | undefined; if (expanded[job_type]) { try { const parsed = JSON.parse(draft.extra_config_text) as unknown; ``` ## Why bug extra_config парсится и попадает в PUT только когда строка раскрыта (expanded). Сценарий: админ раскрыл JSON, отредактировал, свернул кнопкой «▼ скрыть», нажал «Сохранить» — запрос уходит без extra_config, сервер сохраняет старый, onSuccess вызывает toRowDraft(data) и перезаписывает локальный текст серверным значением. Правки JSON исчезают, при этом показывается toast «сохранено» — ложное подтверждение. ## Suggested fix Слать extra_config когда draft.extra_config_text отличается от JSON.stringify(server extra_config), независимо от expanded; либо блокировать сворачивание при невалидном/несохранённом JSON. ## Verify notes - [real/P3] Трасса подтверждена: кнопка «▼ скрыть» меняет только expanded, правки остаются в drafts; handleSave при свёрнутой строке пропускает парсинг (line 149), extra_config не попадает в PUT (lines 179-181). Бэкенд (services/job_settings.py:223 `if extra_config is not None`) поле не трогает и возвращает старый JSON; onSuccess перезаписывает draft через toRowDraft(data) и показывает toast «сохранено». Правки теряются молча с ложным подтверждением. P3: admin-only UI, теряется лишь несохранённый текст. - [real/P3] Защита не найдена: toggle (строка 403) лишь флипает expanded — draft.extra_config_text не сбрасывается и не блокирует save; кнопка «Сохранить» видна всегда. PUT без extra_config + PATCH-семантика бэкенда (services/job_settings.py:223 `if extra_config is not None`) сохраняет старое значение, а onSuccess перезаписывает draft через toRowDraft(data) и показывает toast «сохранено». Правки теряются и на сервере, и локально. Admin-панель, восстановимо → P3. ## Provenance - Finders: `fe-rest` - Confidence: 0.65 - Originally batched at: main@d796027
bot-backend added the
Fable 5 ревью
label 2026-06-13 04:49:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1239
No description provided.