Credentials
NOTE
Статус: Live (HEAD
5e4ce54, 2026-05-06). BC закрыт в P4c-2 (Credentials PG migration, ADR-0041, CLOSED 2026-04-27). Cabinet customer-flow добавлен 2026-05-06.
System и customer credentials для поставщиков: PG-backed pool, scope-resolver, secrets isolation, admin CRUD, customer self-service.
Назначение
Заменить env-seeded StubRouter полнофункциональным пулом credentials с тремя scope’ами:
- system — общие credentials платформы для не-customer-specific операций (catalog sync, общий refresh).
- customer — учётные записи конкретного клиента, используются в его proposal’ах + system-for-customer операциях (PriceRefresh для X).
- diagnostic — не реализован; задел для платформенных пробников.
Pool отвечает за выбор credential’а под intent + supplier + customer (если есть), учитывает rate-limits и health.
Статус документа
- Тип знания:
current service - Статус реализации: PG-backed pool live, secrets isolated в отдельной таблице, admin CRUD + customer self-service CRUD оба работают, seed CLI готов.
- Текущее место кода:
backend/internal/core/credentials/{api,app,domain,infra},backend/cmd/seed-credentials/. - Что читать дальше:
../../20-architecture/adr/0041-credentials-pool-and-secrets-isolation.md,../../20-architecture/adr/0009-multi-tenant-supplier-credentials.md,../../20-architecture/adr/0010-pluggable-credential-schemas.md,../../20-architecture/adr/0018-master-key-and-dek-rotation.md.
Область действия
Входит:
Pool.Pick(PickRequest)— выбор credential под(intent, supplierRef, customerID, briefing).- Health-tracking (last_check_at, consecutive_errors → blocked status).
- Rate-limiter integration (token bucket per credential).
- Admin CRUD
/api/v1/admin/credentials/*+ customer CRUD/api/v1/credentials/*. - Seed CLI (
cmd/seed-credentials) для bootstrap’а system credentials из.env. - Secret-resolver — отдельный port
SecretsRepositoryдля secret payload (изолирован от метаданных).
Не входит:
- Vault migration (P4c-2 deferred — задел для Phase 7).
- Pluggable auth-schemas в БД (на 2026-05-06 — Go-const enum в supplier_catalog).
- Transient credential health probing — отложено.
Публичный контракт
Вход
HTTP (admin):
GET /api/v1/admin/credentials(list with filters)GET /api/v1/admin/credentials/{id}POST /api/v1/admin/credentialsPUT /api/v1/admin/credentials/{id}(metadata, optimistic concurrency)PATCH /api/v1/admin/credentials/{id}/secret(rotate)PATCH /api/v1/admin/credentials/{id}/status(transitions)POST /api/v1/admin/credentials/{id}/reset-healthDELETE /api/v1/admin/credentials/{id}(only if revoked)
HTTP (customer):
GET /api/v1/credentials(own, list)GET /api/v1/credentials/{id}POST /api/v1/credentials(create with supplier from catalog)PATCH /api/v1/credentials/{id}/secret(rotate)PATCH /api/v1/credentials/{id}/status(active ↔ inactive)
Internal Go API:
Pool.Pick(ctx, PickRequest)— для consumer-BC (ingestion, search/proposal).SecretsRepository.Get(ctx, credID)— JSON secret payload.RegisterClient— composition root для api/http handler (используется и cabinet’ом).
Выход
- Outbox events
credentials.{created,rotated,revoked,health_changed}.v1.
Внутренняя архитектура
domain/credential.go—Credentialaggregate + status state-machine.domain/pool.go—Poolport +PickRequestsemantics.domain/scope_resolver.go— кастомер-vs-system выбор по intent.domain/auth_schema.go— типы (basic/api_token/master_key).domain/rate_limit.go— token-bucket helpers.domain/repository.go— Repo + SecretsRepository ports.app/— services (Create / Rotate / Revoke / etc).infra/pg/— Repo (metadata) + SecretsRepository (отдельная таблицаcredential_secret).api/http/— admin + customer handlers (один файл, два basePath).
Зависимости
- PostgreSQL — основное хранилище.
- outbox — публикация событий.
Хранилище
| Таблица | Назначение |
|---|---|
credential | Метаданные (supplier_ref, scope, status, rate_limit, allowed_usages, customer_id) |
credential_secret | Шифрованный JSON-payload (отдельная таблица — secrets isolation) |
credential_health_log | История health-checks |
Конфигурация
| Env var | Default | Описание |
|---|---|---|
CREDENTIALS_DEK | — | base64-encoded data encryption key (32 bytes); ротация см. ADR-0018 |
CREDENTIALS_HEALTH_BLOCK_THRESHOLD | 5 | consecutive_errors → block |
CREDENTIALS_RATE_LIMIT_DEFAULT_RPM | 60 | fallback rpm если нет в supplier_catalog |
Тестирование
- Unit + integration:
go test ./internal/core/credentials/...+-tags=integration. - Seed CLI:
cd backend && go run ./cmd/seed-credentials --dry-run. - Live curl-verify: см.
tracium_curl_live_verifymemory.
Наблюдаемость
- Metrics:
credentials_pick_total{outcome},credentials_health_status{credential_id},credentials_pool_exhausted_total{supplier}. - Phase logs:
credentials.health_check.phase.
Открытые вопросы / TODO
- Vault migration (P4c-2 deferred) — переезд secret payload из PG в Vault/HashiCorp Vault.
- Test-connection кнопка для customer credentials (cabinet UI).
- Pluggable auth-schemas в БД — для proprietary tokens новых поставщиков без релиза backend’а.
Связанные документы
- Cabinet UI:
../cabinet/README.md. - Ingestion (consumer):
../ingestion/README.md. - Memory:
tracium_credentials_model.md,tracium_p4c2_execution.md.