1. Общего понимания проекта мало — нужна карта
Откройте Commerce OS — впечатление обманчиво простое: заказы, платежи, поддержка, отчёты. Хватает до первого вопроса: «где ломается возврат?», «какой маршрут вызывает платёжный сервис?» В этот момент «вроде понятно» превращается в блуждание по папкам.
CODEBASE_INVENTORY.md отвечает на вопрос «что в проекте есть». API_MAP.md — на вопрос «куда идёт запрос»: через какой маршрут он входит, где уходит в сервисы, когда упирается в базу, когда дёргает платёжного провайдера. Один сценарий тянет за собой HTTP-маршрут, бизнес-логику, клиента внешнего сервиса, очередь событий, конфиг и тесты. Без карты каждое расследование начинается с нуля.
Это рабочий документ: куда входит запрос, куда идёт дальше, чем подтверждается.
2. Интеграция — это любой важный стык, не только внешний
«Интеграция» звучит так, будто речь про платёжный шлюз, CRM и вебхуки. В учебном смысле это любой важный стык между частями системы, влияющий на поведение: и внешние сервисы, и внутренние точки соединения. Смотрите на них через таблицу:
| Что мы видим в проекте | Пример в Commerce OS | Почему это попадает в карту |
|---|---|---|
| HTTP-эндпоинт | |
Это входная точка пользовательского сценария |
| Обработчик или контроллер | |
Здесь начинается серверный маршрут |
| Внутренний клиент | |
Он связывает проект с внешним сервисом |
| База данных | таблицы заказов и возвратов | Без неё многие маршруты просто не имеют смысла |
| Очередь или событие | |
Это асинхронное продолжение сценария |
| Граница авторизации | customer session, operator role | Показывает, кто вообще имеет право вызвать маршрут |
| Конфигурация окружения | , |
Маршрут зависит не только от кода, но и от настроек |
| Тесты | |
Они подтверждают контракт и ожидаемое поведение |
Ловушка: не путайте карту интеграций проекта с подключением Claude Code к внешним инструментам. Здесь мы описываем то, что уже живёт внутри кодовой базы, а не настраиваем новые подключения для самого Claude.
Граница авторизации — это ответ на вопрос кто может дойти до этого маршрута: аннотация на методе, фильтр, правила в конфиге безопасности, тест.
3. Доказательства берём из кода, а не из догадок
Частая ошибка звучит мило и опасно одновременно: «Ну он же правдоподобно объяснил». Правдоподобно — не значит проверяемо. Источник истины один: код, конфиги, тесты, при нужде команды сборки.
Вот удобная опора: откуда что обычно подтверждается.
| Источник в проекте | Что он обычно доказывает |
|---|---|
| Контроллер, маршрут, обработчик | Что эндпоинт реально существует |
| Сервис или клиент | Куда маршрут идёт дальше |
| Конфигурация | Какие переменные окружения и внешние зависимости нужны |
| Тест | Какой контракт или сценарий проект считает нормальным |
| Файл сборки | Что внешняя библиотека вообще подключена |
| Комментарий в коде | Иногда помогает, но сам по себе не является достаточным доказательством |
Посмотрите на упрощённый фрагмент контроллера:
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/orders")
class OrderController { // фрагмент класса
@PostMapping
OrderResponse create(@RequestBody CreateOrderRequest request) {
return orderService.createOrder(request); // дальше маршрут уходит в сервис
}
}
Этот кусок уже подтверждает несколько вещей. Во-первых, маршрут POST /api/orders существует. Во-вторых, точка входа находится в OrderController. В-третьих, контроллер сам почти ничего не делает, а передаёт выполнение в OrderService. Значит, на этом расследование не заканчивается.
Теперь посмотрим на конфигурацию:
payments:
stripe:
api-key: ${STRIPE_API_KEY}
queues:
order-events-url: ${QUEUE_URL}
Конфиг не доказывает, что вызов точно произойдёт, но показывает важные зависимости маршрута от окружения. Если в карте вы пишете «создание заказа использует Stripe и очередь событий», а в конфиге нет даже следов этих настроек, стоит насторожиться. Может быть, вы перепутали сервис, а может быть, нашли старый мёртвый код.
Тесты тоже очень полезны, потому что подтверждают не только существование маршрута, но и ожидания проекта:
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Test
void create_returns400_forEmptyCart() throws Exception {
mockMvc.perform(post("/api/orders").content("{}"))
.andExpect(status().isBadRequest()); // пустая корзина недопустима
}
Такой тест — это уже доказательство контракта API. Он не просто говорит «маршрут есть», а добавляет важное условие поведения: пустая корзина должна давать ошибку 400, а не, например, молча создавать пустой заказ. Для карты это очень полезно, потому что она перестаёт быть сухим списком URL и начинает фиксировать реальное поведение системы.
4. Хороший API_MAP.md — короткий и проверяемый
Когда студенты впервые делают такой артефакт, они обычно бросаются в одну из двух крайностей. Либо пишут две строчки в духе «у нас есть заказы и платежи», либо пытаются сделать энциклопедию мира на сорок экранов. Обе крайности не очень полезны. Хорошая карта должна быть короткой, рабочей и проверяемой.
Для Commerce OS достаточно начать с простой структуры:
# API_MAP.md
## Customer API
## Support API
## Dashboard API
## Внешние интеграции
## Открытые вопросы
А внутри секций уже удобно использовать таблицу. Например, такую:
| Поле | Зачем оно нужно |
|---|---|
| Метод и путь | Быстро найти входную точку |
| Обработчик | Понять, где начинается кодовый маршрут |
| Авторизация | Увидеть, кто имеет доступ |
| Интеграции | Зафиксировать базу, очередь, внешние клиенты |
| Конфиг | Понять, от чего маршрут зависит в окружении |
| Тесты | Подтвердить контракт и поведение |
| Открытые вопросы | Не выдумывать отсутствующие факты |
Обратите внимание на последнюю колонку. Она дисциплинирует лучше любого пафосного лозунга. Если вы не нашли мобильного клиента, который использует маршрут, не нужно писать «используется мобильным приложением» только потому, что так было бы логично. Напишите честно: «не проверено».
Очень полезно относиться к API_MAP.md как к живому файлу в репозитории, а не как к красивому ответу в окне чата. Ответ Claude Code может помочь собрать черновик, но рабочим артефактом карта становится только тогда, когда лежит рядом с проектом, проходит через diff и обновляется после изменений.
5. Разбор маршрута на примере создания заказа
Теперь соберём один маршрут целиком, чтобы вы увидели, как из кода рождается нормальная запись в API_MAP.md. Возьмём Commerce OS и типичный сценарий создания заказа.
Сначала полезно увидеть маршрут в виде схемы:
Веб-клиент
↓
POST /api/orders
↓
OrderController
↓
OrderService
├─→ StripeClient // внешний провайдер оплаты
├─→ OrderEventPublisher // событие в очередь
└─→ PostgreSQL // сохранение заказа
Теперь посмотрим на сервисный слой:
import org.springframework.stereotype.Service;
@Service
class OrderService { // фрагмент класса
OrderResponse createOrder(CreateOrderRequest request) {
paymentClient.charge(request.payment()); // внешний платёжный сервис
orderEventPublisher.publishCreated(request); // асинхронное событие
return OrderResponse.created();
}
}
Вот тут уже появляется настоящая интеграционная информация. Если контроллер доказал вход в маршрут, то сервис доказывает, что сценарий идёт как минимум в две стороны: к платёжному клиенту и к издателю событий. Если где-то рядом ещё есть сохранение заказа в репозиторий, значит, в карте стоит упомянуть и базу данных.
Теперь на основе этих фрагментов можно собрать запись в API_MAP.md:
## Customer API
| Метод | Путь | Обработчик | Авторизация | Интеграции | Конфиг | Тесты | Открытые вопросы |
|---|---|---|---|---|---|---|---|
| POST | /api/orders | OrderController#create | customer session | PostgreSQL `orders`, `StripeClient`, `order-events` queue | `STRIPE_API_KEY`, `QUEUE_URL` | `OrderControllerTest#create_returns400_forEmptyCart` | использует ли маршрут mobile-клиент напрямую? |
Заметьте, как мы пришли к этой строке. Не «Claude красиво резюмировал», а буквально собрали её из наблюдаемых деталей: контроллера, сервиса, конфига и теста. Если вы научитесь делать так хотя бы для трёх-четырёх ключевых маршрутов проекта, дальше работать станет спокойнее. Уже не нужно каждый раз заново вспоминать, где у проекта платежи, где события, а где только HTTP-обёртка.
И да, это ровно тот момент, когда становится видно, почему карта API — это не просто список эндпоинтов. Если бы вы зафиксировали только POST /api/orders, вы бы потеряли почти всё интересное.
6. Просим у Claude Code карту, а не выдумки
Здесь соблазн особенно велик. Очень хочется написать: «Посмотри проект и расскажи, какие тут API и интеграции». Claude Code, как вежливый собеседник, постарается помочь. Иногда даже слишком старательно: расскажет не только то, что нашёл, но и то, что просто звучит правдоподобно. Нам такое не подходит.
Слабый запрос выглядит примерно так:
Расскажи, какие API есть в проекте.
После такого запроса вы почти гарантированно получите красивый, но рыхлый текст. Нормальный запрос должен заставить модель работать как аккуратный помощник по исследованию, а не как экскурсовод-импровизатор. Например, так:
Построй черновик файла API_MAP.md для этого репозитория.
Для каждой записи укажи:
- метод и путь;
- файл обработчика;
- связанную бизнес-логику или клиент;
- границу авторизации, если она видна;
- конфиг или переменные окружения, от которых зависит маршрут;
- связанные тесты;
- что не удалось проверить.
Не придумывай недостающие факты.
Если доказательства нет, помечай это как открытый вопрос.
У такого запроса есть сразу несколько плюсов. Во-первых, вы просите именно черновик, а не истину в последней инстанции. Во-вторых, вы задаёте структуру ответа. В-третьих, вы прямо запрещаете модели додумывать недостающие факты.
Если Claude пишет фразу вроде «проект использует Stripe», хороший следующий вопрос звучит очень просто: покажи, чем это подтверждается. Файл клиента, зависимость в сборке, ключ в конфиге, тест, использование в сервисе — что угодно из этого уже превращает догадку в проверяемое утверждение. А вот фраза без опоры должна либо получить доказательство, либо отправиться в колонку «открытые вопросы».
7. Карта живёт в репозитории, а не в истории чата
Очень легко один раз собрать информацию, порадоваться и оставить её в чате, где она героически утонет через пару дней в новых обсуждениях. Но пользы от такого подхода немного. Артефакт начинает работать только тогда, когда лежит рядом с кодом и меняется вместе с кодом.
Есть простое практическое правило: вы не обязаны описать весь проект за один присест. Гораздо полезнее начать с нескольких критичных маршрутов — например, заказы, возвраты, поддержка — а потом дополнять карту по мере расследований. Нашли новый webhook — добавили строку. Обнаружили, что маршрут зависит ещё от одной переменной окружения, — обновили запись. Появился тест, подтверждающий контракт, — дописали его в карту. Это дешевле и надёжнее, чем пытаться написать «полную документацию мира» в первый же день.
Хорошая карта обычно немного неполная, но честная. Плохая карта — очень полная, очень красивая и местами выдуманная. Для инженерной работы почти всегда лучше первый вариант. Особенно если вы работаете с Claude Code и хотите, чтобы он потом использовал этот файл как надёжный контекст, а не как сборник легенд о проекте.
Поэтому для Commerce OS сегодня у вас очень понятная цель: начать API_MAP.md с нескольких проверенных маршрутов, фиксировать рядом обработчик, авторизацию, интеграции, конфиг и тесты, а всё непроверенное честно складывать в открытые вопросы. В этот момент проект перестаёт быть тёмным лесом с табличкой «тут где-то есть платежи» и начинает превращаться в систему, по которой уже можно ходить не на ощупь, а по карте.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ