114Структура учебного эталона
Репозиторий api-standard-template содержит не только код, но и все документы контракта.
api-standard-template/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ ├── workflows/ci.yml, docs.yml
│ ├── CODEOWNERS
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── dependabot.yml
├── app/
├── docs/
│ ├── STANDARDS.md, API_STYLE_GUIDE.md
│ ├── QUICKSTART.md, VERSIONING.md, ERRORS.md
│ ├── SECURITY.md, CONTRIBUTING.md
│ └── adr/
├── openapi/
├── scripts/
├── tests/
├── .spectral.yaml
├── CHANGELOG.md
├── LICENSE
└── README.md
| Папка или файл | Назначение |
|---|
app/ | FastAPI-приложение |
docs/ | правила, политика версий, ошибки, безопасность, ADR |
openapi/ | выгруженный контракт |
scripts/ | выгрузка контракта и сборка страниц ошибок |
.github/ | CI, публикация документации, шаблоны, владельцы кода |
docs/STANDARDS.md | источник каждого правила с цитатой и переводом |
tests/ | поведение endpoints и правила контракта |
.spectral.yaml | правила линтера |
115Это не только FastAPI-код
Вокруг пяти операций собраны артефакты, которые делают API проверяемым контрактом.
OpenAPISwagger UIReDocBearer schemeProblem DetailspaginationAPI Style Guide
GET /tickets
POST /tickets
GET /tickets/{id}
PATCH /tickets/{id}
DELETE /tickets/{id}
versioning policyADRCHANGELOGcontract testsCISpectraloasdiffETag · If-MatchIdempotency-KeyX-Request-IdCODEOWNERSSTANDARDS.md
Все проверки проходят на версии 1.1.0: 31 тест, export_openapi.py --check и Spectral без замечаний.
116Не копируем Service Desk без изменений
В практической работе вы выбираете собственную предметную область и строите контракт для неё.
Например: Books, Events, Cinema, Warehouse, Delivery, Games, Pets, Music, Reservations.
После выбора необходимо:
- определить ресурсы;
- спроектировать URI;
- выбрать HTTP methods;
- определить request/response schemas;
- определить status codes;
- создать собственный Style Guide;
- реализовать API;
- проверить OpenAPI;
- оформить документацию.
DOMAIN→RESOURCES→CONTRACT→IMPLEMENTATION→VALIDATION
Первый черновик контракта своей области можно проверить здесь же:
мой контрактметод и путь, по одному на строку
117Контракт является частью repository
Изменение контракта оформляется так же, как изменение кода. Git заново не изучаем.
- Save
- Source Control
- Commit
- Push
- GitHub
- GitHub Actions
Сообщение commit должно описывать изменение контракта:
документ
docs(api): define ticket error contract
новая возможность
feat(api): add ticket pagination
Перед commit выполните python scripts/export_openapi.py: иначе CI найдёт расхождение openapi/openapi.json с кодом.
118Диагностика стандарта
Если CI не проходит, двигайтесь от сообщения об ошибке к правилу, а от правила к файлу.
- какой именно test или шаг упал;
- какой endpoint указан в сообщении;
- существует ли
operationId; - определён ли success response;
- соответствует ли
response_model возвращаемым данным; - обновлена ли OpenAPI schema в
openapi/; - не нашёл ли oasdiff breaking change в job
breaking-changes; - обновлён ли CHANGELOG;
- сохранён ли файл;
- отправлен ли новый commit.
- CI FAIL
- RULE
- FILE
- CONTRACT
- FIX
пример сообщения
FAILED tests/test_contract.py::test_every_operation_has_operation_id
AssertionError: GET /api/v1/tickets/{ticket_id} has no operationId
119Контрольные артефакты работы
Для отчёта сохраните ссылки, файлы и скриншоты.
- ссылка на GitHub repository
- screenshot Swagger UI
- screenshot ReDoc
- screenshot
/openapi.json - screenshot успешного POST
- screenshot
404 application/problem+json API_STYLE_GUIDE.mdVERSIONING.mdCHANGELOG.md- ADR
- OpenAPI YAML/JSON
- screenshot успешного GitHub Actions run
- commit hash итоговой версии
Swagger UI · POST /api/v1/ticketsСКРИНШОТ · 15.09.2026
Так выглядит скриншот успешного POST: код 201, тело созданного обращения и заголовок location. Клик — увеличить.
120Проверяем понимание, а не память
Студент должен своими словами объяснить ответы на эти вопросы.
- Почему REST и HTTP — не одно и то же?
- Почему Swagger и OpenAPI — не одно и то же?
- Почему
GET /deleteUser является плохим контрактом? - Почему
POST и PUT имеют разную семантику? - Почему
401 и 403 нельзя считать одинаковыми? - Почему OpenAPI version и API version — разные вещи?
- Что делает breaking change опасным?
- Зачем нужен
operationId? - Почему Problem Details лучше произвольного JSON?
- Зачем API Style Guide, если уже существует OpenAPI?
- Что проверяет Spectral?
- Почему успешные тесты приложения ещё не гарантируют качественный API contract?
«ПОЧЕМУ?» вместо «ГДЕ КНОПКА?»