WEB board

всеканоны и докиворкеры↗ iOS↗ Легаси
WEB-077 · Задача · Инфраструктура · web

[GATE-9] Upload-контур: инвентарь ВСЕХ путей загрузки + boundary-тест + прод-привязка

Закрыт P1 · важно ведёт: backup-opus
Суть
Код в снапшоте уже 100MiB (next.config.ts, uploadLimits.ts), MIME allowlist, archive caps с тестами. ОСТАЛОСЬ: инвентарь всех upload-путей (media, video, avatar, import, translate…), проверка что лимит реально действует на КАЖДОМ на прод-артефакте (негативный 100+MiB → 413 до тела), direct-upload решение для видео >100MiB (или явное ограничение), receipt.

Эпик: WEB-282. Норматив: PROD-MIGRATION-PLAN-R4.md §7. Аудит-срез: M4 MIGAUDIT-REPORT.md (20.08). Owner 20.08: «по гейтам дожимайте все до конца».

## 20.08 ~23:55 ИНВЕНТАРЬ ГОТОВ (волна gatespack): сильные guard-ы на podcast publish/video multipart/legacy upload/ME bridge/unified ingest internals. ДЫРЫ: unified-ingest callers без pre-read лимитов; OCR image БЕЗ лимита и MIME-валидации; raw audio 250MiB (>100); URL video/media 250M/500M; Telegram/WhatsApp channel-limit omissions; cloud-drive imports без byte cap. Полная таблица file:line: M4 /Users/milamarty/work/GATE9-UPLOAD-INVENTORY.md. Фиксы — в landing30.

## 21.08 ~07:50 ЗАКРЫТО В ВЕТКЕ l30upload (коммит 28f6f33d, координаторский — волна выполнила работу но не закоммитила). Дыры: pre-read гейты для мессенджеров и cloud-drive; OCR получил MAX_OCR_IMAGE_BYTES + реальный MIME-allowlist (раньше единственной «проверкой» был startsWith(image/), объявленный MIME шёл провайдеру дословно); /api/transcribe и transcribe-local теперь проверяют content-length ДО formData() и отдают 413 вместо 400 (transcribe-local не проверял вовсе); youtube-dl потолки 250M/500M приведены к общей входной границе. Ждёт посадки-30.

## 21.08 — ВЫЕХАЛО НА ПРОД
**Посадка 30 состоялась 21.08 03:53 IST.** serving = `v4-504af77f`, релиз `arm64-504af77f-20260821T025311Z`, артефакт sha `a0afc41415db60377aeb4cf399d91b98a4c407217fc8839b0b1369a2542af362`, аттестация v18. Проверено после переключения: `active`, `NRestarts=0`, `paidReady=true`, `posture=enforce_ready`, `mode=enforce`, `failures=[]`, фатальных строк boot-контракта **0**, секрет сторожа файл≡процесс (`cbabe4a2b16008e3`), nft переприменены, канон проштампован (`CANON.json: serving=504af77f marker=v4-504af77f`).
Проверка байтов релиза и живая проба выполнены после переключения; подробный трейл посадки — в WEB-282.

## 2026-08-23 BOARDSWEEP: STALE-NOT-DEPLOYED
- Evidence: buildFixed is empty. Canonical upload guards/tests exist under src/lib/upload and ingest extractors, but no deployment binding or full ingress inventory receipt is present.
- buildFixed: <empty>; canonical: v4-081ff4fb5 / 081ff4fb5f6110f8001daec7ed910ccef2e395dc.
- Status preserved by sweep: review.

## ДЛЯ НУЛЕВОГО АГЕНТА (обновлено 2026-09-05 UTC)
- **Суть одной строкой:** [GATE-9] Upload-контур: инвентарь ВСЕХ путей загрузки + boundary-тест + прод-привязка
- **Текущее состояние:** статус: done; Код в снапшоте уже 100MiB (next.config.ts, uploadLimits.ts), MIME allowlist, archive caps с тестами. ОСТАЛОСЬ: инвентарь всех upload-путей (media, video, avatar, import, translate…), проверка что лимит реально действует на КАЖДОМ на прод-артефакте (негативный 100+MiB → 413 до тела), direct-upload… | Эпик: WEB-282. Норматив: PROD-MIGRATION-PLAN-R4.md §7. Аудит-срез: M4 MIGAUDIT-REPORT.md (20.08). Owner 20.08: «по гейтам дожимайте все до конца». | 20.08 ~23:55 ИНВЕНТАРЬ ГОТОВ (волна gatespack): сильные guard-ы на podcast publish/video multipart/legacy upload/ME bridge/unified ingest internals. ДЫРЫ: unified-ingest callers без pre-read лимитов; OCR image БЕЗ лимита и MIME-валидации; raw audio 250MiB (100); URL video/media 250M/500M; Telegra… | 21.08 ~07:50 ЗАКРЫТО В ВЕТКЕ l30upload (коммит 28f6f33d, координаторский — волна выполнила работу но не закоммитила). Дыры: pre-read гейты для мессенджеров и cloud-drive; OCR получил MAXOCRIMAGEBYTES + реальный MIME-allowlist (раньше единственной «проверкой» был startsWith(image/), объявленный MI… | 21.08 — ВЫЕХАЛО НА ПРОД | Посадка 30 состоялась 21.08 03:53 IST. serving = v4-504af77f, релиз arm64-504af77f-20260821T025311Z, артефакт sha a0afc41415db60377aeb4cf399d91b98a4c407217fc8839b0b1369a2542af362, аттестация v18. Проверено после переключения: active, NRestarts=0, paidReady=true, posture=enforceready, mode=enforce… | Проверка байтов релиза и живая проба выполнены после переключения; подробный трейл посадки — в WEB-282.
- **Кто работал:**
- нет данных в тикете
- **Ветки/бандлы/отчёты:** нет данных в тикете; sha: 28f6f33d, 504af77f, cbabe4a2b16008e3, 081ff4fb5, 081ff4fb5f6110f8001daec7ed910ccef2e395dc
- **KNOWN ISSUES / ТРАБЛШУТИНГ:**
- Код в снапшоте уже 100MiB (next.config.ts, uploadLimits.ts), MIME allowlist, archive caps с тестами. ОСТАЛОСЬ: инвентарь всех upload-путей (media, video, avatar, import, translate…), проверка что лимит реально действует на КАЖДОМ на прод-артефакте (негативный 100+MiB → 413 до тела), direct-upload…
- 20.08 ~23:55 ИНВЕНТАРЬ ГОТОВ (волна gatespack): сильные guard-ы на podcast publish/video multipart/legacy upload/ME bridge/unified ingest internals. ДЫРЫ: unified-ingest callers без pre-read лимитов; OCR image БЕЗ лимита и MIME-валидации; raw audio 250MiB (100); URL video/media 250M/500M; Telegra…
- 21.08 ~07:50 ЗАКРЫТО В ВЕТКЕ l30upload (коммит 28f6f33d, координаторский — волна выполнила работу но не закоммитила). Дыры: pre-read гейты для мессенджеров и cloud-drive; OCR получил MAXOCRIMAGEBYTES + реальный MIME-allowlist (раньше единственной «проверкой» был startsWith(image/), объявленный MI…
- Посадка 30 состоялась 21.08 03:53 IST. serving = v4-504af77f, релиз arm64-504af77f-20260821T025311Z, артефакт sha a0afc41415db60377aeb4cf399d91b98a4c407217fc8839b0b1369a2542af362, аттестация v18. Проверено после переключения: active, NRestarts=0, paidReady=true, posture=enforceready, mode=enforce…
- Проверка байтов релиза и живая проба выполнены после переключения; подробный трейл посадки — в WEB-282.
- - Evidence: buildFixed is empty. Canonical upload guards/tests exist under src/lib/upload and ingest extractors, but no deployment binding or full ingress inventory receipt is present.
- - buildFixed: <empty; canonical: v4-081ff4fb5 / 081ff4fb5f6110f8001daec7ed910ccef2e395dc.
- **Эволюция:**
- Эпик: WEB-282. Норматив: PROD-MIGRATION-PLAN-R4.md §7. Аудит-срез: M4 MIGAUDIT-REPORT.md (20.08). Owner 20.08: «по гейтам дожимайте все до конца».
- 20.08 ~23:55 ИНВЕНТАРЬ ГОТОВ (волна gatespack): сильные guard-ы на podcast publish/video multipart/legacy upload/ME bridge/unified ingest internals. ДЫРЫ: unified-ingest callers без pre-read лимитов; OCR image БЕЗ лимита и MIME-валидации; raw audio 250MiB (100); URL video/media 250M/500M; Telegra…
- 21.08 ~07:50 ЗАКРЫТО В ВЕТКЕ l30upload (коммит 28f6f33d, координаторский — волна выполнила работу но не закоммитила). Дыры: pre-read гейты для мессенджеров и cloud-drive; OCR получил MAXOCRIMAGEBYTES + реальный MIME-allowlist (раньше единственной «проверкой» был startsWith(image/), объявленный MI…
- 21.08 — ВЫЕХАЛО НА ПРОД
- Посадка 30 состоялась 21.08 03:53 IST. serving = v4-504af77f, релиз arm64-504af77f-20260821T025311Z, артефакт sha a0afc41415db60377aeb4cf399d91b98a4c407217fc8839b0b1369a2542af362, аттестация v18. Проверено после переключения: active, NRestarts=0, paidReady=true, posture=enforceready, mode=enforce…
- 2026-08-23 BOARDSWEEP: STALE-NOT-DEPLOYED
- **Следующий шаг:** Эпик: WEB-282. Норматив: PROD-MIGRATION-PLAN-R4.md §7. Аудит-срез: M4 MIGAUDIT-REPORT.md (20.08). Owner 20.08: «по гейтам дожимайте все до конца». | 21.08 ~07:50 ЗАКРЫТО В ВЕТКЕ l30upload (коммит 28f6f33d, координаторский — волна выполнила работу но не закоммитила). Дыры: pre-read гейты для мессенджеров и cloud-drive; OCR получил MAXOCRIMAGEBYTES + реальный MIME-allowlist (раньше единственной «проверкой» был startsWith(image/), объявленный MI…
Доказательства

[2026-08-24 STALEREV против 61bc04462; в проде с посадки 45 v4-5a4edbac3] Вердикт CANT-VERIFY: код/тесты в дереве есть, но board-критерий требует live/visual/paid-проб — остаётся в review до браузерной приёмки. Отчёт: A1 /home/ubuntu/waves/STALEREVIEW-REPORT.md (STALEREVIEW_DONE).
[2026-08-25 19:11Z] Независимая приёмка запущена: волна accgates на A1 (sol xhigh, приёмщик≠автор), worktree от прод-коммита a453b16; обязательны негативные тесты новых классов; для не-влитых тикетов волна установит факт NOT-LANDED. Бриф /home/ubuntu/waves/accgates-brief.md, отчёт будет в ACCGATES-REPORT.md.
[2026-08-25 20:05Z] NO-GO приёмки accgates (LANDED/REJECT): лимиты/bounded downloads/OCR есть (50/50 зонных), но центрального реестра upload-путей нет — негатив «недекларированный путь → fail-closed» ПРОВАЛЕН. Нужен admission boundary (DECLARED_UPLOAD_PATHS). Фикс-волна web077fix запущена.
[2026-08-25 20:36Z] ФИКС ГОТОВ (web077fix GO @f77e6b8): src/lib/upload/uploadAdmission.ts — реестр DECLARED_UPLOAD_PATHS (28 путей: route/kind/типы/лимит/фича) + assertDeclaredUploadPath (недекларированный→403 UPLOAD_PATH_NOT_DECLARED + X-NB-Guard + rule-10 лог). Тесты 56/56, boundary rc=0. → review, ждёт re-accept.
[2026-08-25 21:35Z] Независимый re-accept reacc077 (luna) запущен: авто-скан всех upload-роутов на полноту реестра + fail-closed негативы.
[2026-08-25 21:46Z] reacc077 NO-GO (независимый, другой приёмщик): реестр НЕПОЛОН — полный скан 522 роутов нашёл 3 незадекларированных file-ingest пути (dropbox/google/onedrive /files: POST fileIds→download→parseBuffer, без assertDeclaredUploadPath). Первый реестр строился УЗКИМ сканом. Фикс web077fix2: добавить 3 пути+гейты И переделать инвентарный тест на ПОЛНЫЙ скан (падает если ingest-путь не в реестре).
[2026-08-25 22:00Z] ФИКС web077fix2 @38ac88c GO: 3 integration file-ingest пути (dropbox/google/onedrive) добавлены в DECLARED_UPLOAD_PATHS + admission gate до req.json() + pre-read cap (readCappedResponseBuffer/gaxios maxContentLength, 413 при превышении). ⭐ Инвентарный тест переделан на ПОЛНЫЙ рекурсивный скан 522 роутов (multipart/arrayBuffer/contentBase64/fileIds+downloader+parseBuffer) — падает если ingest-путь не в реестре. Корень (узкий скан) устранён. → review на финальный re-accept.
[2026-08-25 22:18Z] ПРИНЯТ reacc077b (независимо, полный скан 522 роутов подтвердил 0 пропущенных ingest-путей; google/onedrive/dropbox /files→403 fail-closed при недекларации): GO. Реестр полон, корень (узкий скан) закрыт. → done.
Починено в
a453b16
Воркер
не привязан — привязать: curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \ -d '{"issueId":"WEB-077","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-05T21:05:36.473Z