Skip to content

Repository files navigation

approval-service

Backend-сервис для процесса согласования контента перед публикацией.

Стек

  • Python 3.12
  • FastAPI
  • SQLAlchemy 2.x
  • Alembic migrations
  • PostgreSQL в Docker Compose
  • SQLite для быстрых локальных тестов
  • pytest

Быстрый запуск одной командой

docker compose up --build

Команда собирает Docker-образ API, поднимает PostgreSQL, дожидается healthcheck базы, применяет миграции Alembic и запускает FastAPI на http://localhost:8000.

Проверка:

curl http://localhost:8000/health
curl http://localhost:8000/ready

Swagger UI доступен на http://localhost:8000/docs.

Остановка

docker compose down -v

Тесты

Локально:

pip install -r requirements.txt
pytest

Проверка покрытия:

pytest --cov=app --cov-report=term-missing

Через Docker-образ API:

docker compose run --rm api pytest

Auth-заглушка

Для локального запуска используется header-based auth stub.

Обязательные заголовки для API /api/v1/...:

X-Workspace-Id: ws_1
X-User-Id: usr_1
X-Actions: approval:read,approval:create,approval:decide,approval:cancel

Поддерживаемые actions:

  • approval:read — чтение заявок
  • approval:create — создание заявок
  • approval:decide — approve/reject
  • approval:cancel — cancel

X-Workspace-Id обязан совпадать с {workspace_id} в URL. Иначе сервис вернёт 403.

Для создания заявки обязателен заголовок идемпотентности:

Idempotency-Key: client-request-123

Повтор POST с тем же Idempotency-Key и тем же body вернёт уже созданную заявку. Повтор с тем же ключом, но другим body вернёт 409 Conflict.

Пример создания заявки

curl -X POST http://localhost:8000/api/v1/workspaces/ws_1/approval-requests \
  -H 'Content-Type: application/json' \
  -H 'X-Workspace-Id: ws_1' \
  -H 'X-User-Id: usr_1' \
  -H 'X-Actions: approval:create' \
  -H 'Idempotency-Key: create-approval-001' \
  -d '{
    "sourceType": "publication",
    "sourceId": "pub_123",
    "title": "Instagram reel draft",
    "description": "Needs final approval",
    "reviewerUserIds": ["usr_2", "usr_3"]
  }'

Пример чтения списка

curl http://localhost:8000/api/v1/workspaces/ws_1/approval-requests \
  -H 'X-Workspace-Id: ws_1' \
  -H 'X-User-Id: usr_1' \
  -H 'X-Actions: approval:read'

Пример approve

curl -X POST http://localhost:8000/api/v1/workspaces/ws_1/approval-requests/<request_id>/approve \
  -H 'Content-Type: application/json' \
  -H 'X-Workspace-Id: ws_1' \
  -H 'X-User-Id: usr_reviewer' \
  -H 'X-Actions: approval:decide' \
  -d '{"comment": "Approved"}'

Пример reject

curl -X POST http://localhost:8000/api/v1/workspaces/ws_1/approval-requests/<request_id>/reject \
  -H 'Content-Type: application/json' \
  -H 'X-Workspace-Id: ws_1' \
  -H 'X-User-Id: usr_reviewer' \
  -H 'X-Actions: approval:decide' \
  -d '{"reason": "Brand tone is wrong"}'

Пример cancel

curl -X POST http://localhost:8000/api/v1/workspaces/ws_1/approval-requests/<request_id>/cancel \
  -H 'Content-Type: application/json' \
  -H 'X-Workspace-Id: ws_1' \
  -H 'X-User-Id: usr_1' \
  -H 'X-Actions: approval:cancel' \
  -d '{"reason": "Draft was removed"}'

Миграции

Миграции применяются автоматически при старте контейнера API.

Ручной запуск:

DATABASE_URL=postgresql+psycopg://approval:approval@localhost:5432/approval_service alembic upgrade head

Security / redaction policy

Сервис не принимает в публичные поля секреты, токены, email, storage keys, signed URLs, provider URLs и сырые provider payloads. Валидационные ошибки возвращаются в обобщённом виде, чтобы не отразить потенциально чувствительный input обратно клиенту.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages