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

GET /api/v1/companies/my — Просмотр своей компании

Операция чтения карточки компании (workspace) текущего пользователя: название, тип, статус, описание, реквизиты, настройки workspace. Основа экрана «Моя компания» ЛК застройщика/агентства/брокера/партнёра.

Назначение

Пользователь компании (агент, руководитель агентства, менеджер застройщика, сотрудник ПИН) открывает карточку своей организации. Owning-контекст — identity (дом полей — domain/company.md). Feature group — companies.

Metadata

ПолеЗначение
Сервис/контекстidentity
API areapublic
Feature groupcompanies
Статусdraft
Документdocs/06-services/identity/api/company-user/get-my-company.md

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

ПроверкаЗначение
Actor typeUser (пользователь с CompanyId != null; инвестор компании не имеет — 404)
Auth policy / Permissionsidentity.companies.view (domain/permission.md)
Scope (RBAC)организация: permission должен покрываться Active RoleAssignment со scope Platform или Organization(CompanyId)
Record-levelне применяется — доступ только к собственной компании (CompanyId из claims, id в route не принимается)
Tenant isolationTenantId = CompanyId из JWT claims (ADR-0052); интерсептор INullableTenantedEntity не применяется к companies (platform-level таблица), изоляция — выборкой строго по CompanyId актора
Auditnone (чтение не-sensitive данных своей организации)
Только своя компания

CompanyId берётся из claim tenant_id, а не из route/query — id чужой компании в запросе игнорируется, эндпоинт всегда возвращает карточку компании актора.

HTTP-контракт

ПолеЗначение
MethodGET
Route/api/v1/companies/my
Success status200
Idempotency headerне применяется (безопасный read)
Correlationсквозной trace через заголовок traceparent

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

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
UserIdidentity claims (sub)GuidДаRequired
CompanyIdidentity claims (tenant_id)GuidДаRequired; отсутствие claim (инвестор) → IDENTITY_COMPANY_NOT_FOUNDTenant isolation — id из route/query не принимается

Body отсутствует.

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

ПолеТипОбязательностьИсточникMaskingОписание
IdGuidДаCompanyEntity.IdИдентификатор компании.
Typestring (enum CompanyType)ДаCompanyEntity.TypeDeveloper / Agency / Broker / Partner / Pin.
Statusstring (enum CompanyStatus)ДаCompanyEntity.StatusPending / Active / Suspended / Archived.
NamestringДаCompanyEntity.NameОтображаемое название.
SlugstringДаCompanyEntity.SlugURL-адрес workspace.
Descriptionstring?НетCompanyEntity.DescriptionПубличное описание.
LogoFileIdGuid?НетCompanyEntity.LogoFileIdId файла логотипа во внешнем storage.
Websitestring?НетCompanyEntity.WebsiteСайт.
ContactEmailstring?НетCompanyEntity.ContactEmailПубличный email компании (не PII физлица).
ContactPhonestring?НетCompanyEntity.ContactPhoneПубличный телефон компании.
RequisitesCompanyRequisitesModelНетowned VO CompanyRequisitesЮрреквизиты (см. таблицу ниже).
WorkspaceSettingsCompanyWorkspaceSettingsModelДаjsonb CompanyWorkspaceSettingsDocumentНастройки workspace (см. ниже).
SyncSourcestring (enum CompanySyncSource)ДаCompanyEntity.SyncSourcePin / TalentIdentity — фронт по нему делает реплика-поля read-only (INV-5 company.md).
CreatedAtDateTimeOffsetДаCompanyEntity.CreatedAtДата создания.
VersionlongДаCompanyEntity.VersionДоменная версия (для optimistic UI).

CompanyRequisitesModel

ПолеТипОбязательностьИсточникMaskingОписание
LegalNamestring?НетRequisites.LegalNameЮридическое имя.
Innstring?НетRequisites.InnИНН (10/12 цифр).
Kppstring?НетRequisites.KppКПП.
Ogrnstring?НетRequisites.OgrnОГРН/ОГРНИП.
LegalAddressstring?НетRequisites.LegalAddressЮридический адрес.

CompanyWorkspaceSettingsModel

ПолеТипОбязательностьИсточникMaskingОписание
DefaultRoleIdGuid?Нетjsonb DefaultRoleIdРоль по умолчанию для приглашённых.
FixationVisibilitystring (enum FixationVisibilityMode)ДаjsonbOwnerOnly / OwnerAndManagers / WholeCompany.
AllowAgentSelfRegistrationboolДаjsonbРазрешена ли саморегистрация агентов.
NewsCategoriesEnabledIReadOnlyList<string>ДаjsonbКоды доступных категорий новостей.
LocalestringДаjsonbBCP-47, дефолт ru-RU.

Алгоритм

  1. Контекст и доступ. Операцию выполняет пользователь компании; CompanyId — из claim tenant_id; требуется право identity.companies.view в scope Organization(CompanyId) (алгоритм проверки — check-permission.md). У инвестора компании нет — отсутствие claim tenant_idIDENTITY_COMPANY_NOT_FOUND; отказ прав → FORBIDDEN.
  2. Что читаем. Карточку компании по CompanyId. Если компания не найдена или удалена → IDENTITY_COMPANY_NOT_FOUND. Других агрегатов не читаем.
  3. Маппинг. Поле-в-поле по таблице модели ответа: скаляры — из CompanyEntity, Requisites — из owned VO, WorkspaceSettings — из jsonb-документа CompanyWorkspaceSettingsDocument (при версии документа старше текущей недостающие поля дозаполняются дефолтами, company.md «Правила версии»).
  4. Результат. Карточка компании (200). Маскирование не требуется (PII физлиц нет). Актуальность — read-your-writes из основной БД (без реплик).

Диаграмма

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
IDENTITY_COMPANY_NOT_FOUND404Claim tenant_id отсутствует (инвестор) или компания не найдена/архивирована«Компания не найдена»no retry
FORBIDDEN403Нет identity.companies.view в покрывающем scope«Недостаточно прав»no retry
UNAUTHORIZED401Нет/просрочен access-токенretry после refresh-token

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

  • Новые optional поля ответа — additive; удаление/переименование/смена типа — breaking (migration + rollout).
  • Logs: CompanyId, UserId, результат (без тела); metrics: identity_company_get_total{result}; traces: OTel, сквозной traceparent. Dashboard — identity-overview.

Acceptance Criteria

  • Given пользователь компании с identity.companies.view и живой claim tenant_id, When GET /companies/my, Then 200 с карточкой своей компании; реквизиты и WorkspaceSettings заполнены (при отсутствии в источнике — null/дефолты); SyncSource отражает источник (по нему UI делает реплика-поля read-only).
  • Given у актора нет claim tenant_id (инвестор), When GET /companies/my, Then IDENTITY_COMPANY_NOT_FOUND (404).
  • Given актор аутентифицирован, но без identity.companies.view в покрывающем scope, When GET /companies/my, Then FORBIDDEN (403).
  • Given компания актора удалена/архивирована, When GET /companies/my, Then IDENTITY_COMPANY_NOT_FOUND (404) — состояние архива неотличимо от отсутствия для пользователя.
  • Given только что через update-my-company изменено Name, When тот же пользователь читает карточку, Then возвращается новое Name (чтение из основной БД, без реплик).
  • Given в запросе присутствует id чужой компании в route/query, When GET, Then id игнорируется — возвращается только компания из claim tenant_id.

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

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

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