iac/docs/architecture/app-docs.md

298 lines
154 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Описания компонентов прикладного слоя
Источник поля `Documentation` у элементов `ApplicationComponent` в модели ArchiMate. Заголовок второго уровня — имя каталога в `apps/` либо идентификатор элемента для компонентов, которых в `apps/` нет.
Каждое описание построено на анализе исходного кода компонентных репозиториев: первый абзац — стек и репозитории, второй — назначение и место в продукте, третий — реализация и связи. Там, где доказательств в коде недостаточно, это отмечено явно.
Конкретные домены заменены на `<домен>` — файл коммитится в репозиторий и не должен содержать данных инсталляции.
## attachments
Репозитории: pdm/attachments — REST-сервис хранения и выдачи файловых вложений. Стек: Python, FastAPI, Pydantic, PostgreSQL (psycopg2 + пул соединений, сырой SQL), SQLAlchemy/Alembic для схемы и миграций, S3 через boto3 (presigned URL), OpenTelemetry, JSON-логирование.
Компонент отвечает за универсальные вложения к произвольным сущностям платформы: пользователь прикрепляет файл — фото с объекта, скан, приложение к документу — к записи любого типа, а сервис хранит сам файл в объектном хранилище, а метаданные о нём в реляционной БД. Модель `Attachment` содержит `name`, `company_id` (мультиарендность), `model_name` — имя сущности-владельца, `instance_id`/`instance_uid` — ссылку на конкретный экземпляр, `author_id`, а также имена объектов в S3 для оригинала и превью. Полиморфная привязка «`model_name` + `instance_id`» позволяет использовать один сервис для вложений к замечаниям, документам, задачам и другим объектам, не заводя отдельных таблиц под каждый домен. В жизненном цикле проекта компонент задействован прежде всего на этапах полевой работы и согласований, когда к записи нужно приложить подтверждающие материалы. Выдача файлов идёт по временным ссылкам: клиент скачивает содержимое напрямую из хранилища, минуя сервис.
Реализация следует слоистой структуре в Go-подобной раскладке каталогов: `cmd/app` создаёт приложение, `internal/controller/http/v1` содержит роутер, `internal/service` — прикладную логику, `internal/repository` — доступ к БД, а `internal/usecase/interfaces.py` описывает протоколы `RepositoryInterface` и `S3ClientInterface`, внедряемые через `Depends`. HTTP-контракт включает загрузку файла (`UploadFile` с промежуточной записью во временный файл и выгрузкой в S3), выборку списка с фильтрами, получение одной записи и удаление; ссылки на скачивание формируются функцией `create_presigned_url`. Репозиторий работает не через ORM, а сырыми SQL-запросами psycopg2 с `RealDictCursor` поверх пула соединений — SQLAlchemy-модели нужны лишь как источник метаданных для Alembic. Приложение инструментировано трассировкой OpenTelemetry. Не подтверждён механизм генерации превью: поле `thumbnail_object_name` в модели есть, кода его формирования в репозитории нет.
## auth-flow
Репозитории: platform/auth-flow-frontend — SPA-обработчик OIDC-редиректов (login / callback / logout / error); platform/frontend/core/auth — модуль авторизации микрофронтенд-ядра; infra/zitadel-auth-proxy — Helm-чарт oauth2-proxy; infra/oauth2-facade — сервис-фасад OAuth2 (в репозитории только точка входа и конфиг). Стек: TypeScript, React, Webpack 5, внутренний `sdk-js` и его модуль `zitadel` поверх oidc-client, Zitadel как OIDC-провайдер, Authorization Code flow; в инфраструктуре — oauth2-proxy, Kubernetes/Helm.
Компонент реализует вход пользователя в платформу и поддержание сессии: страницы `/login`, `/logout`, `/auth/callback` и `/auth/error` образуют изолированный маршрут авторизации, через который проходит любой пользователь перед доступом к проектам, документам и моделям. Конфигурация OIDC не зашита в сборку, а читается из localStorage (`AUTHORITY`, `CLIENT_ID`), что позволяет одному бандлу обслуживать разные контуры и разных заказчиков; при отсутствии этих значений приложение падает с явной ошибкой. Запрашиваемые скоупы — `openid profile email offline_access urn:zitadel:iam:user:metadata`, то есть вместе с профилем подтягиваются пользовательские метаданные Zitadel (принадлежность к организации), на которых далее строится авторизация в доменных сервисах. Отдельно проработан сценарий ошибки: параметры разбираются из query и показывается страница с возможностью скопировать диагностический текст. Компонент не хранит бизнес-данных и не участвует в жизненном цикле проекта напрямую — он является входной точкой ко всем остальным приложениям.
Технически это отдельный SPA-микрофронтенд: `App.tsx` маршрутизирует по `window.location.pathname` без react-router, в проде разрешены лишь `/auth/callback` и `/auth/error`, любой другой путь принудительно переписывается в callback через `history.replaceState`. На странице callback вызывается `zitadel.userManager.signinCallback()`, полученный `User` сохраняется утилитой `setTokensInfo`, а токены транслируются в host-приложение через оконные события — это и есть механизм интеграции с оболочкой микрофронтенда; для выхода используется отдельный ключ в storage и идентификатор вкладки. Фоновое обновление токенов сознательно отключено (`automaticSilentRenew: false`). Модуль `platform/frontend/core/auth` — вторая, «ядровая» реализация: класс `Auth` с MobX-состоянием, монтируемый в оболочку. На стороне инфраструктуры доступ к сервисам может дополнительно закрываться oauth2-proxy с прокидыванием access-токена. Серверная часть авторизации подтверждена лишь фрагментарно: `oauth2-facade` содержит только точку входа и конфиг, а выпуск и валидация токенов выполняются во внешнем Zitadel.
## bim
Репозитории: platform/bim-backend-v2 — основной Go-сервис BIM-моделей, элементов, свойств и статусов; aero/bimbackend — предыдущее поколение того же домена на Flask/Celery (сравнения, слияние, архивация, оптимизация мешей); platform/bim-api-metadata-inserter-v4 — batch-джоб загрузки метаданных сконвертированной модели в БД. Стек: Go (go-pg, gorilla/mux, validator, zap, Prometheus), PostgreSQL с шардированием по нескольким инстансам, партиционированием таблиц элементов и материализованными представлениями; Python (Flask, peewee, Celery, PostgreSQL ltree, boto3/S3, JWT).
Компонент — ядро работы с информационными моделями здания: он хранит перечень BIM-моделей проекта, дерево их элементов, свойства элементов и статусную модель, по которой ведётся учёт хода строительства. Ключевые сущности — `bim` (модель, привязанная к проекту, документу и компании, с трансформацией и статусной моделью), `bim_element` (элемент с иерархией и категорией), таблицы свойств (строковых, числовых, логических), история изменений и корпоративный шаблон статусов `company_status_model`. Статусная модель по умолчанию — категория «Строительство» со статусами «Неопределённый», «Не приступали», «В работе», «Готово», «Отклонение», у каждого свой цвет и разрешённые переходы: это напрямую питает раскраску модели во вьюере и отчётность о проценте готовности. Пользователь получает по API дерево элементов, фильтрует их по статусам и свойствам, выгружает свойства в CSV, назначает статусы и настраивает собственные статусные модели на уровне компании. Более раннее поколение дополнительно закрывает сопоставление проектной модели с данными обмеров: задачи сравнения, расчёт отклонений, слияние моделей, откат изменений, архивирование.
Архитектурно bim-backend-v2 построен по слоям cmd → config → controller/http/v1 → usecase → entity: отдельные бинарники HTTP-сервера и миграций, роутеры `bim`, `bim_internal` и `company_status_model`, на каждый эндпоинт свой файл с юнит-тестами и сгенерированными моками. Публичный контур отделён от служебного `bim_internal` (создание модели, синхронизация свойств, выборка элементов по статусу), предназначенного для межсервисных вызовов. Данные распределены по нескольким кластерам Postgres: конфиг задаёт до трёх наборов реквизитов подключения плюс границы диапазонов id, по которым выбирается инстанс; подключение к БД идёт по TLS, есть отдельная схема v3 и интеграция с legacy-контуром Django. Metadata-inserter — не сервис, а джоб: он читает описание входов и параметров из окружения, скачивает из объектного хранилища файлы метаданных и свойств (msgpack + gzip), нормализует типы параметров Revit, создаёт партиции под модель, пакетно вставляет элементы и свойства в транзакции, обновляет агрегаты модели и пересобирает материализованное представление, после чего переводит статус модели из `Pending` в `OK`. Точная граница ответственности между v2 и aero/bimbackend в текущем проде по коду не устанавливается — обе кодовые базы живые.
## ac-bim-converter
Репозитории: algorithms/ifc_converter — Python-ядро конвертации IFC в glTF и извлечения свойств; algorithms/ifc-converter-job — Go-обёртка, запускающая ядро как job; pdm/nwd-converter — Go-воркер RPC поверх RabbitMQ, конвертирующий файлы Autodesk в формат `.s3d`; platform/nwd-gltf-converter — .NET-плагин к Autodesk Navisworks; platform/bim-converter — пустой репозиторий. Стек: Python + ifcopenshell, NumPy; Go (envconfig, validator, resty, zap), RabbitMQ, S3, Docker; C#/.NET с Autodesk.Navisworks.Api и SharpGLTF; целевые форматы — glTF/GLB, `.s3d`, JSON-файлы свойств.
Компонент отвечает за подготовку исходных проектных моделей к просмотру и анализу в платформе: пользователь загружает файл в САПР-формате (IFC, NWD/Navisworks и другие форматы Autodesk), а конвертер превращает его в облегчённое геометрическое представление для веб-вьюера и в машинно-читаемый набор свойств и категорий элементов. Помимо геометрии извлекаются данные экземпляров и категорий, материалы и матрицы размещения, то есть на выходе получается не «картинка», а структурированная модель, пригодная для дерева элементов, фильтров и назначения статусов. Именно эти артефакты далее загружает metadata-inserter в базу BIM, поэтому конвертер является обязательным звеном между загрузкой документа в CDE и появлением работоспособной модели в интерфейсе. В жизненном цикле проекта компонент срабатывает при каждой публикации новой версии модели, а также при повторной обработке уже загруженных файлов.
Реализация распадается на два типа исполнителей. Первый — эфемерный джоб: `ifc-converter-job` получает описания входов, выходов и параметров JSON-структурами в переменных окружения, валидирует их, скачивает исходный IFC из объектного хранилища, запускает встроенный Python-код и выгружает результат обратно; само ядро на Python собирает glTF вручную — формирует JSON-структуру сцены, пишет бинарные буферы, принимает геометрию из итератора ifcopenshell, сохраняет свойства в JSON и упаковывает результат в zip. Второй тип — постоянный воркер: `nwd-converter` поднимает RPC поверх RabbitMQ (консьюмеры `input` и `cancel`), принимает сообщение с bucket/key входа и выхода, параметрами Navisworks, метаданными (компания, документ, комплект) и идентификаторами задачи оркестрации, скачивает файл, вызывает консольный конвертер через `os/exec` с разбором кодов ошибок, выгружает `.s3d` и возвращает статус со временем выполнения. `nwd-gltf-converter` — плагин, устанавливаемый в каталог Plugins Autodesk Navisworks Manage; в репозитории лежат преимущественно скомпилированные сборки, исходных файлов поиск не находит. Репозиторий `platform/bim-converter` пуст, поэтому будущая консолидированная реализация неизвестна.
## cde
Репозитории: pdm/cde-api — основной Go-сервис среды общих данных (документы, версии, комплекты, права, штампы, подписи, публичные ссылки); platform/cde-orchestration-demo — оркестратор процессов CDE на Camunda 8/Zeebe с набором воркеров; generic/cde-v2-write-service — пустой репозиторий. Стек: Go (go-pg, Fiber, zeebe-client, OpenTelemetry), PostgreSQL, S3/MinIO, Apache Kafka (transactional outbox + outbox-relay), Valkey/Redis для кеша прав, RabbitMQ в оркестраторе, Camunda 8 и BPMN, AsyncAPI для контрактов событий, Helm/Kubernetes.
Компонент реализует среду общих данных (Common Data Environment) — центральное хранилище проектной документации с версионированием, правами доступа и регламентом согласования. Модель данных, восстановленная по миграциям, включает проект, «диск» (пространство компании), документ с типами, версиями и связями, комплект (bundle) с атрибутами, датами и признаками маркировки, файл-источник, постраничное представление, состояние многочастной загрузки, права, workflow, штамп со схемой позиционирования, QR-метку, электронную подпись, публичную ссылку с автоудалением, события разметки и changelog. Это покрывает полный документооборот стройки: загрузку чертежей и разделов, сборку комплектов, простановку штампов «В производство работ», QR-кодов и ЭЦП, выдачу публичных ссылок подрядчикам, фиксацию замечаний и истории изменений. Отдельно решается задача вывода из эксплуатации legacy-сервисов: мутирующие запросы `documentation-api` и `documentation-api-v2` проксируются в cde-api, чтобы бизнес-логика и публикация событий выполнялись в одном месте.
cde-api построен на чистой архитектуре с явным разделением слоёв: бизнес-логика в сущностях, usecase управляет транзакциями через Unit of Work, write-репозитории работают в рамках одной транзакции, read-репозитории держат отдельный пул и допускают параллельные выборки; эндпоинты сегментированы по потребителям — `app` (фронтенд), `internal` (межсервисные), `external` (внешние интеграции) и `public` (без авторизации). Событийная интеграция реализована строго по паттерну transactional outbox: сервис не содержит Kafka-продюсера, а пишет строку в таблицу `outbox` в той же транзакции, что и бизнес-запись; воркер relay собирает конверт «metadata + payload» с идентификатором, типом, временем и трассировкой события и публикует по одному топику на тип (`documents.document.created.v1`, `documents.bundle.uploaded.v1` и др.), проставляя заголовок арендатора; гарантии — at-least-once с идемпотентностью потребителя, контракты обязательны к описанию в AsyncAPI. В состав входят также бинарники миграций и файлового стрима и собственный пакет клиента Zeebe с воркерами на типы BPMN service task, пробросом трассировки из переменных процесса и продлением аренды задачи. Оркестратор — исполнительная часть процессов: отдельные воркеры копирования, создания версий, разметки, подписи, разбиения PDF и обновления комплектов плюс HTTP-сервер и адаптеры к pdm, bim, flows и system-log.
## checklists
Репозитории: proc/checklists-backend — HTTP-сервис чек-листов и результатов их заполнения. Отдельный фронтенд-репозиторий не найден. Стек: Python, FastAPI, Pydantic v2, Piccolo ORM + Piccolo Admin (русская локаль), PostgreSQL (JSONB), OpenTelemetry, JWT-аутентификация собственным middleware.
Компонент реализует функцию типовых чек-листов (шаблонов проверок) и фиксации результатов их прохождения. Администратор создаёт чек-лист, состоящий из упорядоченных шагов, каждый из которых содержит элементы ввода. Элементы ввода типизированы ограничениями — строковые и выбор из вариантов с привязкой цвета к варианту, что позволяет строить цветовую индикацию результата. Исполнитель на объекте заполняет чек-лист, и создаётся результат, привязанный к произвольной сущности платформы через пару `entity_type` / `entity_id` — то есть чек-лист может навешиваться на любой объект: замечание, работу, актив, согласование. Все сущности мультиарендные: фильтрация и проверки прав идут по `company_id`. Результаты поддерживают блокировку — фиксацию после согласования; блокировку инициирует не пользователь, а смежный сервис.
Архитектура слоистая: контроллеры HTTP (публичный `/api/v1` и служебный `/internal/api/v1`) → сервисный слой → модели Piccolo. Публичные роутеры — `/checklists` и `/results` с пагинацией limit/offset, сортировкой и фильтрами. Внутренний API содержит только `/results`, включая массовую операцию блокировки, которую вызывает сервис согласований flows (`PATCH /internal/v1/results/lock`). Аутентификация — middleware, декодирующий JWT и наполняющий контекст пользователя, откуда берутся `company_id` и автор записи. Конкурентный доступ решён через `SELECT ... FOR UPDATE` на уровне Piccolo. Данные хранятся в PostgreSQL, миграции ведутся с июня 2025 по март 2026, поля включают JSONB — снимок структуры шагов и элементов ввода в результате, что фиксирует состав проверки на момент её прохождения. Поверх БД поднята админка Piccolo Admin для ручного управления. Внешних брокеров, S3 или gRPC в коде не обнаружено.
## comparisons
Репозитории: pdm/comparisons-backend — исходный Go-сервис сравнений; pdm/comparisons-api-v2 — переписанная на Fiber версия с чистой архитектурой; platform/comparisons-frontend — микрофронтенд UI сравнений; platform/bim-2-bim-comparisons-frontend — фактически пуст. Стек: Go (go-pg, Fiber, validator), PostgreSQL; TypeScript, React, MobX, Material-UI, Webpack Module Federation, внутренние `sdk-js` и `ui-kit`, локализация en / zh-CN; Docker-образы задач в реестре контейнеров.
Компонент отвечает за сравнение проектных данных между собой и выявление изменений и отклонений. Поддерживаются несколько типов сравнений, видимых и в коде, и в иконках интерфейса: `c2c` (облако точек к облаку), `c2s` (облако к модели/поверхности), `abap`, `pdf2pdf` (сравнение PDF-чертежей), `deviation` (отклонения) и `bim2bim` в версии v2. Пользователь выбирает диск и документы-источники, задаёт параметры и допуск (tolerance), запускает сравнение и затем видит список сравнений со статусом выполняющегося процесса. Результат раскладывается на элементы и изменения, которые можно фильтровать по набору полей и редактировать — то есть инженер верифицирует найденные расхождения, а не просто получает отчёт. Сравнения удаляются мягко, что подтверждается отдельной миграцией. Сценарий применяется при контроле соответствия построенного проекту и при отслеживании изменений между версиями документации.
Бэкенд v1 — Go-сервис с бинарниками API и миграций, таблицами `comparisons`, `elements`, `changes`, `deviation_element`. Каждый тип сравнения оформлен как отдельный пакет с единым набором шагов: проверка прав → создание документа → создание модели → создание workflow, то есть тяжёлые вычисления делегируются внешнему оркестратору, а результат возвращается через эндпоинт `webhook`. Интеграции реализованы клиентами к сервису документации (включая имя бакета), к сервису workflow (запуск и статус по типам сравнения) и к рабочим пространствам. Версия v2 построена на Fiber со слоями контроллеры → usecases → services → репозитории, с JWT-middleware; её ключевое отличие — пакет, который прямо в коде собирает DAG задач (slug, docker-образ, входы, требования к ресурсам, связи `needs`), например импорт в bim-api с последующей сборкой облака. Фронтенд — модуль микрофронтенда с MVVM на MobX: слой репозиториев (типы, диски, документы, сравнения, workflow), слой view-model и usecase удаления; хосты бэкендов резолвятся через общий SDK, интеграция с общей панелью документов платформы выполнена переиспользуемым компонентом. Какая из версий бэкенда сейчас в проде, по коду не определяется.
## contracts
Репозитории: platform/contracts — бэкенд договоров; platform/contracts-frontend — интерфейс договоров. Стек: Go, Fiber v3, pgx/v5 + pgxpool, squirrel, ULID, SQL-миграции, PostgreSQL (управляемый, с TLS), Helm + GitLab CI на стенды stage/preprod/prod; TypeScript, React, MobX, Feature-Sliced Design с контролем границ слоёв через eslint, внутренний `sdk-js`.
Компонент ведёт реестр договоров (контрактов) компании и связанных с ними подрядчиков. Договор описывается номером, подрядчиком, датой начала и крайним сроком, стоимостью и текстовым описанием и может быть привязан к ресурсу платформы — объекту или проекту. Это даёт коммерческий контур поверх производственных данных: подрядчик, срок и стоимость становятся атрибутами, к которым можно привязывать факт выполнения работ; на договор, в частности, ссылается предписание. На фронтенде пользователь работает со списком договоров, выбирает подрядчиков и компанию, причём текущая компания хранится в localStorage и отслеживается отдельным хуком, что типично для мультикомпанийной платформы. Компонент относительно молодой: одна первичная миграция и API версии `v0`.
Бэкенд реализован по чистой архитектуре: бинарники HTTP-сервера и CLI → приложение → контроллер `v0` с маршрутами создания, списка, получения по id, обновления и удаления → сервис → usecase → репозиторий PostgreSQL. Идентификатор договора — ULID, хранится строкой. Схема: таблица `contracts` с номером, `tenant_id`, `resource_id` (UUID), подрядчиком в JSONB, датами, стоимостью `DECIMAL(19,4)`, описанием и таймстампами, индексы по арендатору, ресурсу и номеру, триггер обновления `updated_at`, мягкое удаление. Мультиарендность реализована через `tenant_id` и middleware проверки принадлежности пользователя компании поверх JWT. Запросы частично константный SQL, частично конструктор squirrel для фильтров. Деплой — Helm-чарт в неймспейсы по стендам, ingress-префикс `/contracts/api/` на соответствующих доменах API. Фронтенд построен по FSD с жёстким контролем границ слоёв; в слое `entities` — договоры, подрядчики и компании, каждая со связкой store + repository + adapter, причём тип DTO в адаптерах компаний и подрядчиков указывает, что часть справочных данных берётся из Django-монолита, а не из Go-сервиса договоров.
## control-interface
Репозитории: platform/srx-admin. Прямого репозитория с именем `control-interface` в инстансе нет; соответствие установлено по коду: srx-admin деплоится в неймспейсы `control-interface-stage / -preprod / -prod`, а его модули публикуются по путям `modules.<домен>/control-interface/modules/admin/remoteEntry.js` и `.../modules/assets/remoteEntry.js`, которые зарегистрированы в шелле generic/sarex-frontend как модули `administration` и `assets`. Стек: TypeScript, React, MobX, Material-UI и собственный `ui-kit`, Webpack 5 Module Federation, монорепозиторий npm-workspaces (`services/*` + `packages/app-kit`), FSD-слои, внутренний `sdk-js`, Helm + GitLab CI.
Функционально это административный контур платформы — интерфейс управления. Модуль `admin` даёт разделы «Пользователи», «Атрибуты», «Роли», «Места работы», «Проекты» и «Функциональные группы»; каждый раздел доступен по отдельному признаку прав, и пользователь при входе перенаправляется на первый доступный ему раздел. Модуль `assets` управляет реестром активов компании: деревом активов, правами доступа к ресурсам и массовыми действиями над выбранными активами. Отдельный крупный сценарий — пакетный импорт активов из XLSX: пользователь выбирает проект и файл (до 400 МБ, только `.xlsx`), система создаёт задание импорта и показывает таблицу заданий со статусами, счётчиками ошибок и предупреждений и ссылками на файлы с их расшифровкой. Таким образом компонент — точка входа администратора компании в справочники, оргструктуру, права и наполнение реестра активов.
Технически это микрофронтенд-монорепозиторий: два независимо собираемых и публикуемых remote-модуля и общая библиотека `app-kit` с переиспользуемыми сущностями, фичами динамических селектов по атрибутам, отделам, группам и правам и общими типами. Модули подключаются в шелл по URL `remoteEntry.js`, при этом конфиг эндпоинтов содержит варианты для stage, preprod, prod и закрытого контура с относительными путями. Состояние — MobX-сторы уровня фичи и виджета с пагинацией limit/offset и фильтрами по статусу и проекту. Работа с API идёт через слой `shared/api` поверх общего `httpService`; импорт актива отправляется как `multipart/form-data` с полями файла, организации, автора и ресурса, а скачивание шаблона XLSX разбирает заголовок `Content-Disposition`. Контекст текущей компании и пользователя приходит из шелла, права — из контекста администрирования. Собственного хранилища у компонента нет: это презентационный слой над бэкендами платформы. Не установлено, входят ли в тот же ArchiMate-компонент другие приложения, деплоящиеся в неймспейсы `control-interface-*`.
## cross-section
Репозитории: aero/cross-section — фронтенд-модуль построения сечений в 3D-вьюере (деплоится как статика); aero/cross-secttions-to-dwg-job — Go-джоб экспорта сечения в DWG. API сечений обслуживает aero/drawings-api. Стек: TypeScript, React, MobX, Material-UI, внутренние `pixi-viewer` и `sdk-js`, Storybook, Helm; Go (go-pg, gotools, SDK вложений), PostgreSQL с TLS, объектное хранилище, Python-код генерации DWG внутри базового образа.
Компонент даёт инженеру инструмент построения поперечных сечений по облакам точек и BIM-документам прямо во вьюере платформы, а затем выгрузки полученного сечения в DWG для работы в CAD. Сценарий в интерфейсе выражен явным конечным автоматом: пользователь выбирает ось сечения (X/Y/Z), указывает центр сечения кликом по облаку точек, корректирует и перемещает секущий бокс, дожидается обработки изображения сечения и вводит имя, после чего сечение сохраняется. Сохранённые сечения показываются списком с датой создания, легендой документов и цветовой раскраской — каждому документу-источнику присваивается свой цвет; их можно показывать и скрывать, зумить, удалять и экспортировать. Вкладка экспортов показывает созданные выгрузки со статусом и кнопкой скачивания. Компонент применяется на этапе контроля и обмера построенного: сечение по лазерному сканированию сопоставляется с проектной геометрией и уходит в CAD.
Фронтенд — микрофронтенд с ленивой загрузкой, встраиваемый в общий вьюер: он получает от хоста экземпляр вьюера, карту документов и идентификатор компании. Доменное состояние — MobX-классы: хранилище сечений, само сечение с документами, цветами, экспортами и признаком видимости, сценарий с описанным автоматом и расчётом размеров бокса, а также слой обработки с генерацией цветов и разрешением идентификаторов документов. Отрисовка идёт через собственные PIXI-компоненты с чанковой загрузкой геометрии сечения. Обращения к бэкенду инкапсулированы в слое эндпоинтов поверх общего `httpService` с выбором хоста по окружению сборки. Джоб экспорта — отдельный контейнер, запускаемый как задача workflow: он создаёт временный каталог, читает сечение из PostgreSQL, выгружает точки в файл, создаёт целевой DWG, вызывает Python-код конвертации с параметром толщины линии, затем загружает результат как вложение через SDK и проставляет идентификатор вложения в запись экспорта. Подключение к БД — управляемый PostgreSQL с TLS.
## django
Репозитории: generic/sarex-backend — легаси-монолит платформы на Django/DRF, ядро доменной модели и API; generic/sarex-frontend — основной SPA-хост, в который встраиваются модули микрофронтендов. Стек: Python, Django (миграции от 2.2 до 4.2), DRF, PostgreSQL, ClickHouse, MongoDB, Celery + Redis, Kafka, S3, django-guardian, django-channels, SimpleJWT + JWKS, Zitadel (OIDC), Prometheus, Sentry, OpenTelemetry, Helm; фронтенд — TypeScript, React, MobX, Material-UI, Webpack 5 с Module Federation, PWA.
Компонент реализует ядро продукта: компании и пользователи с ролями, должностями, подразделениями и подрядчиками, объекты строительства, миссии аэрофотосъёмки и их импорт, ортофотопланы, облака точек, поверхности и меши. Отдельный слой закрывает фотограмметрию и измерения: измерения, вложения, сравнение объёмов и поверхностей, экспорт облаков точек и ортомозаик, PDF-подложки, интеграция с Metashape. Аналитический блок даёт дашборды, виджеты, метрики с атрибутами и значениями, вычисляемые метрики, фильтры, группировки и импорт значений из XLSX — инструмент отслеживания прогресса работ и КПЭ проекта. Приложение карты отвечает за кадастровые данные и заметки на ортофотоплане, отдельный модуль — за ТОиР. Сквозные механизмы — уведомления, согласования, замечания, рабочие процессы и журнал действий — покрывают весь жизненный цикл: от съёмки и загрузки данных до контроля качества и приёмки. Фронтенд собирает всё это в единое рабочее место с 2D/3D-вьюером и разделами рабочих пространств, документации, договоров, трансмитталов, RFI, замечаний, инспекций, предписаний, аналитики, помещений, активов и администрирования.
Технически бэкенд — классический слоёный Django-монолит с приложениями базовой модели, ядра, аналитики, карты, ТОиР, фотограмметрии, активностей, ресурсов и аутентификации, с DRF-роутерами и вьюсетами под `/api/`, админкой, метриками и swagger в отладочном режиме. Асинхронная обработка вынесена в Celery (импорт миссий, активности, уведомления), состояние — в PostgreSQL, аналитические выборки дополнительно идут в ClickHouse, файлы — в S3 с чанковой загрузкой и проверкой хешей. Интеграция с остальной платформой идёт через Kafka-продюсер, HTTP-шлюз к внутренним сервисам (в частности к system-log) и внутренние эндпоинты, включая интроспекцию пользователей, выдачу публичного ключа и сервисных токенов. Аутентификация двухрежимная: собственные JWT с ротацией и JWKS-эндпоинтом и Zitadel как внешний OIDC-провайдер; права — через django-guardian и модели прав на уровне объектов. Фронтенд построен как host-приложение с ленивыми маршрутами и fallback на ошибку загрузки модуля; Module Federation настроен на общие зависимости, внешние модули подключаются как отдельные бандлы.
## documentations
Репозитории: pdm/documentation-api — основной Go-сервис документации (документы, диски, версии, права, обработка файлов); pdm/documentation-api-v2 — переписанная версия домена с проксированием в cde-api; pdm/documentation-frontend — микрофронтенд раздела «Документация». Стек: Go (go-pg, minio-go S3, Valkey/Redis, RabbitMQ, Mailgun/SMTP, OpenTelemetry, Sentry, JWT), в v2 — Fiber, swaggo, отдельные бинарники API, файлового стрима и миграций; PostgreSQL с TLS; фронтенд — TypeScript, React, MobX, Material-UI, axios с ретраями.
Компонент — рабочая среда данных проекта: пользователь работает с «дисками» компании, деревом папок и документами, у каждого документа есть версии-комплекты и физические файлы, страницы с превью, атрибуты, права доступа и связи с другими документами. Через него проходит весь документооборот проекта: загрузка и версионирование проектной документации, штампы и QR-маркировка, электронная подпись, согласования, трансмитталы, подписки на обновление и удаление, корзина и восстановление, changelog версий, избранное и шаблоны наименования файлов. Сервис также отвечает за преобразование инженерных форматов: загруженные IFC, NWC/NWD, RFT, DWG, DXF, PDF, DOCX, облака точек и ортофото ставятся в очередь на обработку и превращаются в просматриваемые в платформе модели и растры. Отдельная функция — публичные ссылки на документы и папки, позволяющие передать файл внешнему участнику без учётной записи. Фронтенд-модуль встраивается в основной SPA и даёт полноценный файловый менеджер с деревом дисков, таблицей документов, контекстным меню, диалогами загрузки и скачивания, правами, поиском и фильтрами.
Технически documentation-api — Go-сервис поверх PostgreSQL с миграциями в коде; модель данных включает документ, диск, комплект, файл-источник и его страницы, состояние многочастной загрузки, права, workflow, проект, штамп, QR, ЭЦП, публичную ссылку, связанные документы, избранное, changelog, шаблон наименования, хеш файла и сессии загрузки. Файлы лежат в S3 с потоковой многочастной загрузкой, горячие данные кэшируются в Valkey. Обработка файлов вынесена в контейнерные джобы: отдельный пакет клиентов workflow формирует и запускает задание для каждого формата с образом из реестра контейнеров и общей версией образов, поддерживается рестарт. Сервис интегрирован с Django-монолитом (компании, пользователи, сервисные аккаунты, настройки), с bim-api, cde-api, workspaces, flows, автоматизацией, system-log, трансмитталами и разметкой через RabbitMQ; авторизация — Zitadel плюс подпись в URL для публичных ссылок и файлового стрима. documentation-api-v2 повторяет тот же домен в чистой архитектуре с публичным и внутренним контурами и отдельным файловым сервером, при этом мутирующие вызовы проксируются в cde-api, а оставшиеся легаси-вызовы помечаются специальным логгером — то есть домен находится в процессе миграции.
## document-link
Репозитории: pdm/document-link-frontend — публичное веб-приложение страницы «ссылка на документ». Отдельного бэкенда нет: серверная часть реализована в pdm/documentation-api (таблица `document_public_link`, настройки секрета и срока жизни JWT публичной ссылки). Стек: TypeScript, Next.js (app router), React, SWR, dayjs, PostCSS/Tailwind.
Компонент решает задачу передачи документа наружу контура платформы: сотрудник проекта создаёт публичную ссылку на документ или папку, а получатель — подрядчик, заказчик, проверяющий — открывает её в браузере без учётной записи. Страница показывает карточку документа: имя, тип с иконкой формата, размер, даты, служебные атрибуты — и даёт скачать файл. Это типовой сценарий выдачи рабочей документации и актов внешним участникам стройки, когда полноценный доступ к среде общих данных не нужен и не разрешён. Приложение публичное, поэтому вынесено в отдельный деплой, а не в основной SPA. Срок жизни ссылки ограничивается на стороне documentation-api через JWT с настраиваемым временем экспирации.
Технически это тонкий Next.js-фронтенд: маршрут `/[uuid]` принимает идентификатор публичной ссылки, компонент модального окна через SWR запрашивает публичный эндпоинт `documentations/api/v1/public/documents/public_link/{uuid}`, а вспомогательный компонент рендерит поля карточки. Собственного хранилища и серверной логики в репозитории нет — вся выдача метаданных и подписанных ссылок на файл делается публичным эндпоинтом documentation-api, который валидирует JWT публичной ссылки. Форматирование размера и дат выполняется на клиенте, иконки типов документов подбираются по расширению. Базовый URL API берётся из окружения сборки, что позволяет разворачивать одну сборку на всех стендах. Аутентификация пользователя отсутствует по определению — контроль доступа полностью сводится к валидности и сроку действия ссылки.
## drawings
Репозитории: aero/drawings-api — Go-сервис поперечных сечений и их экспорта; является серверной частью компонента cross-section. Стек: Go, gorilla/mux, go-pg + миграции, envconfig, zap, Prometheus, внутренние библиотеки gotools и sdk-go (пакет workflows); PostgreSQL (управляемый, с TLS); Docker + Helm.
Компонент отвечает за построение чертёжных данных по результатам аэросъёмки и лазерного сканирования: пользователь задаёт поперечные сечения (профили) по поверхности или облаку точек объекта и получает геометрию сечения для анализа и выпуска чертежей. Это типовая задача земляных работ и линейных объектов — контроль профиля насыпи, выемки, дороги, откоса — когда нужно сопоставить фактическую поверхность с проектной по заданной линии. Сервис хранит сами сечения и отдельно задания на их экспорт, что позволяет выгружать результаты в файлы для передачи в CAD. Он работает в связке с фотограмметрическим контуром платформы, получая исходные поверхности и вложения по внутренним URL. В жизненном цикле проекта компонент применяется на этапе исполнительной съёмки и контроля выполненных объёмов.
Технически это компактный Go-сервис с плоской структурой: бинарник с маршрутизатором, health-проверкой и метриками Prometheus, домен сечений с моделями, интерфейсом хранилища, реализацией на PostgreSQL и репозиторием workflow. HTTP-слой содержит операции создания, получения, получения данных и удаления сечений, а также создания, получения и удаления экспорта и приёма webhook — то есть экспорт выполняется асинхронно во внешнем workflow, который по завершении вызывает webhook сервиса. Схема БД ведётся собственными миграциями, включая мягкое удаление сечений. Конфигурация — через переменные окружения, включая сертификат для TLS-подключения к БД; логирование — zap с прокидыванием request-id. Запуск заданий опирается на общий SDK работы с workflow, что связывает сервис с движком фоновой обработки платформы; из значений Helm видны внутренний адрес сервиса для других компонентов и адрес сервиса вложений. Точный формат экспортируемых файлов по прочитанным фрагментам не восстановлен.
## eav
Репозитории: platform/eav_python — работающий сервис EAV (атрибуты, схемы атрибутов, значения) и справочника активов; platform/eav — репозиторий с gRPC-контрактом EAV, без серверной реализации. Стек: Python, Django + DRF, django-filter, Celery, PostgreSQL (в том числе сырой SQL для пересчёта иерархии), pandas + openpyxl, jsonschema; в platform/eav — protobuf 3 и сгенерированный Go-код.
Компонент даёт платформе универсальную модель «сущность — атрибут — значение»: любые доменные объекты (документы, активы, элементы модели, метрики, замечания, инспекции) можно расширять произвольными пользовательскими атрибутами без изменения схемы БД. Администратор описывает атрибуты и их типы (целое, дробное, дата, дата-время, логическое, справочные Choice и MultiChoice со списками значений), группирует их в схемы и привязывает схемы к типам объектов. Второй крупный блок — активы: иерархический классификатор объекта строительства (структура проекта, секция, этаж, помещение) с внешними идентификаторами, родительскими связями и правами доступа, фактически играющий роль WBS/дерева объекта. Массовое наполнение справочников выполняется импортом Excel-файла с листами «Справочники» и «Аттрибуты» по шаблону, который сервис же и выдаёт; предусмотрен обратный экспорт. Именно через этот компонент атрибутивная информация попадает в документацию, аналитику, замечания и BIM-разделы платформы.
Технически eav_python — Django-сервис с приложениями атрибутов (атрибут, группа, схема, связь схемы и атрибута, варианты значений, перечисление типов), активов (актив, права, процессы импорта и экспорта) и общего ядра; URL смонтированы как несколько версий API для атрибутов и схем и две версии для активов, есть админка. Импорт реализован как Celery-задача с мягким и жёстким таймаутом, лимитами на размер файла и число активов, статусами от `pending` до `committed` и раздельными файлами исходника, ошибок и предупреждений; пайплайн разложен на модули разбора колонок, нормализации, валидации, сборки атрибутов и сохранения с типизированными кодами ошибок (циклическая иерархия, дубль внешнего идентификатора, отсутствующий атрибут) и последующим пересчётом иерархии сырым SQL. Мультиарендность обеспечивается фильтрацией по организации и правами на основе токена, метаданные валидируются jsonschema. Репозиторий platform/eav содержит только proto-файл и сгенерированный Go-код сервиса EAV с методами CRUD и фильтрации, причём целевой Go-пакет указывает на bim-backend-v2 — это незавершённая попытка вынести контракт EAV в gRPC, а не самостоятельный сервис. Потребители держат локальные копии атрибутов и синхронизируют их отдельными командами (`sync_eav` в issues и inspections).
## faas
Репозитории: не найдены. Поиск по проектам GitLab по запросам «faas», «openfaas», «nuclio», «knative», «lambda», «serverless» результатов не даёт; по «function» найден единственный PoC-обработчик событий S3 в облачных функциях. Поиск по коду в ключевых сервисах даёт совпадения только внутри вендоренных библиотек OpenTelemetry (семантические соглашения `faas.name`, `faas.trigger`), то есть к коду платформы отношения не имеет. В issues и merge request'ах упоминаний тоже нет.
Прямых доказательств существования компонента с таким именем нет — ни репозитория, ни группы, ни упоминаний в коде и тикетах. По косвенным признакам функцию «функции как сервис» в платформе выполняет связка движка workflow и множества одноразовых job-контейнеров: есть семейство workflows-api / workflows-engine / workflows-backend / workflows-frontend, инфраструктурный argo-workflows, шаблоны и инструменты workflow, а также группы job-репозиториев в aero/jobs, pdm/jobs, generic/processing и algorithms — от разрезания и склейки PDF и генерации документов из шаблона до конвертации DXF в поверхность и расчёта объёмов.
Ровно эта модель видна в коде потребителей: documentation-api для каждого формата собирает имя контейнерного образа из реестра и версии образов и запускает задачу через адрес движка, а результат принимает по webhook; тот же приём используют drawings-api, comparisons и issues (генерация предписаний). Таким образом, faas в архитектуре — с высокой вероятностью логическое имя для слоя эфемерных вычислительных функций-джобов, запускаемых движком workflow поверх Kubernetes, а не отдельная кодовая база. Это интерпретация по косвенным признакам, а не подтверждённый факт: перед фиксацией в модели значение компонента стоит уточнить у команды платформы.
## flows
Репозитории: proc/flows-backend — сервис маршрутов согласования документации; proc/flows-frontend — микрофронтенд конструктора маршрутов. Стек: Python, FastAPI, SQLAlchemy + Alembic, PostgreSQL (JSONB, массивы), sqladmin, Celery, FastStream + Kafka (SASL/SCRAM), httpx, pandas (расчёт рабочих дней), JWT-middleware, OpenTelemetry; фронтенд — TypeScript, React, MobX, Material-UI, rsbuild + Module Federation.
Компонент реализует согласование и выпуск проектной документации: пользователь настраивает маршрут (`Flow`) из последовательных шагов (`Step`) с назначенными согласующими, а каждый документ проходит по маршруту в виде ревью (`Review`) с фиксацией решений участников и статусов. Основные сущности — маршрут, шаг, ревью, документ, статус, действие пользователя и очередь задач согласующего с приоритетами, длительностями и сроками, пересчитываемыми по рабочим дням. Поддерживаются типы маршрутов и шагов, минимальное число согласующих на шаге, массовые операции над списками маршрутов и согласующих, режимы уведомлений о завершении. Отдельный блок — трансмитталы: у маршрута есть флаг автоматической передачи после согласования, шаблоны передачи и фильтры по статусам и типам документов, а созданные передачи привязываются к ревью с записью в историю действий. Применяется на стадии выпуска и приёмки рабочей документации, где нужны формализованные круги согласования и подтверждённая передача комплектов.
Технически это монолитный FastAPI-сервис со слоями роутеры → CRUD-менеджеры (маршрут, ревью, шаг, статус, документ, действие пользователя, очередь задач) → модели SQLAlchemy. Роутеры смонтированы под внешним путём `/flows/api/v1`, отдельно вынесен внутренний роутер; авторизация — middleware разбора JWT и декларативная таблица правил вида `base.can_view_review` с точечными правилами для отдельных URL. Исходящие события публикуются в Kafka через FastStream: смена статуса документа, создание и завершение ревью, изменение состава согласующих. Интеграции по HTTP: Django-монолит (пользователи, токены, предки документов), сервис ресурсов, чек-листы (в том числе блокировка результатов через внутренний эндпоинт) и EAV с кешированием типов атрибутов. Есть админка на sqladmin с собственной аутентификацией, фоновый пересчёт кеша нагрузки согласующих в отдельном потоке и тяжёлые агрегирующие SQL-запросы для счётчиков. Важно не путать с платформенным семейством `workflows`: flows — доменный сервис согласования документов со своей моделью и БД, тогда как workflows-engine — универсальный исполнитель фоновых задач; историческое имя внутренней секции настроек в flows-backend (`settings.workflows`) и создаёт путаницу.
## iam
Репозитории: platform/iams-v2 — сервис управления пользователями, ресурсами и правами; platform/srx-rebac — репозиторий пуст. Стек: Go (гексагональная архитектура), PostgreSQL, SpiceDB (ReBAC) по gRPC, Zitadel Management API v2, Kafka (SCRAM), S3, Helm/Kubernetes с настройками Istio, k6 для нагрузочных тестов.
Компонент — платформенный IAM: он владеет иерархией ресурсов, компаниями и организациями, пользователями, сервисными аккаунтами и разрешениями, которые все остальные модули используют как единый источник прав на объект строительства или проект. Из архитектурных решений видно разделение: `Resource` — мета-модель иерархии, `Project` — её реализация; права описаны в модели ReBAC схемой SpiceDB. Сервис отвечает на прикладные вопросы «какие права у пользователя на ресурс», «какие ресурсы доступны пользователю», «какие сервисные аккаунты действуют на ресурсе», а также отдаёт списки пользователей с фильтрами по ресурсу и разрешению — именно на эти ответы опираются flows, issues и inspections при фильтрации данных. Пользователи заводятся во внешнем провайдере идентификации: адаптер создаёт, обновляет и ищет пользователей в Zitadel и пишет им метаданные, которые затем приходят в другие сервисы заголовком `identity`. Организация в Zitadel выбирается правилами по домену email или логина, то есть поддерживается мультиарендность заказчиков.
Архитектурно это гексагональный Go-сервис с тремя бинарниками — сервер, CLI и наполнение данными — и адаптерами SpiceDB, Zitadel, Kafka и S3. SpiceDB подключается gRPC-клиентом и используется для чтения и записи отношений и авторизации ресурсов с ретраями; у SpiceDB собственный Postgres-datastore, отдельный от базы приложения, а миграция схемы и запись `.zed`-схемы вынесены в pre/post-хуки Helm. HTTP API включает выборку пользователей, проверку разрешений, поиск ресурсов и сервисных аккаунтов, CRUD ресурсов и виджетов, массовое обновление прав и отдельный внешний административный контур, который монтируется только при включённой аутентификации и принимает legacy-токены для обратной совместимости. Kafka используется для публикации доменных событий об изменении ресурсов и состояния пользователей, а бэкфиллы в закрытых контурах гоняются как Kubernetes Job из чарта; потребители этих топиков видны, в частности, в inspections-backend. Есть подробный контур нагрузочных тестов на k6 с порогами по времени ответа. Провайдер идентификации в коде — Zitadel; Keycloak в этой части не используется (он встречается только как auth-сервер Camunda в оркестраторе CDE).
## inspections
Репозитории: proc/inspections-backend — бэкенд модуля «События / Проверки»; proc/inspections-frontend — микрофронтенд с календарём событий и бронированием слотов. Стек: Python 3.12, FastAPI, Piccolo ORM + Piccolo Admin, PostgreSQL (JSONB, массивы, интервалы, триггеры, advisory-локи), FastStream + Kafka, httpx, OpenTelemetry, XLSX-экспорт, отдельные образы API и Kafka-приложения; фронтенд — TypeScript, React, MobX, Material-UI, DevExpress Scheduler, rsbuild + Module Federation.
Компонент ведёт события и проверки на объекте в продукте строительного контроля: инспекция — это запланированный осмотр с типом, датой и временем, ответственными, локацией (в том числе идентификатором помещения), набором настраиваемых атрибутов, статусом и историей изменений с парами «было — стало». Сервис даёт CRUD событий и их типов с конфигурируемыми атрибутами и связью с типами замечаний из issues, проверяет занятость ответственных (пересечение по времени, запрет текущего дня — настройки уровня компании), рассылает уведомления и выгружает реестр событий в XLSX. Отдельная подсистема — бронирование слотов: правила доступности для связки «проект + тип события» бывают цикличными по дням недели или разовыми по датам, интервал ограничен рабочим днём кратно тридцати минутам, задаются целевые сервисные аккаунты и лимит участников, а само бронирование идемпотентно по внешнему идентификатору. Практически это планирование выездов инспекторов и приёмок с контролем ёмкости; отдельной сущности «рабочий календарь специалиста» в платформе нет — доступность исполнителя определяется его событиями.
Реализация — два приложения из одной кодовой базы: HTTP API со слоями контроллер → сервис → БД/клиенты, синглтонами в состоянии приложения и контекстом на запрос, и отдельный Kafka-консьюмер на FastStream. Роутеры — события и бронирование слотов; права двухуровневые: глобальные из токена либо права сервисных аккаунтов на конкретные типы событий, проверка вынесена в зависимость. JWT не проверяется по подписи (доверие шлюзу), поддерживаются два формата — обычный payload и base64-метаданные Zitadel в заголовке `identity`. Исходящие события версионируются в имени топика (`inspections.inspection.created.v1`, статусы, типы); входящие — события активов EAV для обновления локальной копии таблицы атрибутов и топики IAM для клона пользователей, подразделений, должностей и сервисных аккаунтов. По HTTP сервис ходит в Django-монолит за пользователями, в EAV за атрибутами и в движок workflow за отправкой писем; есть массовые скрипты синхронизации, админка Piccolo, мягкое удаление, создание правила бронирования по умолчанию через триггер PostgreSQL и защита конкурентных изменений через advisory-локи и оптимистичную блокировку по `updated_at`.
## issues
Репозитории: proc/issues-backend — сервис замечаний и предписаний; proc/issues-frontend — микрофронтенд реестра замечаний. Сюда же переехала логика архивных remarks-*. Стек: Python, Django 4.2 + DRF, drf-spectacular, PostgreSQL (в том числе полнотекстовый поиск), Celery + Redis, Kafka, S3 (boto3), pandas + Pillow (XLSX), ReportLab (PDF), SimpleJWT с несколькими бэкендами включая Zitadel, внутренняя библиотека `sarex_cli` для фильтров EAV, OpenTelemetry.
Компонент закрывает работу с замечаниями строительного контроля: замечание с типом, статусами и настраиваемыми статусными моделями, ответственными, комментариями, вложениями-фотографиями, историей изменений и атрибутами из EAV. Пользователь ставит «пин» на странице документа, в ячейке XLSX или на задаче календарно-сетевого графика и заводит замечание с описанием, сроком устранения, ответственными и графическими пометками поверх чертежа. Замечание связывается с контекстом платформы: помещением, ресурсом или проектом, ревью из flows, событием из inspections и рабочим пространством. Отдельное приложение реализует предписания — документы, формируемые по набору замечаний, со своими статусами. Продуктовый сценарий — фиксация дефекта на объекте с фото, назначение ответственного и срока, движение по статусной модели с проверкой прав на переход, выпуск предписания и выгрузка реестра в Excel и PDF для заказчика или подрядчика. Есть также реестр шифров и ежемесячные счётчики для нумерации.
Технически это классический Django-проект с разделением на API (вьюсеты, сериализаторы, фильтры, сервисы), доменные модели, предписания и общее ядро с аутентификацией, правами и миксинами. Экспорт вынесен в отдельный пакет: сборщик данных с пулом потоков, экспортёр Excel на pandas и экспортёр PDF на ReportLab с русскими шрифтами; при большом числе замечаний экспорт уходит в Celery, результат складывается с ограниченным сроком жизни, и пользователь получает уведомление. Celery на Redis обслуживает уведомления (создание, изменение, назначение ответственного, массовые рассылки), публикацию событий в Kafka с трассировкой и синхронизацию с OLAP-сервисом. Права строятся на токене компании и уточняются правилами на уровне типа замечания и допустимости перехода статуса, в том числе через кеш. Атрибуты EAV держатся локальной копией: миграция первичного импорта и management-команда синхронизации тянут активы пачками под сервисным токеном, а фильтрация по атрибутам строится маппером из общей библиотеки. Вложения хранятся в S3; фронтенд организован по слоям API → репозитории → сторы → view-model → представления и подключает диалог создания документа из модуля документации.
## mapper
Репозитории: platform/mapper — агрегирующий сервис (BFF) поверх нескольких API. Стек: Python, FastAPI, httpx (async с ретраями), Redis/RedisJSON (опционально отключается), PyJWT, Helm/Kubernetes.
Компонент решает узкую продуктовую задачу — склеивать данные из разных сервисов в один ответ для интерфейса, чтобы фронтенд не делал N запросов и не соединял сущности на клиенте. Реализованы два сценария. Первый — реестр документов на диске: документы из сервиса документации объединяются с данными о согласовании из flows по ключу документа, так что в списке сразу видно состояние маршрута согласования. Второй — заметки: записи сервиса notes объединяются со связями по идентификатору для произвольной пары «сервис / сущность / экземпляр». Компонент оперирует чужими сущностями (документ, ревью и шаг согласования, заметка, связь), собственной доменной модели и базы данных не имеет. Применяется в интерфейсах работы с проектной документацией и с комментариями к объектам платформы.
Технически это два GET-эндпоинта — по документам диска и по заметкам — обслуживаемых менеджером сервисов: обёрткой над httpx-сессией с прокидыванием пользовательского токена и кешированием ответа в Redis через RedisJSON по ключу «пользователь + URL» с TTL из конфигурации. Слияние данных выполняют чистые функции, индексирующие ответы по идентификаторам. Внешние адреса заданы переменными окружения: сервис документации, flows, notes и Django-монолит — это прямое подтверждение зависимости компонента от flows и documentations. Аутентификация — зависимость, которая понимает два варианта: Zitadel (заголовок авторизации плюс base64-метаданные в `identity`) и legacy-JWT платформы, разбираемый без проверки подписи. Таймаут запросов вынесен в конфигурацию, сервис деплоится одним Deployment без БД и брокеров. Не установлено, какие именно фронтенд-модули сегодня используют эти эндпоинты.
## measurements
Репозитории: aero/measurements — сервис геопространственных измерений по растрам аэрофотосъёмки. Стек: Python, FastAPI, GDAL/osgeo (чтение GeoTIFF, в том числе напрямую из S3), boto3, pyproj, NumPy, OpenCV, SciPy, Pillow, Sentry, OpenTelemetry.
Компонент даёт инструменты измерений по материалам аэрофотосъёмки и лазерного сканирования: по ортофотопланам, цифровым моделям местности и рельефа и тепловизионным растрам он считает величины, нужные при контроле земляных работ и мониторинге стройплощадки. Поддерживаются точечные запросы (высота или температура в точке и в наборе точек), построение профиля вдоль ломаной с достройкой промежуточных точек, расчёт объёма по замкнутому контуру в нескольких режимах, включая объём относительно цифровой модели, и расчёт разности объёмов между двумя съёмками — то есть выполненного за период объёма работ. Дополнительно отдаётся служебная информация по растру: метаданные, статистика по каналам и границы покрытия по тайловым зумам, а также пересчёт координат между системами. Типичное применение — обмер отвалов и котлованов, контроль объёмов вывоза и завоза грунта, тепловые обследования кровель и фасадов.
Реализация — stateless-сервис на FastAPI без собственной БД: роутеры под общим префиксом (точка, набор точек, профиль, объём, разность объёмов, преобразование координат, информация о GeoTIFF), pydantic-модели запросов и вычислительный слой с открытием датасета и чтением блоков, преобразованием «пиксель ↔ координата» и трансформациями систем координат с кешированием, расчётом высот, температур, масок и объёмов. Растры читаются напрямую из объектного хранилища: конфигурация хранит несколько учётных записей S3 и настраивает GDAL под них, открытые датасеты кешируются. Маски полигонов строятся через OpenCV и Pillow, аппроксимация для температурных расчётов — методом наименьших квадратов из SciPy. Аутентификация — собственное middleware, понимающее и JWT из заголовка, и base64-метаданные, с обращением во внешний сервис; наблюдаемость — Sentry и трассировка OpenTelemetry. Тесты покрывают модели и точечные роутеры с моками GDAL-зависимостей. Не установлено, какие клиенты вызывают сервис и как именно исходные растры попадают в хранилище.
## message-hub
Репозитории: planning/message-hub — центральный событийный хаб домена планирования; pdm/dps_message_hub — узкий консьюмер событий по активам для домена PDM. Стек: Python 3.12, FastStream, Kafka через aiokafka (SASL + SSL), Redis (кеш и менеджер сокетов), python-socketio, SQLAlchemy Core с сырыми SQL-запросами к PostgreSQL, boto3/S3, httpx, Jinja2; в dps_message_hub — FastStream + async psycopg с пулом.
Компонент отвечает за асинхронную интеграцию сервисов платформы: он принимает события из Kafka и превращает их в побочные действия, которые не должны блокировать пользовательские API. Для пользователя это выражается в том, что после изменения задач календарно-сетевого плана автоматически пересчитывается аналитика, обновляются атрибуты объектов, отправляются письма, формируются экспортные файлы (в том числе HTML → PDF), пишется системный журнал действий и выполняется автопланирование. Отдельная ветка обработки — синхронизация проектных сущностей и ресурсов: создание, обновление или удаление проекта при изменении ресурса. Хаб также транслирует изменения в браузер по WebSocket, обеспечивая живое обновление доски проекта у нескольких пользователей одновременно. Второй репозиторий решает более узкую задачу: слушает broadcast-топик активов и переносит обновления атрибутов и события разметки в базу документации домена PDM.
Технически planning/message-hub — не HTTP-сервис, а ASGI-приложение FastStream с четырьмя Kafka-роутерами (активы, планирование, проектные сущности, ресурсы), общим обработчиком повторов и политикой подтверждения, плюс health-эндпоинты, проверяющие брокер и Redis. Сервисный слой обращается к смежным сервисам по HTTP (BI, EAV, issues, PDF, PM, projects), кэширует пользователей и токены в Redis, пишет в PostgreSQL напрямую SQL-запросами (системный лог, сводные поля, разделы активов, проектные сущности), складывает экспорт в S3 и рендерит письма Jinja-шаблонами. dps_message_hub построен строго по чистой архитектуре с разделением на домен, приложение, инфраструктуру и интерфейс, использует внедрение зависимостей FastStream, транзакции через отдельный компонент, middleware повторов и одну consumer-группу с чтением с начала топика. Ключевое отличие: planning/message-hub — «толстый» хаб с десятком бизнес-обработчиков, WebSocket и множеством интеграций, dps_message_hub — тонкий однотопиковый сервис свежей архитектуры только для атрибутов активов.
## notes
Репозитории: aero/notes-backend — REST API заметок, документов, ссылок и вложений; aero/notes-frontend — фронтенд-модуль заметок, встраиваемый в 2D/3D-просмотрщик. Стек: Python, FastAPI, SQLAlchemy + Alembic, PostgreSQL с полнотекстовым поиском (TSVECTOR), httpx, PyJWT, профилирование SQL; фронтенд — React + TypeScript, MobX, Material-UI, react-hook-form, react-dropzone, снятие скриншота вида, собственный переводчик.
Компонент реализует пользовательские заметки и примечания на объектах проекта: пользователь может создать заметку на 2D-чертеже или в 3D-модели, задать срок, цвет, приложить фото и файлы, связать её с документом и другими проектными сущностями. Заметка оперирует сущностями «заметка», «связь», «документ» и «вложение» и привязывается к внешним сущностям через перечисления сервиса и типа сущности, то есть служит универсальным механизмом комментирования объектов разных сервисов платформы. Отдельный сценарий — формирование документа по заметке: во фронтенде есть форма создания документа с типом, атрибутами и вложенными табличными полями, а в бэкенде — запуск задачи генерации документа. Есть фильтрация по датам и статусам, поиск, режимы отображения подсказок и видимости заметок, отправка скриншота вида вместе с заметкой. Применяется на этапах авторского надзора и строительного контроля, когда замечание нужно зафиксировать прямо на модели или чертеже.
Технически бэкенд построен по схеме роутеры → обобщённый CRUD → модели SQLAlchemy; роутеры — заметки, связи, документы и вложения с общим префиксом из настроек. Полнотекстовый поиск реализован кастомным типом TSVECTOR и соответствующими миграциями. Доступ проверяется декларативной таблицей прав и middleware интеграции с legacy-аутентификацией, сессия БД живёт в отдельном middleware с ContextVar. Вложения не хранятся в самой БД: файлы отправляются во внешний файловый сервис по httpx. Есть опциональный подмодуль интеграции со сторонней системой со своей моделью-прокси, JWT-авторизацией и отдельным роутером, включаемый флагом конфигурации. Генерация документов инициируется через шаблон задачи и клиент создания документа. Фронтенд организован как встраиваемый модуль со стором MobX, собственным контекстом и режимами работы в 2D и 3D; интерфейс разбит на список с фильтром, создание заметки, создание документа и общие компоненты — зона перетаскивания файлов, слайдер изображений, действия над заметкой и отправка вида.
## pm
Репозитории: planning/pm-backend — ядро календарно-сетевого планирования; planning/pm-frontend — интерфейс диаграммы Ганта и управления задачами. Стек: Python, Django 5 + DRF, PostgreSQL с SQL-триггерами и функциями, Celery + Redis, Kafka, ClickHouse, S3, Zitadel-аутентификация плюс собственный JWT-бэкенд, OpenTelemetry и Sentry, pandas/NumPy, Jinja2 (HTML-шаблон Ганта для PDF), парсеры XML и XER; рядом с Django смонтировано FastAPI-приложение, документация описывает новый слоёный стиль на FastAPI + async SQLAlchemy. Фронтенд — React + TypeScript, MobX, Material-UI, Webpack 5, Storybook.
Компонент закрывает управление проектом во времени: иерархия задач, длительности, связи предшествования, календари (включая производственные с масками рабочих дней и праздниками), базовые планы, фактические значения и проценты выполнения, ресурсы и их назначения на задачи и элементы модели. Пользователь может импортировать существующий график из MS Project (XML), Primavera (XER), корпоративного шаблона XLSX и отраслевых форматов, работать с ним на диаграмме Ганта и выгружать обратно в PDF с настраиваемой детализацией, условным форматированием и составом колонок. Поддерживаются детализированные задачи и срезы значений для учёта выполнения, визуальные профили оформления, комментарии к задачам, связи задач с внешними сущностями и связи между проектами. Автопланирование и пересчёт запускаются асинхронно, что позволяет работать с крупными графиками без блокировки интерфейса.
Технически бэкенд — DRF-приложение с набором вьюсетов: проекты, задачи, детализированные задачи, значения, состояния проекта, ресурсы и их назначения, связи задач, атрибуты проекта, настройки, визуальные профили, связи проектов, календари, комментарии, связи сущностей и описания; отдельно вынесен внешний API с урезанным набором для интеграций. Импорт реализован иерархией парсеров с типизированными ошибками разбора файла, календаря, иерархии, связей и базовых планов и запускается Celery-задачами. Экспорт в PDF собирается провайдерами на pandas с обогащением атрибутами, базовыми планами, связями и пользователями, рендерится Jinja-шаблоном и отдаётся внешнему PDF-сервису. Модель данных включает проект, задачу с локальным индексом, путём, прогрессом и распределением, связи задач, значения атрибутов (в том числе привязку к активам), календари, базовые планы, срезы значений, системный лог и собственную модель прав по типу модели, экземпляру и действию. Взаимодействие с остальной платформой идёт через Kafka (события подхватывает message-hub) и ClickHouse для аналитики. Не установлено, какая часть API уже переехала на встроенное FastAPI-приложение.
## prescriptions
Репозитории: proc/prescriptions-frontend — микрофронтенд предписаний; бэкенд — приложение `prescriptions` внутри proc/issues-backend, публикуемое по пути `/issues/api/prescriptions`. Отдельного репозитория бэкенда не существует. Стек: фронтенд — React + TypeScript, rsbuild + Module Federation, MobX, Material-UI, react-hook-form + zod, внутренний `sdk-js` с провайдером Zitadel; бэкенд — Python, Django + DRF, django-filter, PostgreSQL; генерация документов делегируется движку workflow.
Компонент реализует выдачу предписаний подрядчику по результатам строительного контроля. Предписание собирается из зафиксированных замечаний, привязывается к договору и подрядчику (наименование, ИНН, идентификаторы), к объекту или ресурсу и компании, получает уникальный в рамках компании номер и проходит согласование по статусам «Черновик → На согласовании → Согласовано / Не согласовано → Передано / Не передано». По выбранному шаблону формируется официальный документ (docx, затем pdf) с реквизитами сторон: застройщик, подрядчик, субподрядчик, лица строительного контроля, номера приказов, адрес и наименование объекта. Пользователь редактирует состав замечаний, генерирует документ, экспортирует его и удаляет версии; все действия фиксируются в истории предписания. Компонент используется на этапе строительно-монтажных работ как формализованный выход процесса инспекций и замечаний.
Технически бэкенд — Django-приложение внутри issues-backend: модель предписания с автором, компанией, ресурсом, подрядчиком, договором, идентификатором шаблона-комплекта, номером с уникальным ограничением в пределах компании, статусом генерации и мягким удалением; настраиваемые по компаниям статусные модели с цветами и журнал истории с типами событий (создано, изменено, смена статуса, старт/финиш/ошибка генерации, добавление и удаление замечаний). Связь с замечаниями — «многие ко многим» по их публичным идентификаторам, фильтрация выполняется кастомными фильтрами, поддерживающими и GET со списком через запятую, и POST со списком значений. Генерация формирует тело задания для движка workflow — имя, список задач со slug, docker-образом, лимитом повторов и входными данными — и складывает результат по заданному пути, то есть предписание напрямую зависит от компонента фоновой обработки. Фронтенд собран rsbuild с Module Federation, авторизуется через Zitadel, ходит в хосты issues, documentations, checklists, файлового сервиса, EAV, шлюза и оркестратора, подтягивает удалённый компонент диалога создания документа из модуля документации и содержит фичи редактирования состава замечаний, генерации, экспорта и удаления документа.
## processing
Под этим именем сходятся две связанные, но разные сущности — платформенный движок процессов и инфраструктура фоновых джобов; ниже описаны обе.
Репозитории: platform/workflows-engine — исполнитель воркфлоу; platform/workflows-api — HTTP API воркфлоу, задач и запусков; platform/workflows-backend — предшествующая монолитная реализация; platform/workflows-frontend — микрофронтенд мониторинга; generic/processing/job_template и generic/processing/remove-object-from-s3 — шаблон и типовой пример контейнерного задания. Отдельно: platform/srx-processing — несмотря на имя, это ETL-скрипт наполнения отраслевых справочников, к движку процессов отношения не имеющий. Стек: Go (pgx в движке, go-pg в API), PostgreSQL, RabbitMQ/AMQP, Kubernetes client-go, zap, mock-тесты; фронтенд — React + TypeScript, MobX, Material-UI, виртуализация списков, внутренний `sdk-js`; джобы — Python, boto3, pydantic, внутренняя библиотека `workflows-tools`, Docker.
Компонент — внутренняя «фабрика» тяжёлых вычислений платформы: любая длительная операция (конвертация модели, генерация документа, обработка облака точек, экспорт, обслуживание файлов) оформляется как workflow — направленный граф задач, каждая из которых выполняется в отдельном контейнере. Продуктовые сервисы не выполняют такую работу сами, а публикуют задание и отслеживают его статус; результат складывается в хранилище и возвращается пользователю как готовый файл или обновлённые данные. Ровно через этот механизм работают documentations (конвертация форматов), comparisons (сравнения), drawings и cross-section (экспорт в DWG), prescriptions (генерация документа). Для инженера поддержки есть отдельный интерфейс: список воркфлоу с фильтром по компаниям, конвейер задач по слоям с индикаторами состояния, просмотр логов запуска, отмена выполняющегося запуска и перезапуск задачи с ручной правкой параметров, входных объектов и требований к ресурсам — это делает компонент точкой наблюдаемости и ручного вмешательства в фоновую обработку.
Движок построен по чистой архитектуре: сущности воркфлоу, задачи, запуска и описания job, слои сценариев, оркестратор принятия решений о запуске, контроллер периодического опроса состояний и исполнители двух типов — Kubernetes Job и отправка сообщения в очередь RabbitMQ стороннему воркеру (именно так работает, например, nwd-converter). API — отдельный HTTP-сервер с контроллерами v1 и авторизационным middleware; наблюдаемые эндпоинты: список и карточка воркфлоу с фильтрами и пагинацией, перезапуск задачи, чтение логов запуска. Схема БД общая с прежней реализацией и включает блокировки воркфлоу, логи и прогресс запусков, требования к сервисам, параметры и зависимости по умолчанию и конфигурацию исполнения. Внешне сервис публикуется под хостом `orchestrator` (`/orchestrator/api`), логи запусков смотрятся в SigNoz. Вторая часть компонента — сами задания: каждая фоновая операция упакована в собственный Docker-образ по единому шаблону, в который ставится общая библиотека `workflows-tools` и копируется точка входа. Параметры передаются не аргументами, а JSON-структурами в переменных окружения, валидируются pydantic-моделями, доступ к хранилищу инкапсулирован в отдельном модуле, реквизиты S3-аккаунта также приходят из окружения — это соответствует контракту движка, где в описании задачи указываются образ, slug, лимит повторов и входы. Формально не установлено, какой из репозиториев (workflows-backend или workflows-engine) работает в проде; вывод о замещении сделан по датам миграций и структуре кода.
## projects
Репозитории: planning/projects-backend — API карточки и витрины проектов; planning/projects-frontend — интерфейс страницы проекта и витрины. Стек: Python, FastAPI, async SQLAlchemy 2.0, Alembic (собственная схема БД), PostgreSQL с JSONB, массивами и UUID, boto3 (S3 для фотографий), PyJWT, httpx, настройки для Superset; фронтенд — React + TypeScript, MobX + TanStack React Query, Material-UI, Webpack 5, leaflet (карта), виртуализация списков.
Компонент отвечает за витрину проектов и карточку конкретного проекта — верхнеуровневый вход пользователя в платформу. Здесь проект описывается атрибутами и местоположением, снабжается фотографиями, группируется по настраиваемым признакам компании и отображается карточками в общем списке. Внутри проекта пользователь работает с настраиваемыми вкладками и разделами: каждый раздел — это виджет с показателями, который администратор может добавить, отредактировать, переупорядочить или удалить прямо в интерфейсе, переключив режим администрирования в шапке проекта. Поддерживаются разные типы разделов, включая встраивание внешней аналитики через iframe (в конфигурации присутствует Superset) и выбор объектов из дерева активов. Таким образом компонент выступает «обложкой» проекта, агрегирующей данные остальных модулей на всём жизненном цикле.
Технически бэкенд следует слоёной архитектуре: роутеры API v1 (проект, вкладка, раздел, фотография, витрина) → сценарии → репозитории → модели, зависимости собираются в отдельном модуле, проверки доступа вынесены в слой безопасности поверх разбора JWT. Помимо публичного API есть служебный контур `/internal` (создание и обновление проекта, массовое обновление разделов), используемый другими сервисами платформы, и служебный роутер health-проверок. Собственные таблицы живут в отдельной схеме БД — комментарий в коде прямо указывает, что имена в `public` уже заняты, а таблица проектов заменяет прежний синк из legacy-контура. Модели: проект с JSONB-атрибутами, координатами и UUID, вкладка, раздел с JSONB-конфигурацией и порядком, фотография с порядком и привязкой к проекту, настройки компании с группировками. Файлы фотографий кладутся в S3, справочные данные берутся из сервиса ресурсов. Фронтенд использует MobX-сторы в связке с React Query, страницу проекта с шапкой, карточкой описания и показателями, модальные окна управления разделами и виртуализированное дерево объектов для выбора активов. Миграции датированы июлем 2026 года и содержат ссылки на этапность и legacy-синк — компонент, вероятно, находится в стадии замещения прежнего решения.
## remarks
Репозитории: proc/remarks-frontend — активный микрофронтенд работы с замечаниями; proc/remarks-api, proc/remarks-cli, proc/export-remarks — архивные (`_archived_`) бэкенд, CLI и экспорт; proc/issues-backend — действующий бэкенд, куда переехала вся логика. Стек: фронтенд — TypeScript, React, MobX, Material-UI, TanStack Table + TanStack Virtual, внутренний `sdk-js`, внутренний пакет переводов; бэкенд — см. компонент issues (Django/DRF, PostgreSQL, Celery + Redis, Kafka, S3, экспорт в XLSX и PDF).
С точки зрения архитектуры это пользовательский модуль замечаний, сохранивший историческое имя: собственный `remarks-api` архивирован, и модуль работает поверх сервиса issues. Пользователь ставит «пин» на странице документа, ячейке XLSX или задаче календарно-сетевого графика и заводит замечание с описанием, сроком устранения, ответственными (сотрудники, подразделения, должности), вложениями, графическими и текстовыми пометками поверх чертежа, комментариями и произвольными атрибутами. Замечания типизированы и имеют настраиваемые статусные модели с правами на переходы, что позволяет вести цикл «выдано → в работе → устранено → проверено» под регламент конкретного заказчика. Замечание привязано к документу и его версии, к рабочему пространству и к ресурсу или проекту, а также может быть связано с процедурой согласования и с предписаниями. Доступны табличное и списочное представления, фильтры с сохранением, настройка видимых колонок, история изменений и массовое редактирование; результат выгружается в XLSX и PDF-отчёты, в том числе с изображениями вложений.
Технически это микрофронтенд-модуль, экспортируемый в host-приложение со своим провайдером и MobX-стором и порталами для встраивания панелей, общающийся по HTTP через общий `httpService` с сервисом issues. На стороне бэкенда работают модели замечания, его изменений, типа, статусов и их связей, прав на переход и на тип, вложений, комментариев и записей атрибутов. Права строятся на JWT и наборе разрешений просмотра, редактирования, администрирования и надзора, дополнительно уточняемых на уровне типа замечания и сервисных аккаунтов. Атрибуты вынесены в собственную EAV-модель, синхронизируемую с внешним сервисом EAV миграцией первичного импорта и management-командой. Асинхронная часть — Celery-задачи уведомлений, синхронизации с OLAP-сервисом, публикации событий в Kafka и фоновой генерации больших экспортов с сохранением файлов в S3. При переносе компонента в модель ArchiMate стоит явно зафиксировать, что «remarks» и «issues» — это один бэкенд и два имени, иначе связи между элементами получатся дублирующими.
## reviews
Репозитории: proc/reviews-frontend — микрофронтенд рабочего места согласующего; proc/flows-backend — бэкенд маршрутов согласования; proc/flows-frontend — UI конструктора маршрутов; proc/export-reviews — сервис экспорта отчётов по согласованиям. Отдельного репозитория `reviews-backend` не существует. Стек: фронтенд — TypeScript, React, MobX, rsbuild + Module Federation, внутренний `sdk-js`, Helm; бэкенд — см. компонент flows (FastAPI, SQLAlchemy, PostgreSQL, Kafka через FastStream, Celery, sqladmin).
Компонент отвечает за согласование (рецензирование) проектной документации: документ или комплект запускается по маршруту, состоящему из шагов с назначенными согласующими, сроками и минимальным числом согласований. Согласующий получает задачу в очередь с приоритетом и длительностью, просматривает документ, ставит пометки и замечания, заполняет чек-листы и выносит решение — согласовано, с замечаниями или отклонено, после чего документ переходит на следующий шаг либо маршрут завершается. Компонент оперирует сущностями «согласование», «маршрут», «шаг», «статус», «документ», «действие пользователя», «задача в очереди» и состоянием документа на шаге. Это ключевой этап жизненного цикла проектной документации между выпуском версии и её выдачей «в производство работ»: именно результат согласования определяет статус документа и появление штампа и QR на печатной версии. Поддерживаются массовые операции, копирование маршрутов, пересчёт сроков по рабочим дням и уведомления согласующих и администраторов, в том числе о пустых шагах.
Технически reviews-frontend — remote-модуль Module Federation со своим маршрутизатором и корневым стором, обращающийся к нескольким хостам, объявленным декларативно: flows (`/flows/api/v1`), documentations, лямбды, шлюз и Django-монолит. Основные вызовы: фильтрация и получение согласований, выборка документов по идентификаторам и статусу согласования, список задач с изменением приоритета и длительности, обновление результатов чек-листа, привязка маршрута к документам, а также API отметок и агентов с длительным таймаутом прогона. Серверная часть построена по слоям роутеры → зависимости → CRUD-менеджеры → модели, с отдельными менеджерами на каждую сущность, миксинами проверки маршрута и действий пользователя, публичным и внутренним роутерами и декларативной моделью прав. Интеграции: публикация в Kafka событий смены статуса документа и завершения согласования, кеширование типов атрибутов EAV, исходящие HTTP-вызовы к смежным сервисам, кеш количества задач пользователя в памяти с фоновым обновлением. Экспорт отчётов вынесен в отдельный сервис. Как и в паре remarks/issues, здесь один бэкенд обслуживает два фронтенд-компонента: flows-frontend — конструктор маршрутов, reviews-frontend — рабочее место согласующего.
## rfi
Репозитории: proc/rfi-backend — сервис запросов информации; proc/rfi-frontend — микрофронтенд RFI. Стек: Python, Django 5.1 + DRF, PostgreSQL, django-filter, drf-spectacular, SimpleJWT с интеграцией Zitadel, Celery + kombu, pydantic (DTO), httpx, django-colorfield, локализация; фронтенд — TypeScript, React, MobX, rsbuild + Module Federation, внутренний `sdk-js`; CI/CD — GitLab CI + Helm.
Компонент реализует процесс RFI (Request for Information) — формальные запросы информации и разъяснений между участниками проекта: подрядчик или строительный контроль задаёт вопрос проектировщику или заказчику, получает ответ и фиксирует его как официальное решение. Основная сущность — запрос с приоритетом, статусом, автором, ответственными и привязкой к ресурсу или проекту; переписка ведётся сообщениями, одно из которых может быть помечено как решение. Приоритеты и статусы не захардкожены, а конфигурируются на уровне компании и ресурса через модели наборов приоритетов и статусов со своим цветом, что позволяет каждой организации настроить собственный регламент обработки запросов. Ведётся полный журнал изменений полей запроса с человекочитаемым рендерингом «было → стало», включая изменения атрибутов. Запросы поддерживают копирование, вложения и фильтрацию, а участники получают уведомления по мере движения запроса.
Технически бэкенд разложен на Django-приложения запросов, сообщений, приоритетов, статусов, истории изменений, уведомлений и общего ядра; версионированный API собирается из отдельных роутеров каждого приложения и публикуется под `/api/v1/`. Ключевые эндпоинты: фильтрация запросов, CRUD запроса, копирование, создание и получение сообщений с фильтром по запросу, пометка сообщения решением. Все модели наследуют базовую модель с мягким удалением и таймстампами; изоляция арендаторов обеспечивается фильтром по компании и правами на уровне объектов, а аутентификация — stateless-JWT с тремя вариантами разбора токена, включая Zitadel с упакованными в base64 клеймами. Атрибуты запросов подтягиваются из внешнего сервиса EAV, оттуда же берутся имена ресурсов и пользователей — все вызовы по httpx с обработкой ошибок внешнего API. Уведомления и рассылка писем вынесены в Celery. Фронтенд — remote-модуль Module Federation с корневым стором и маршрутизатором, работающий через общий `httpService` с сервисом rfi и отдельным списком хостов других микрофронтендов; вложения адресуются через имя модели в сервисе вложений. Не подтверждено, публикует ли сервис события в Kafka.
## stamp-verification
Репозитории: pdm/stamp-verification-frontend — публичная статическая страница проверки штампа по QR-коду; бэкенд отдельного репозитория не имеет — обслуживается публичным эндпоинтом pdm/documentation-api, данные QR-меток ведутся в pdm/documentation-api-v2. Стек: фронтенд — статический сайт без сборщика и фреймворка (HTML, vanilla JS с `fetch`, moment.js, CSS), счётчик веб-аналитики; бэкенд — Go (gorilla/mux, обработчик публичной информации о документе, клиент к flows, go-pg и миграции по PostgreSQL).
Компонент решает задачу подтверждения подлинности бумажной или PDF-копии проектного документа: на выпущенный документ наносится QR-код (штамп), и любой человек — прораб на площадке, инспектор, представитель заказчика — сканирует его телефоном и попадает на публичную страницу проверки, где видит, какому документу и какой его странице соответствует код и в каком состоянии этот документ находится в системе. Это закрывает типичную проблему стройки — работу по устаревшей или неутверждённой версии чертежа. Проверка не требует авторизации в платформе, поэтому доступна и внешним подрядчикам. Метка привязана к конкретному документу, комплекту, странице и позиции на листе, что позволяет отличать оригинальный штамп от произвольно скопированного. У документа в модели данных предусмотрены признаки наличия QR, штампа, электронной подписи и публичной ссылки — то есть QR-штамп встроен в общий механизм маркировки и публикации документов.
Технически фронтенд — один HTML-файл с inline-логикой: скрипт извлекает идентификатор метки и номер страницы из URL, выбирает базовый хост в зависимости от контура и делает запрос на публичный эндпоинт `documentations/api/v1/public/qr/{public_uuid}/document_info`, после чего отрисовывает карточку документа и раскрывающийся блок истории изменений; даты форматируются moment.js с локалями. Серверная часть находится в documentation-api: маршрут зарегистрирован в публичном контуре и обслуживается отдельным пакетом разметки, который читает документ из своего хранилища и дополнительно запрашивает состояние согласования через клиент к flows — то есть статус согласования на странице проверки берётся из компонента reviews. Сами метки хранятся в таблице `document_qr`: публичный идентификатор, ссылки на документ и комплект, автор, отметка времени, признак обработки, координаты, тип позиционирования и список страниц. Рядом с этим маршрутом в коде есть пометка о постепенном проксировании части эндпоинтов в cde-api под флагом конфигурации. Генерация и нанесение QR на PDF в изученном коде не найдены — соответствующие сервисные пакеты в v2 пусты, эта часть, вероятно, выполняется отдельным заданием обработки.
## subscriptions
Репозитории: pdm/sarex-subscriptions — Django-сервис подписок и рассылки уведомлений (приложения подписок, уведомлений и получателей). Стек: Python, Django 4.1 + DRF, django-filter, Jinja2, PostgreSQL + PostGIS с TimescaleDB (гипертаблицы), python-telegram-bot, SMTP и Mailgun HTTP API, requests с ретраями, OpenTelemetry.
Компонент отвечает за то, чтобы пользователи получали уведомления о значимых изменениях в проектных данных без ручного отслеживания. Пользователь или администратор компании оформляет подписку на объект определённого типа — модель подписки хранит имя модели (например, документ), имя сервиса, компанию и расписание доставки. Поддерживаются периодичности «дважды в день» (по умолчанию 9:00 и 17:00), «ежедневно», «раз в неделю» с выбором дня и «немедленно», то есть подписчик может получать либо мгновенные оповещения, либо дайджест за период. Получатели описаны отдельной сущностью с именем, e-mail, телефоном, идентификатором чата Telegram и ссылкой на пользователя, что позволяет доставлять одно и то же событие в разные каналы. Тексты писем задаются шаблонами уведомлений, привязанными к модели, типу события (создание, редактирование, удаление, копирование, чтение) и статусу события; шаблон может быть общим для всех компаний или привязанным к арендатору. Применяется на всём жизненном цикле проекта — подписка на документ, комплект или объект и получение уведомлений о его правках и передачах.
Технически сервис не слушает брокер, а периодически опрашивает журнал системных событий: сервисный слой ходит по HTTP в компонент system-log и забирает события по фильтру, затем доразрешает пользователей и документы для подстановки в шаблон. Логика вынесена в management-команды периодических и мгновенных уведомлений, которые запускают соответствующие сценарии; в репозитории сосуществуют две версии пайплайна. Модель хранения: событие уведомления с временем регистрации как Timescale-полем, ключом маршрутизации и JSON-атрибутами; транзакция уведомления со статусами «новая / в обработке / успешно / ошибка», временем начала и завершения и текстом ошибки; сообщение с типом канала, темой, текстом и связью с получателями; отправленное уведомление с уникальным ограничением по подписке и началу окна — защита от повторной отправки одного окна. Отправка реализована взаимозаменяемыми сервисами через общий протокол: SMTP, Mailgun и Telegram. Наружу выставлен REST-API на DRF по подпискам с фильтрами по компании и сервису, получателям и уведомлениям, плюс стандартная админка Django. Конфигурация планировщика, запускающего команды, в репозитории не найдена — вероятно, это CronJob уровня кластера.
## system-log
Репозитории: platform/system-log — HTTP-API приёма и выборки событий аудита; platform/system-log-worker — фоновый обогатитель записей журнала. Стек: Go, Fiber, pgx/pgxpool + Squirrel, PostgreSQL, SQL-миграции с применением на старте, собственный пакет Kafka-коннектора на sarama с TLS и SASL/SCRAM, OpenTelemetry, OpenAPI-схема; в воркере — resty и cron.
Компонент — централизованный журнал системных событий (аудит) всей платформы: любой сервис отправляет сюда факт «кто, что и над чем сделал». Запись описывается полями актора, имени модели (документ, инспекция, задача проекта), идентификатора объекта в его домене (числового, UUID или пути), имени события (создание, редактирование, удаление, копирование, передача), подстатуса события (например, для редактирования — добавление комплекта, передача документа, переименование), произвольных метаданных в JSON и свободного текстового сообщения. Дополнительно хранятся идентификаторы цели, ресурса и компании, что позволяет строить ленты активности в разрезе компании и конкретного объекта. Журнал используется не только для прослеживаемости: компонент subscriptions вычитывает из него события, чтобы рассылать уведомления подписчикам, то есть system-log выступает источником изменений для механизма оповещений. На уровне жизненного цикла проекта это сквозной слой прослеживаемости изменений документации и задач.
Архитектура — классическая слоистая: бинарник HTTP-сервера → приложение с запуском сервера и миграций → контроллер v0 с роутером, DTO и валидацией → сценарии → сервисы → репозиторий. API версии v0: POST принимает пакет записей и пишет его в PostgreSQL батчем, валидация требует ровно один из идентификаторов экземпляра; GET отдаёт постраничную выборку с фильтрами по акторам, именам событий и моделей, идентификаторам экземпляров и ресурсов, целям, компании и диапазону времени регистрации, с сортировкой по убыванию времени и ответом со счётчиком, лимитом, смещением и ссылками на соседние страницы; запрос собирается конструктором Squirrel. В репозитории есть опция подключения Kafka-коннектора с продюсером и консьюмером, однако основной путь записи — синхронный HTTP плюс Postgres. Отдельный сервис-воркер решает задачу дообогащения: cron-джобы с интервалом 20 и 30 секунд выбирают записи без идентификатора компании по моделям документа и задачи проекта, через REST-клиенты определяют компанию (документы запрашиваются батчами по 500) и проставляют её вместе с флагом обработки в той же таблице. Используется ли Kafka-коннектор в проде и включена ли на таблице гипертаблица TimescaleDB, по коду не устанавливается.
## transmittal
Репозитории: pdm/transmittal-api — бэкенд сопроводительных писем и передач; pdm/transmittal-frontend — микрофронтенд трансмитталов. Стек: Python 3.12, FastAPI, Pydantic v2, async SQLAlchemy + Alembic, PostgreSQL (UUID, JSONB, массивы, интервалы), taskiq + RabbitMQ, boto3/S3, Jinja2 и собственный конвертер HTML → PDF, Mailgun и SMTP, httpx, PyJWT, OpenTelemetry; фронтенд — TypeScript, React, MobX, Material-UI, Webpack 5 Module Federation, внутренние `ui-kit` и `sdk-js`.
Компонент реализует формальную передачу комплектов проектной документации между участниками стройки — трансмиттал (сопроводительное письмо) с фиксацией состава, отправителя, получателей, сроков и результата. Пользователь формирует трансмиттал в рамках проекта, включает в него версии документов и комплектов, назначает получателей (по пользователям, отделам и ролям), задаёт срок и признак автоотправки. Получатели принимают или отклоняют передачу с комментарием — эти действия складываются в историю и в пошаговый маршрут. По завершении формируется акт передачи в PDF, доступный по временной ссылке. Отдельная сущность — шаблоны трансмитталов, задающие типовой состав получателей, допустимых инициаторов, интервал срока и текст; на фронтенде им отведён собственный раздел со списком, фильтрами, включением и переименованием. Трансмиттал связывается с согласованиями, то есть закрывает цикл «выдал документацию → получил замечания». Автоматическая инициация передачи после согласования настраивается на стороне flows.
Бэкенд построен по слоям контроллер → сценарий → репозиторий → сущность и DTO. Публичный API включает создание, списки и поиск (в том числе по ресурсам), справочники глобальных статусов и статусов, счётчик открытых трансмитталов пользователя, приём и отклонение, получение и удаление, выдачу ссылки на акт и проверку его готовности, привязку согласования, а также работу с шаблонами и шагами; внутренний контур отдаёт трансмитталы по идентификаторам комплектов для других сервисов. Схема БД: справочники статусов (с текстом штампа и признаком системного), шагов и действий; агрегат трансмиттала с ресурсом, компанией, автором, статусом, текущим шагом, массивом шагов, получателями в JSONB, номером, уникальным в пределах компании, признаками автоотправки и готовности акта и отметками отправки и получения; версии документов со связью с комплектом и признаком акта; действия пользователя с комментарием и массивами подразделений и ролей; шаблоны и связь с согласованиями. Интеграции — репозитории Django-монолита (пользователи, отделы, должности), документации, flows и ресурсов, сервис разметки (штампы, QR, ЭЦП), S3 для актов и почтовые сервисы. Асинхронная часть — брокер taskiq на RabbitMQ с ретраями: задачи уведомлений получателей и отправителя и генерации акта, плюс отдельные CLI-точки генерации акта, обработки просроченных трансмитталов и наполнения системных справочников.
## workspaces
Репозитории: pdm/workspaces-api — Go-бэкенд рабочих пространств, состояний и приложений; platform/workspaces-frontend — микрофронтенд v1; platform/workspace-v2-frontend — микрофронтенд v2. Стек: Go (gorilla/mux, go-pg с миграциями в коде, zap, Prometheus, Sentry, JWT на RSA), PostgreSQL; фронтенды — TypeScript, React, MobX, Material-UI, Webpack 5 Module Federation, внутренний `viewer` (3D/BIM/облака точек), Cypress со сравнением скриншотов, Jest; в v2 дополнительно кеш в IndexedDB и скрипты замера производительности на Puppeteer.
Рабочее пространство — это сцена, в которой пользователь одновременно работает с набором проектных данных: BIM-моделями, облаками точек, PDF-чертежами, панорамами и фотографиями, привязанными к объекту строительства. Пользователь добавляет в пространство документы и комплекты, настраивает их отображение (видимость, цветовые схемы, раскраска элементов по статусам и атрибутам, фильтры по свойствам BIM-элементов) и сохраняет результат как именованное состояние, к которому можно вернуться или которым можно поделиться; есть состояние по умолчанию, неудаляемые состояния и динамические состояния — сценарии с привязкой к времени или видео. Второй ключевой сценарий — приложения: в пространство можно устанавливать прикладные модули компании и создавать их экземпляры, которые подгружаются во фронтенд как отдельные федеративные модули; так в сцену встраиваются, например, замечания. Пространства и документы поддерживают архивирование и восстановление, что важно при закрытии этапов проекта. В v2 набор сценариев расширен: работа с атрибутами EAV, анализ и экспорт BIM-элементов, история статусов элемента, ресурсы элемента, отклонения облака точек с цветовыми пресетами.
Бэкенд единый для обеих версий фронтенда. Роутинг делится на публичный контур (карточка пространства, архивирование и восстановление, сброс кеша, изменение и архивирование документов, CRUD состояний и динамических состояний, добавление и удаление документов в пространстве, управление приложениями компании и их экземплярами) и два внутренних набора. Внутренний контур v1 содержит создание пространства с резолвом комплектов в документы с настраиваемым параллелизмом, внутренний контур v2 — отдельную процедуру создания пространства, батч-проверку принадлежности пространств к v2, удаление и восстановление документов. Именно эта пара внутренних наборов и миграции показывают соотношение версий: v2 — не отдельный сервис, а вторая модель данных внутри того же API (собственная таблица документов, создание без резолва комплектов), сосуществующая с v1; фронтенд v2 читает тот же эндпоинт карточки пространства, но ожидает в ответе поле документов v2. Хранилище — PostgreSQL через go-pg, внешние зависимости — клиенты документации и комплектов, есть CLI для сброса кеша. Оба фронтенда — remote-модули Module Federation с одинаковой архитектурой (декларативный реестр эндпоинтов, MobX-сторы пространств, приложений и документов), но v2 заметно шире по функциональности и дополнительно обращается к файловому сервису за геометрией и панорамами, к EAV за атрибутами и к шлюзу за динамическими состояниями. Выведен ли v1 из эксплуатации, по репозиториям не видно.