# Архитектура

## 1. Границы ответственности

### 1.1. Ядро системы (общее, переиспользуемое)

- API-contract framework (`list/scheme`, envelopes, error model).
- Module runtime (`install/uninstall`, dependency graph, module capabilities).
- Auth/session/permissions framework.
- Общая telemetry/realtime шина (`status`, WebSocket/MQTT).
- Базовый UI shell (карточки, fullscreen, layout, routing runtime).

### 1.2. Отраслевой изолят (`industry package`)

- отраслевые сущности и словари;
- отраслевые KPI, нормы и события отклонений;
- отраслевые сценарии управления/оркестрации;
- отраслевые UI-модули и формы;
- отраслевые интеграционные профили оборудования.

## 2. Правило совместимости

Любой отраслевой модуль обязан:

1. публиковаться через общий модульный реестр;
2. использовать единый envelope ответа и общие заголовки;
3. не изменять ядро API обратнонесовместимо;
4. подключать права через общую permission-модель;
5. хранить отраслевые параметры в отдельном namespace.

## 3. Технический контракт изоляции

### 3.1. Namespace модулей

Рекомендуемый префикс:

- `industry.<name>.<module>`
- примеры: `industry.poultry.climate`, `industry.poultry.flock`, `industry.swine.climate`

### 3.1.1. Правило модульной гранулярности (принятое D-002)

- Отрасль состоит из набора специализированных модулей.
- Для конкретной площадки допускается частичное включение модулей (не весь набор сразу).
- Каждый модуль владеет одной ключевой сущностью (`key_entity`).
- Модуль может строить агрегаты из других модулей (`enrichment`), но source-of-truth ключевой сущности остается у владельца.

### 3.1.2. Правило версионирования отраслевых модулей

- Формат версии отраслевого модуля: `MAJOR.MINOR.PATCH` (числовой semver).
- Для модулей одной отрасли в рамках активной release-линии `MAJOR` должен совпадать.
- Изменение `MAJOR`: обратнонесовместимые изменения API/контракта данных.
- Изменение `MINOR`: обратносовместимое расширение (новые поля, endpoint-ы, сценарии).
- Изменение `PATCH`: исправления без изменения контракта.
- Минимальная автоматическая проверка политики выполняется тестом `backend-go/internal/modules/catalog/versioning_policy_test.go`.

### 3.2. Namespace данных

- `tenant_id` + `industry_code` + `site_id` + `object_id`
- отраслевые таблицы и события не смешиваются без явного cross-industry представления.

### 3.3. Namespace конфигурации

- профиль отрасли (`industry_profile`)
- профиль оборудования (`equipment_profile`)
- профиль регламентов (`compliance_profile`)

### 3.4. Жизненный цикл нормативных профилей (принятое D-003)

- Нормативы и уставки хранятся в profile-конфигурациях.
- Формат обмена между хозяйствами: `YAML`.
- Профиль проходит состояния:
  - `draft`
  - `validated`
  - `published`
  - `archived`
- Каждая публикация создает новую версию (`version_id`, `created_at`, `created_by`, `change_note`).
- Откат выполняется как publish предыдущей версии с новым `version_id` и ссылкой `rollback_of`.

Минимальные операции profile-service:

- `exportYaml(profile_id, version_id)`
- `importYaml(industry_code, site_scope, yaml)`
- `validateProfile(profile_draft_id)`
- `publishProfile(profile_draft_id)`
- `rollbackProfile(profile_id, target_version_id)`

### 3.5. Контуры тревог (принятое D-004)

- `status` — единый системный контур тревог для общей операционной видимости.
- `industry alarm-bus` — специализированный отраслевой контур тревог и эскалаций.
- Правило синхронизации:
  - `industry alarm-bus -> status` публикует агрегированные/критические события;
  - `status -> industry alarm-bus` не является источником истины для отраслевых деталей.
- Ownership:
  - `status` хранит унифицированное событие;
  - отраслевой модуль хранит детальные причины, контекст и историю эскалаций.

## 4. Runtime модель подключения отрасли

1. В ядре активируется `industry dispatcher` (по `industry_code`).
2. Dispatcher подключает отраслевые manifests и backend plugins.
3. UI получает catalog/scheme и отображает отраслевые карточки.
4. Общие сервисы (`auth`, `status`, `modules`) остаются едиными.

### 4.0.1. Правило frontend workspace для poultry

- `poultry` отображается во frontend как единый workspace с изолированными submodule-экранами.
- В `cloud` primary-входом служит overview dashboard.
- В `edge-single` primary-входом служит тот же dashboard в fullscreen cards-layout:
  - карточки уплотняются под 10" HMI;
  - dashboard остается экраном общего контекста и KPI;
  - переход в детали модуля выполняется из карточек без отдельного canvas-режима.

### 4.1. Режимы по уровню развертывания (принятое D-001)

- `cloud` (master/tenant): multi-industry режим, несколько отраслей в одном контуре.
- `site/cabinet` (edge): single-industry режим, одна отрасль на одну инсталляцию.

### 4.2. Правило переключения отрасли

- В cloud переключение отрасли допустимо на уровне контекста (`tenant/site/object`).
- В edge переключение отрасли в runtime запрещено; смена отрасли выполняется через переинициализацию профиля инсталляции.

## 5. Минимальный пакет новой отрасли

Для каждой новой отрасли обязательно создать:

- `docs/industries/<industry>/README.md`
- `docs/industries/<industry>/architecture.md`
- `docs/industries/<industry>/tasks.md`
- `docs/industries/<industry>/source-instructions.md`

## 6. Матрица общих vs отраслевых модулей

- Общие: `overview`, `modules`, `status`, `auth`, `passkey`.
- Отраслевые: процессные панели, специализированные KPI, нормативы и сценарии.
- Гибридные: `tasks`, `charts` (общий каркас + отраслевые наборы метрик).

## 6.1. Метаданные отраслевого модуля

Минимальный набор metadata в каталоге модулей:

- `industry_code`
- `industry_scope` (`industry` | `hybrid`)
- `key_entity`
- `provides_enrichment_for` (опционально)

## 7. Контроль качества

- Contract tests: общие + отраслевые.
- E2E smoke: отдельно по каждой отрасли.
- Проверка изоляции данных: обязательна для каждого релиза отрасли.
- Проверка консистентности `status` и `industry alarm-bus`: обязательна для каждого релиза отрасли.
- Проверка и аудит cross-industry policy-решений (`allow/deny`) через `modules/access-audit`: обязательна для изменений прав и модульных операций.
