Живой тест показал: 77 файлов отслеживаются, но get_task_file отвечал «не
относится к задаче» — старые backfill-строки без task_id/field_id (ON CONFLICT
DO NOTHING их не обновлял), а проверка по file-полям искала ключ только в
строковых значениях (file-поля хранятся объектом/массивом).
- MCP get_task_file: поиск ключа в JSON.stringify(value) для нестроковых значений;
- trackFileOnDemand: у существующих строк без task_id дозаполняет taskId/fieldId;
- startup-backfill: UPDATE task_id/field_id из task_field_values и task_messages
для строк с task_id IS NULL.
Проблема: прямое скачивание /api/files/<key> с X-Api-Key давало 403 (файловые
эндпоинты принимали только JWT), а get_task_file отвечал «не отслеживается» —
77 файлов со старыми АБСОЛЮТНЫМИ URL (https://iistwin.ru/api/files/...) не
попадали в file_uploads: startup-backfill понимал только относительные ссылки.
- tryPresignedOrAuth: ветка X-Api-Key — resolve ключа, req.apiKey/organizationId,
tenant-контекст; владение проверяет canAccessFile, скоупы форм — новый
checkApiKeyFileScope (файл привязан к задаче → форма должна быть разрешена ключом);
- /api/files/:key/presigned теперь тоже через tryPresignedOrAuth (боты могут
выпускать presigned-ссылки);
- server/utils/file-tracking.ts: trackFileOnDemand — догрузка по требованию из
task_field_values/task_messages по ссылке любого вида; используется в
canAccessFile и MCP get_task_file;
- startup-backfill: паттерны покрывают абсолютные URL (substring FROM regex).