Skip to content

fix: three core defects found in the pre-2026.3.40 audit - #1098

Merged
jorikfon merged 3 commits into
developfrom
worktree-post-3.40-cleanup
Aug 5, 2026
Merged

fix: three core defects found in the pre-2026.3.40 audit#1098
jorikfon merged 3 commits into
developfrom
worktree-post-3.40-cleanup

Conversation

@jorikfon

@jorikfon jorikfon commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Три независимых дефекта ядра, подтверждённых на боевом трафике и в Sentry при аудите перед релизом 2026.3.40. Каждый — отдельный коммит; при желании легко разнести по разным PR.

1. OutWorkTimes GetList — поиск и сортировка ломались (MIKOPBX-MBB)

У модели нет колонки name; поле name в ответе — алиас description. Убрано из searchableFields/allowedOrderFields, поправлен apidoc.
Проверено на живом стенде: GET /pbxcore/api/v3/off-work-times?search=x — было Column 'name' doesn't belong to any of the selected models, стало 200; order_by=description сортирует.

Замечание: order_by=name теперь молча деградирует к priority ASC (сортировка на этой странице в UI отключена, вызывающих в коде нет). Если нужно принимать name, есть прецедент $fieldMap в Lib/TimeSettings/DataStructure.php.

2. JS-воркер статуса установки модулей (MIKOPBX-PCV, MIKOPBX-KX3)

InstallPipeline шлёт события без stageDetails.data — три колбэка падали с Cannot read properties of undefined, прогресс-бар замирал. Добавлены || {} в стиле файла (не optional chaining — из-за пресета airbnb). Транспилированный артефакт пересобран.

3. handleFileStreaming получал true (MIKOPBX-PEX)

Легаси-модули используют плоский формат 2017 года (fpassthru => true, ключи на data) → TypeError. Теперь плоский формат проходит дальше по обычному пути, где его забирает ModulesControllerBase::handleFilePassThrough() — он владеет легаси-заголовками (Content-Disposition с basename, fallback text/plain), которых handleFileStreaming() не воспроизводит. Все core-действия используют вложенный массив и не затронуты.

Проверки

  • phpstan по изменённым PHP-файлам: 65 ошибок до и после (весь объём — шум Phalcon property.notFound), регрессии нет.
  • Пункт 1 проверен end-to-end на стенде 172.16.32.85.
  • Пункты 2 и 3 проверены по коду; code-review-агент прошёлся по всем прочим GetList-действиям (других алиасов-фантомов нет) и по всем производителям fpassthru.

…olumn

OutWorkTimes has no `name` column — the `name` field in the API response is an
alias for `description` (DataStructure::createForList). Passing it in
searchableFields/allowedOrderFields made the ORM raise "Column 'name' doesn't
belong to any of the selected models", so any search or ordering request on the
time-conditions page failed instead of returning data.

Verified on a live stand: GET /pbxcore/api/v3/off-work-times?search=x went from
an ORM error payload to 200, and order_by=description now sorts.

Sentry: MIKOPBX-MBB
…tails.data

InstallPipeline pushes stage events that carry only `result`/`messages` (e.g. a
failure raised before the download starts), so the download/upload/installation
callbacks crashed with "Cannot read properties of undefined" while reading
stageDetails.data.*. The progress bar froze even though the installation itself
kept running.

Uses the `|| {}` idiom already present in this file rather than optional
chaining, to stay within the airbnb babel preset. Transpiled artifact rebuilt.

Sentry: MIKOPBX-PCV, MIKOPBX-KX3
…reaming

Legacy modules return the 2017 layout where `fpassthru` is the boolean flag and
filename/content_type/need_delete sit on `data` itself, so
handleSpecialResponse() passed `true` into handleFileStreaming(array $fileData)
and raised a TypeError.

The flat shape now falls through to the normal payload path, where
ModulesControllerBase::handleFilePassThrough() picks it up as it has since 2017
— it owns the legacy headers (Content-Disposition with basename, text/plain
fallback), which handleFileStreaming() does not reproduce. Core actions all use
the nested array shape and are unaffected.

Sentry: MIKOPBX-PEX
@jorikfon

jorikfon commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

Про тесты: отдельных юнит-тестов не добавлено.

  • Фикс 1 проверен end-to-end на стенде (422 с ошибкой ORM → 200); покрытие уровня GetListAction требует поднятой БД, поэтому уместнее в API-тестах, а не в tests/Unit.
  • Фикс 3 живёт в private-методе BaseController::handleSpecialResponse(), вызов которого невозможно изолировать без мока Response/DI, а мок-сервисы в проекте запрещены. Вместо теста проверен весь путь по коду: setPayloadSuccess() кладёт массив в setJsonContent() без обёртки (Http/Response.php:181-188), meta добавляется только в send(), поэтому callActionForModule декодирует исходный $response и handleResponse() видит data.fpassthru на верхнем уровне — плоский легаси-формат доходит до handleFilePassThrough().
  • Фикс 2 — фронтенд, JS-юнитов в проекте нет.

Также: стенд 172.16.32.85 hot-patched версией GetListAction.php из этой ветки.

@jorikfon
jorikfon marked this pull request as ready for review August 5, 2026 08:28
@jorikfon
jorikfon merged commit bb03a51 into develop Aug 5, 2026
1 check passed
@jorikfon
jorikfon deleted the worktree-post-3.40-cleanup branch August 5, 2026 08:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant