feat(api): управление ИИ-воркерами через внешний API
Внешние системы не могли разбудить воркер, переочередить упавшие
задания или отправить запись на повторную ИИ-проверку: все эти роуты
существовали только во внутреннем API под requireAdmin.
Добавлено на apiV1 (все под apiWrite('write')):
- POST /ai/wake, /photo-jobs/wake — пинок воркеров
- POST /ai/requeue-failed, /photo-jobs/requeue-failed — error -> pending
- POST /entries/:id/ai/recheck — повторная проверка конкретной записи
Филиальная изоляция (главное в этом изменении):
- внутренние requeue-failed делают UPDATE по всей таблице; перенос их
как есть позволил бы ключу с ограничением по филиалу переочередить
чужие задания, что ломает правило «ключ не шире выдавшего»
- добавлен хелпер apiBranchClause(user, expr, params): пустая строка
для admin, AND FALSE при пустом списке филиалов, иначе
AND <expr> = ANY($N::int[]); применён к обоим массовым UPDATE
- entries фильтруется через groups.branch_id, photo_jobs — через
photo_jobs -> entries -> groups
Аудит через apiAudit() с префиксом api., метки добавлены в
public/js/audit.js; после мутаций invalidateEntries/invalidateStats
и broadcastEntryChanged.
Воркер отчётов о занятии wake-эндпоинта не получает: он будится сам
из POST/PUT /lesson-reports при ai_check === true.
Документация: таблица эндпоинтов и раздел про воркеров в README.md,
правило apiBranchClause в AGENTS.md 3f.
Проверено: изолированный тест на двух филиалах — requeue-failed
ключом одного филиала вернул count 1 из двух ошибочных заданий,
запись и фото-джоб чужого филиала остались в error, recheck чужой
записи 403; api-keys.selftest.js 61 PASS, api.smoketest.js 76 PASS,
регрессий нет.
Замечание: server.js запечён в образ, compose монтирует только
uploads/, поэтому restart правку не подхватит — нужен
./scripts/deploy.sh или docker compose up -d --build app.
This commit is contained in:
@@ -76,6 +76,11 @@ const ACTION_LABELS = {
|
||||
'ai.wake': 'Воркер ИИ разбужен вручную',
|
||||
'ai.enabled': 'Переключена автопроверка ИИ',
|
||||
'ai.requeue-failed': 'Ошибочные записи возвращены в очередь ИИ',
|
||||
'api.ai.wake': 'Воркер ИИ разбужен через API',
|
||||
'api.ai.requeue-failed': 'Ошибочные записи возвращены в очередь ИИ через API',
|
||||
'api.photo-jobs.wake': 'Фото-воркер разбужен через API',
|
||||
'api.photo-jobs.requeue-failed': 'Ошибочные фото-задания возвращены в очередь через API',
|
||||
'api.entry.ai.recheck': 'Запись отправлена на ИИ-проверку через API',
|
||||
'ai.profile.create': 'Создан профиль ИИ',
|
||||
'ai.profile.update': 'Изменён профиль ИИ',
|
||||
'ai.profile.delete': 'Удалён профиль ИИ',
|
||||
|
||||
Reference in New Issue
Block a user