Перейти к основному содержимому

GET /api/admin/v1/model-config — Чтение платформенной экономической модели (admin)

Назначение

Отдаёт администратору платформы платформенную экономическую модель доходности — singleton-агрегат EconomicModelConfig для таба «Глобальный дефолт». Возвращает все девять коэффициентов, текущую ревизию (Version) и штампы последней правки (кто и когда менял модель); ревизия нужна как expectedVersion при сохранении. Доступ — только администратор платформы через admin API (ADR-0053).

Metadata

ПолеЗначение
Сервис/контекстinvest-analytics
API areaadmin (ADR-0053)
Feature groupadmin-economic-model
Статусdraft
Документdocs/06-services/invest-analytics/api/admin/get-model-config.md

Актор и доступ

ПроверкаЗначение
Actor typeOperator(Admin) — администратор платформы (доступ через admin API, m2m client-credentials)
Auth policy / Permissionspolicy AdminSystemOnly (клиент pin-admin-system); каталожное соответствие — permission invest-analytics.model-config.view (docs/06-services/identity/domain/permissions.md; для admin API каталог permissions справочный, ADR-0053)
Scope (RBAC)платформа
Tenant isolationне применяется — конфигурация не tenanted (ADR-0052 п.3)
Auditread: не аудируется (несекретная конфигурация, PII нет); наружу за пределы admin API модель не раскрывается

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/admin/v1/model-config
Success status200
Idempotency headerне применяется (safe GET)
Correlationсквозной trace через traceparent; X-Admin-User-Id (Guid администратора) — обязательный заголовок admin-области

Входные данные / параметры запроса

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
AdminUserIdheader X-Admin-User-IdGuidДа!= Guid.Emptyконтекст admin-области (в лог)

Параметров запроса нет — singleton читается целиком.

Модель ответа ModelConfigResult

Проекция полей дома economic-model-config.md один-в-один (семантика/единицы/диапазоны — там):

ПолеТипОбязательностьИсточникMaskingОписание
marketPremiumdecimalДаEconomicModelConfig.MarketPremiumНадбавка к прайсу, доля.
priceGrowthMonthlydecimalДа.PriceGrowthMonthlyМесячный рост цены м², доля.
dailyRentM2decimalДа.DailyRentM2Аренда, руб/м²/сутки.
rentGrowthMonthlydecimalДа.RentGrowthMonthlyМесячный рост аренды, доля.
expenseSharedecimalДа.ExpenseShareДоля расходов от выручки.
appreciationTaxMonthlydecimalДа.AppreciationTaxMonthlyЛегаси-поле (совместимость admin UI; в расчёте не участвует).
ebitdaTaxMonthlydecimalДа.EbitdaTaxMonthlyЛегаси-поле.
occupancydecimalДа.OccupancyЗаполняемость, доля.
horizonMonthsintДа.HorizonMonthsГоризонт прогноза, мес.
versionlongДа.Version (0, если строки нет — отданы дефолты кода)Ревизия модели; используется как expectedVersion при PUT.
updatedAtDateTimeOffset?Нет.UpdatedAt; null при дефолтах кодаДата последнего изменения (показывается в админке).
updatedByUserIdGuid?Нет.UpdatedByUserIdКто последним менял (Guid администратора из X-Admin-User-Id записи).

Алгоритм

  1. Контекст и доступ. Операцию выполняет администратор платформы через admin API (policy AdminSystemOnly); scope — платформа; требуется право invest-analytics.model-config.view. Обязателен заголовок X-Admin-User-Id.
  2. Проверка входа. X-Admin-User-Id должен быть непустым, иначе — ValidationError. Параметров запроса нет: singleton читается целиком, отсутствие строки — не ошибка (см. шаг 4).
  3. Что читаем. Платформенную модель EconomicModelConfig по её well-known-идентификатору. Отсутствие строки допустимо: seed-настройка её создаёт, но до её применения ответ строится из дефолтов кода.
  4. Правила и маппинг. Если строка есть — все поля ответа берутся из агрегата. Если строки нет — ответ формируется из дефолтов кода (таблица дефолтов — economic-model-config.md) с version = 0, updatedAt = null, updatedByUserId = null.
  5. Результат. Возвращаются девять коэффициентов, ревизия и штампы правки. Консистентность — read-your-writes в рамках PostgreSQL: после сохранения (PUT) администратор сразу видит новую ревизию.

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
ValidationError400Отсутствует/пустой X-Admin-User-IdОшибка валидации запросаno retry
FORBIDDEN403Клиент не pin-admin-system / нет policyДоступ запрещёнno retry

Отсутствие строки в БД — не ошибка: 200 с дефолтами кода и version = 0.

Совместимость и наблюдаемость

  • Additive-поля ответа — без breaking; удаление/переименование — breaking. Легаси-поля appreciationTaxMonthly/ebitdaTaxMonthly не удалять до deprecation-решения.
  • Logs: admin-model-config-read (adminUserId, version). Metrics: invest_analytics_admin_operations_total{operation="get-model-config"}. Traces — сквозной trace через traceparent.

Acceptance Criteria

  • Given seed применён и модель сохранена (Version = 3), When администратор шлёт GET с валидным X-Admin-User-Id, Then 200 с девятью коэффициентами, version = 3, updatedAt/updatedByUserId последней правки.
  • Given строки модели в БД нет (seed не применён), When GET, Then 200 с дефолтами кода, version = 0, updatedAt = null, updatedByUserId = nullне ошибка.
  • Given администратор только что выполнил PUT (ревизия n → n+1), When сразу шлёт GET, Then version = n+1 (read-your-writes в рамках PostgreSQL).
  • Given заголовок X-Admin-User-Id отсутствует или пуст, When GET, Then 400 ValidationError.
  • Given клиент не pin-admin-system (нет policy AdminSystemOnly), When GET, Then 403 FORBIDDEN; модель наружу не раскрывается.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы