Ланцюг resolve
USER → ORGANIZATION → PLATFORM — як runtime отримує той єдиний ключ, яким має працювати, разом із plaintext.
POST /internal/v1/credentials/resolve — це те, що runtime-и перекладу викликають перед кожною задачею: дай мені credential для користувача X і провайдера P. Це ендпоїнт сервісної площини, що вимагає scope provider-credentials.invoke (Service Plane Tokens) — і, разом із reveal, одне з лише двох місць, де plaintext взагалі покидає сервіс.
Запит
{
"user_id": "b6a4f6cd-…",
"org_id": "0d1e2f3a-…",
"provider_code": "deepl_api",
"purpose": "translation",
"allow_platform_fallback": true,
"correlation_id": "req-01J8…"
}
user_id та org_id мусять походити з провалідованого користувацького токена вашої власної площини — ніколи з клієнтського вводу. Членство тут навмисно не перевіряється повторно: надати достовірну пару — це половина контракту з боку того, хто викликає. org_id опційний; без нього рівень організації просто пропускається. purpose називає призначення, під яке резолвиться ключ, — translation, glossary або tag_fix; будь-яке інше значення — 400. correlation_id — ваш, їде в audit-стрічку й повертається в X-Correlation-ID.
Прохід
У межах політики credential_resolution провайдера (Vendors and Providers) сервіс іде фіксованим ланцюгом і повертає перший активний default, який знайде:
- USER — власний default користувача для цього провайдера.
- ORGANIZATION — коли
org_idприсутній і провайдер допускає цей рівень: default організації. (В audit — з причиноюUSER_NOT_CONFIGURED_ORG_SELECTED.) - PLATFORM — коли дозволяють і політика, і ваш
allow_platform_fallback: спільний platform-default.
Нічого не знайдено → 404 CREDENTIAL_NOT_CONFIGURED (провайдер існує; ключ ніхто не налаштував — це відмінне від 404 PROVIDER_NOT_FOUND). Disabled/removed провайдер → 409 PROVIDER_DISABLED. Кожне влучання і кожен промах записуються в audit-стрічку.
Відповідь
{
"credential_id": "…",
"provider_code": "deepl_api",
"credential_source": "organization",
"owner_type": "organization",
"owner_id": "0d1e2f3a-…",
"credentials": {"api_key": "the-actual-plaintext-key"},
"configuration": {},
"catalog_version": "2026.08.24",
"resolved_at": "2026-08-12T12:30:00Z"
}
credential_source каже, чий ключ ви тримаєте — покажіть це користувачеві («працює на ключі вашої організації»). Поводьтеся з credentials як із радіоактивними: використайте одразу, ніколи не зберігайте, ніколи не логуйте; відповідь приходить із Cache-Control: no-store.
Жодного fallback на runtime-помилки — так задумано
Якщо виданий ключ виявився зламаним на боці вендора (401, вичерпана квота), сервіс не дасть вам наступний рівень на повторі: резолюція залежить лише від збереженого стану, тож ви отримаєте той самий ключ знову. Покажіть збій тому, хто володіє ключем; не спалюйте мовчки чужу квоту. allow_platform_fallback: false існує для зворотної дисципліни — контрактів, що вимагають виключно клієнтських ключів.
Розібраний прохід end-to-end (влучання user → fallback на org → fallback на platform → промах): сценарій cookbook 06. Що UI має показати перед відправленням задачі: Credential Status.