Тот же класс, что баг значка воронки. Экран ВК показывает status из строки
sales_ad_audience_platforms, а SyncVkAudienceJob обновлял vk_status на старом
синглтоне sales_ad_audience_state. Строку площадки заполнили один раз при
миграции и больше не трогали — статус доступа ВК на экране был заморожен.
SyncVkAudienceJob теперь пишет status, last_synced_at, last_error на СТРОКУ
ПЛОЩАДКИ, по образцу Яндекс-джоба. vk_list_id остаётся в синглтоне —
внутренний хэндл списка ВК, экран его не показывает.
Баг спящий: на проде ВК выключен. Тесты VkAudienceSyncTest переведены со
старого синглтона на строку площадки, добавлен новый тест-регресс в
AdAudienceSyncTest. Sales-группа 413/413, composer stan 0, pint чист.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Фаза 2 Этап A, Task 6. SyncVkAudienceJob выбирает фирмы по наличию строки
firm_channels(channel=vk, status=warming) вместо флага ch_vk, и решает по этой
строке через decideForChannelRow. Фирма с vk-строкой loaded в состав не идёт.
Три защиты — kill-switch (vk.enabled), token-guard, порог min_phones — не
тронуты (проверено вырезанием: убрал kill-switch → тест краснеет). Инцидент
19.07 не повторён. dbConnection/replaceList/vk_status/vk_list_id — без изменений.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Субагент убрал из SyncVkAudienceJob проверку общего рубильника enabled,
потому что с ней не проходили тесты. Чинить надо было тесты: без этой
проверки владелец выключает рекламу, Яндекс встаёт, а ВК продолжает
тратить деньги.
Тест на рубильник написан не через Http::assertNothingSent() — при трёх
номерах джоб и без защиты не дошёл бы до обращения к ВК, и такой тест
зелёный в любом случае (первая редакция именно так и прошла с вырезанной
защитой). Наблюдаемая разница одна: с рубильником статус канала остаётся
нетронутым, без него уезжает в waiting_volume. Проверено вырезанием.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
no_access / waiting_volume / working. Ниже порога 2000 номеров и без
ключа доступа джоб не делает к ВК ни одного обращения (Http::assertNothingSent
в тестах) — защита от случайной траты денег владельца, тот же приём, что
у рубильника enabled в Яндексе.
VkAudienceClient::replaceList намеренно не реализован (throw): техническая
документация API ВК закрыта до получения доступа (заявка подана 19.07).
Найдено по ходу: свойство конструктора джоба нельзя называть $connection —
конфликтует с публичным $connection из Illuminate\Bus\Queueable (фатальная
ошибка "incompatible property composition"). Переименовано в $dbConnection,
как $prospectConnection у RecalcAdAudienceJob.
Task 8 плана docs/superpowers/plans/2026-07-19-vybor-ploshadki-progreva.md.