Вы заплатили разработчику или собрали приложение сами с помощью ИИ. Я читаю код и показываю, что на самом деле происходит, когда клиент нажимает кнопку.
Проверить мой проектПервые десять бесплатно. Отвечаю сам, обычно в тот же день.
Заказ пишется в базу, но никто не смотрит, записался ли он. Если база откажет, деньги с человека спишутся, а заказа не будет.
api/checkout/route.ts:30
Работу сдали. Вы кликаете - всё работает.
Регистрация работает. Корзина работает. Оплата проходит, деньги списываются, появляется страница «спасибо». Вы оплачиваете счёт и запускаетесь.
Через пять недель клиент пишет: я заплатил, где мой заказ?
Вы смотрите в админку. Заказа нет. Деньги с карты ушли, Stripe это подтверждает, а записи не существует. Сколько таких было до него, вы не знаете: остальные просто не написали.
Вот что всё это время было в коде.
Заказ пишется в базу, и никто не смотрит, записался ли он. Клиент базы при отказе не бросает исключение, а возвращает ошибку в ответе. В ответ никто не смотрит, поэтому код идёт дальше и списывает деньги.
Из приложения этого не видно вообще.
Оно случается, только когда база отказала: таймаут, кончилось место, поменялось правило доступа. В обычный день всё работает - поэтому оно и дожило до запуска и прошло вашу приёмку.
Зато видно в коде, если прочитать путь целиком.
Кнопка, запрос, сервер, база, Stripe - выписаны по шагам, и то место, где цепочка рвётся, помечено. В этом проекте 9 обращений к базе из 10 результат проверяют. Десятое - то самое, на пути денег.
В этом и весь смысл
Я читаю код проекта, который вам сдали, прослеживаю все пути клиента и говорю человеческими словами, где рвётся. Первые десять проверок бесплатно, руками, обычно в тот же день.
Проверить мой проектТот же демо-магазин целиком: все пути, которыми может пойти клиент, разложенные по вопросам, которые вы и так задаёте.
И ещё одна находка из того же прогона
В 16 точках входа из 17 этот проект проверяет, кто спрашивает. В одной - нет: чужой заказ прочитает любой, кто знает адрес.
src/app/api/orders/[id]/route.ts:5
В этом магазине 18 путей. В настоящем проекте их обычно от ста до трёхсот, и отчёт устроен так же: сначала вопросы, под ними пути, а дальше каждый путь целиком.
Вот что вы получите: сначала вывод человеческими словами, потом каждая находка с точным файлом и строкой. Откройте до того, как что-то присылать.
Открыть пример отчётаВы присылаете ссылку
Достаточно ссылки на публичный репозиторий. Если он закрытый, ниже есть два других пути.
Я гоняю инструмент и читаю результат руками
Движок прослеживает все пути клиента. Каждую находку я сверяю с исходником сам: инструмент в одиночку ошибается достаточно часто, чтобы это было важно.
Вы получаете личную ссылку на отчёт
Обычно в тот же день. В отчёте указаны файлы и строки, так что его можно передать разработчику как есть.
Все пути клиента, разложенные по шагам
Регистрация, оплата, удаление, письма, данные, уходящие в чужие сервисы. По каждому: что нажали, куда ушёл запрос, что сделал сервер, дошло ли до базы и что будет при отказе.
Места, где путь рвётся
Запись в базу без проверки, что она прошла. Отказ, который никто не обрабатывает. Запись, которую берут по идентификатору, не проверив, что она принадлежит этому пользователю. Ключи в открытом коде. У каждой находки файл и номер строки, чтобы разработчику было нечего возразить.
Я читаю код, а не запускаю приложение. Поэтому не скажу «кнопка нажимается» и «страница выглядит правильно», и общего вердикта «проект хороший» тоже не будет: молчание там, где инструмент слеп, честнее зелёной галочки. Зато то, что скажу, будет точным - с файлом и номером строки.
Первый: вы наняли человека, он сказал «готово», а проверить вам нечем. Второй: вы собрали приложение сами через ИИ, оно постоянно ломается, и перед запуском хочется понять, в каком оно состоянии. В обоих случаях проект живёт на Supabase и я вижу код. Проверку делаю руками и отвечаю сам, поэтому первые десять бесплатно.
Если репозиторий публичный, отдавать нечего: его уже читают все, включая ботов, которые круглосуточно ищут на GitHub ключи. Если закрытый, присылать его целиком не нужно, ниже два других пути. А если проект не ваш, а вашего разработчика, попросите у него доступ на чтение или папку с миграциями: это обычная просьба, он поймёт.
Публичный репозиторий: пришлите ссылку, больше ничего
Я клонирую, читаю миграции и исходники, а клон удаляю, когда отчёт написан. Ни доступа к аккаунту, ни приглашения, ни прав.
Закрытый репозиторий: пришлите только миграции
Папки `supabase/migrations` хватает для большей части находок. Там описания таблиц и политик, а не ваша бизнес-логика, и именно там живут эти проблемы.
Ничего не покидает вашу машину: выполните один запрос сами
Откройте SQL-редактор Supabase, выполните запрос ниже и пришлите, что он вернул. Там имена политик и таблиц, кода нет вообще. Я скажу, какие строки важны и что с ними делать.
SELECT tablename, policyname, cmd, roles, qual, with_check
FROM pg_policies
WHERE schemaname = 'public' AND cmd <> 'SELECT'
AND (qual = 'true' OR with_check = 'true');Инструмент называется plumbline, отвес для кодовой базы. Автор: nzt108, hello@nzt108.dev