randomayzer/agents/antigravity/done/TASK-2026-08-21-13-preview-anonymous-policy.md

4.9 KiB
Raw Blame History

Task 13: Политика анонимного доступа к POST /api/posts/preview Report

Date: 2026-08-21
Base Commit SHA: 76ab7d0e77d06cbc31b66fc5c0cdd80282d7f496
Status: COMPLETED / PASS
Assigned Agent: Antigravity (Implementation Orchestrator)


1. Исправление предыдущего утверждения (Correction of Finding)

В отчёте по Заданию 05 (agents/antigravity/done/TASK-2026-08-21-05-post-preview-auth.md:37) содержалось ошибочное утверждение:

"Quota Protection: Невозможно истощить квоту приложения анонимными запросами благодаря строгому ограничению IP."

Фактический анализ:

  1. При TRUST_PROXY=true злоумышленник с пулом IP-адресов мог линейно расходовать квоту VK_SERVICE_TOKEN, обходя per-IP лимитер.
  2. При дефолтной конфигурации (TRUST_PROXY не задан, пустой req.ip) все анонимные клиенты делили один ключ direct-client. Превышение 15 запросов одним пользователем блокировало превью всем остальным анонимам, создавая DoS.
  3. Весь сценарий визарда создания розыгрыша в интерфейсе (handleFetchPost -> POST /api/giveaways) требует авторизации через VK ID (requireAuthenticatedUser), поэтому анонимный доступ к превью не обслуживал ни один завершаемый пользовательский сценарий.

2. Принятое архитектурное решение: Вариант A (Обязательная аутентификация)

  1. Защита маршрута POST /api/posts/preview (src/app/api/posts/preview/route.ts):

    • На маршрут установлен вызов const sessionUser = await requireAuthenticatedUser(req).
    • Анонимные запросы без сессионной куки немедленно отклоняются с кодом 401 Unauthorized.
    • Запросы без авторизации никогда не обращаются к VK API / провайдеру (0 вызовов VK API, что математически и аппаратно доказано mock-счетчиками в тестах).
    • Лимитирование переведено на user-scoped ключ организатора: generalApiRateLimiter.assertAllowed('post-preview:user:' + sessionUser.id) (120 запросов / мин).
  2. Интерфейс пользователя (src/app/giveaways/new/page.tsx):

    • Клиентский визард корректно обрабатывает 401 на этапе предпросмотра поста и выводит понятное сообщение: «Для создания розыгрыша и предпросмотра публикации необходимо войти через VK ID.» со ссылкой на вход, сохраняющей целевой URL.

3. Modified & Created Files

File Status Description
src/app/api/posts/preview/route.ts MODIFIED Установлен requireAuthenticatedUser(req) и user-scoped rate limiter.
tests/preview-quota-policy.test.ts NEW 4 теста: отсечение анонимов с 401 и 0 вызовов VK API, успешный preview для организатора, user-scoped лимит, CSRF-защита.
tests/post-preview-guard.test.ts MODIFIED Тест 3 обновлен под обязательную аутентификацию (401).
tests/rate-limit-identity.test.ts MODIFIED Тестирование TRUST_PROXY=true переведено на публичный эндпоинт GET /api/giveaways/[id]/public.
tests/security.test.ts MODIFIED В тест утечки токенов добавлена сессия организатора.
tests/effective-capabilities-truthfulness.test.ts MODIFIED Тест 4 обновлен для авторизованного пользователя без кастомных токенов.

4. Verification Evidence

npx prisma generate  -> EXIT 0 (Prisma Client v5.22.0)
npx tsc --noEmit     -> EXIT 0 (0 ошибок типизации во всех 59 тест-файлах и исходном коде)
npm test             -> EXIT 0 (59 тест-сьютов, 342 теста пройдены успешно)
npm run lint         -> EXIT 0 (0 ошибок, 6 warnings на no-img-element)
npm run build        -> EXIT 0 (Все 17 маршрутов скомпилированы успешно в Next.js 16.3.2)
npm audit --omit=dev -> EXIT 0 (0 vulnerabilities)