Главная/Рецепты (Cookbook)/Резолвите credentials ENУКРРУС API-справочник (ReDoc) ↗

Резолвите credentials

Пройдите цепочку USER → ORGANIZATION → PLATFORM с места рантайма и наблюдайте, как каждый уровень побеждает по очереди.

Взгляд с сервисной плоскости: рантайм перевода запрашивает эффективный ключ, и цепочка отвечает. Этот сценарий заготавливает все три уровня и промах, так что каждая ветка прохода показывает себя.

Цель

Наблюдать, как credential_source меняется с user на organization и на platform по мере исчезновения верхних уровней, и закончить промахом 404 CREDENTIAL_NOT_CONFIGURED.

Предварительные условия

  • Сервисный токен со scope provider-credentials.invoke: export SERVICE_TOKEN=... (Service Plane Tokens).
  • Заготовленные записи для одного провайдера: личный default пользователя, default организации, платформенный default (сценарии 02, 05, 07).

Шаги

1. Собственный ключ пользователя побеждает

Вызовите POST /internal/v1/credentials/resolve:

curl -s -X POST "$CREDS_BASE/internal/v1/credentials/resolve" \
  -H "Authorization: Bearer $SERVICE_TOKEN" -H "Content-Type: application/json" \
  -d '{
    "user_id": "'$USER_ID'",
    "org_id": "'$ORG_ID'",
    "provider_code": "'$CODE'",
    "purpose": "translation",
    "correlation_id": "cookbook-06-a"
  }'

Ожидаемый 200: credential_source: "user" и — уникально для этой плоскости — plaintext credentials. Обращайтесь соответственно (Resolve Chain).

2. Уберите пользовательский уровень — вступает организация

Удалите (или отключите) credential пользователя, снова резолвните с тем же телом. Ожидаемый 200 с credential_source: "organization", owner_id = UUID организации.

3. Уберите организацию из запроса — ловит платформа

Резолвните без org_id. Ожидаемый 200 с credential_source: "platform" — отсутствие контекста организации означает, что уровень пропускается целиком, и отдаёт общий fallback.

4. Запретите fallback — управляемый промах

Тот же запрос плюс "allow_platform_fallback": false:

r = httpx.post(f"{CREDS_BASE}/internal/v1/credentials/resolve",
               headers={"Authorization": f"Bearer {SERVICE_TOKEN}"},
               json={**body, "allow_platform_fallback": False})
assert r.status_code == 404
assert r.json()["error"]["code"] == "CREDENTIAL_NOT_CONFIGURED"

Ожидаемый 404 CREDENTIAL_NOT_CONFIGURED — провайдер существует, ничего допустимого не настроено. Каждый шаг этого сценария, попадания и промах равно, теперь виден в audit-ленте под вашими correlation id (сценарий 09).

Токенам с неверным scope отказывают, а не понижают их

Повторите шаг 1 с admin-scoped токеном: ожидаемый 403 FORBIDDEN. Resolve принадлежит одному лишь provider-credentials.invoke.

Проверено тестом test_s06_resolve_credentials.