NODEDC_PLATFORM/docs/ADR_EXTERNAL_PROVIDER_DATA_...

144 lines
9.8 KiB
Markdown
Raw Permalink 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.

# ADR: канон External Provider Data Plane
Статус: **superseded**.
Дата: 2026-07-13.
Владелец решения: NODE.DC Platform.
> Заменено 2026-07-14 документом
> [`ADR_L2_OWNED_EXTERNAL_CONNECTORS.md`](ADR_L2_OWNED_EXTERNAL_CONNECTORS.md).
> Этот черновик неверно помещал provider adapter, normalisation и collection
> policy в `services/<provider>-gateway`. Новое правило: adapter принадлежит
> изолированному L2 workflow; Platform Data Plane остаётся provider-neutral.
## Контекст
Клиент может подключить к NODE.DC любой внешний продукт: телеметрию, ERP,
роботов, энергетику, BIM-систему или иной источник данных. Gelios Pro для
Gelios — первый конкретный поставщик для проверки канона, а не исключительная
архитектурная ветка. Нельзя превращать Engine workflow, Ontology Core или общую БД Platform
в место, куда попадают токены, raw payloads и частная логика каждого API.
Нужна повторяемая форма, в которой новый provider добавляется как отдельный
adapter, но получает общие правила scope, секретов, collection, хранения,
read-model, аудита и безопасной публикации в NDC.
## Решение
1. В `platform/packages/external-provider-contract` живёт общий versioned
контракт интеграции. Это не runtime и не база данных. Он задаёт форму
`provider`, `connection`, `capability catalog`, `credential reference`,
`access scope`, `field policy`, `collection profile`, `retention policy`,
`read model` и красный command-domain.
2. Каждый provider получает самостоятельный app-owned adapter в
`platform/services/<provider>-gateway`. Первый экземпляр —
`platform/services/gelios-gateway`. Adapter владеет intake contract, rate
budget, normalisation, collection policy, storage и своим internal
read/realtime API. Сам provider secret остаётся в Engine Credentials и
доступен только назначенному защищённому execution workflow.
3. Один provider service может обслуживать много клиентов. Каждая строка,
cursor, audit-event и read-model обязана иметь `tenant_id` и
`connection_id`; видимость provider account сама по себе не является
продуктовым scope. Для клиента с отдельными требованиями изоляции допустим
отдельный deployment/database profile без изменения контракта.
4. База принадлежит adapter-сервису, а не Ontology Core, Engine, Tasker или
общему Platform Postgres. Для пространственно-временного Gelios-кейса
базой служит PostgreSQL 16 + TimescaleDB + PostGIS (`gelios-postgres`).
Другой provider может выбрать иной storage engine только через явный ADR,
сохранив внешний контракт.
5. Ontology Core хранит только provider-neutral и provider-specific смыслы,
связи, правила и контракты. Он не хранит credentials, runtime telemetry,
customer raw payloads или renderer objects. Enforcement остаётся в
gateway/adapters. Engine Credentials хранит provider secret в границе
специально назначенного execution workflow; значение не сериализуется в
граф, ontology, логи, read-model или UI.
6. Engine L2 Collector использует credential reference и получает разрешённые
данные поставщика. Он передаёт в adapter только аутентифицированный нормализованный
intake payload. Остальные L2 workflow получают исключительно scoped
internal API/event contract и не читают gateway DB напрямую.
## Каноническая форма нового подключения
```text
Client / tenant
-> Engine Credential + protected Collector workflow
-> provider connection instance
-> provider adapter (safe intake policy + normalizer)
-> provider-owned storage and projections
-> internal read/realtime contract
-> L2 workflow / approved interface binding
-> renderer adapter
```
Каждый новый provider добавляет только свой adapter package, capability
catalog, schema mappings, scrubbed fixtures и domain ontology package. Он не
добавляет отдельную схему доступа к Engine/Studio и не создаёт прямой путь из
browser в provider API.
## Полнота данных без неконтролируемого объёма
«Предусмотреть все данные» означает каталогизировать каждую provider
capability и поле, а не опрашивать весь account на максимальной частоте.
Collection profile явно решает, какие safe-read capabilities, поля, scope и
частота включены в конкретной connection instance.
| Слой | Что хранится | Режим |
| --- | --- | --- |
| Capability catalog | documented endpoint/read-field/command capability и его риск | versioned source + ontology |
| Inventory/configuration | units, devices, groups, sensors, custom definitions | медленный reconcile |
| Current projection | последняя разрешённая позиция, состояние и display fields | idempotent upsert |
| Event history | нормализованные события и approved measurements | append-only, partitioned |
| Raw envelope | полный safe-read ответ с provenance и hash | restricted cold layer, retention-bound |
| Aggregates/features | rollups и признаки для аналитики/предиктива | derived, replaceable |
Raw envelope не выдаётся UI и не становится таблицей «всё в JSON навсегда».
Вначале он может быть compressed/partitioned storage с метаданными в БД; при
реальном объёме переносится в object storage, а PostgreSQL хранит immutable
index, hash, policy и ссылку. Retention, raw depth и downsampling утверждаются
после замера сообщений/сек, размера payload, требуемой истории, RPO/RTO и
стоимости. Так инженер может запросить ранее не показанное поле из
каталога/архива, не раздувая горячую read-модель.
## Realtime и интерфейс
Частота provider collection, обновления `current projection` и выдачи в UI —
три разные настройки. Например, map consumer может получать выбранную
read-модель раз в 3 секунды, но это не даёт ему права опрашивать Gelios раз в
3 секунды или создавать отдельный polling loop на каждого зрителя.
Gateway сначала обновляет одну current projection и публикует change event.
L2/Map binding затем может sampling/throttle этот поток по утверждённой
настройке интерфейса. Источник истины для live state — gateway storage, не
долгоживущий workflow и не Cesium session.
## Commands: моделируются, но не подключаются
Command templates, параметры, delivery states и audit входят в capability
catalog и ontology полностью. Read adapter не содержит send route и не
использует command capability. В будущем command execution создаётся только
как отдельный `provider-command-gateway`/red-domain deployment с явным
человеческим подтверждением, role/scope check, idempotency, audit и отдельным
security review. До этого команда не может быть отправлена из collector, L2,
Map или AI Workspace.
## Обязательные артефакты каждого adapter
- `provider manifest`: provider id, adapter version, auth modes, rate limits;
- capability and field catalog: read/write classification, source evidence,
pagination and error semantics;
- connection profile: tenant, secret reference, approved scope, field policy,
collection and retention profile;
- normalised contract and migrations; scrubbed fixtures and contract tests;
- health/metrics/audit without secrets or raw personal data;
- ontology package with stable subjects, relations and guardrails;
- internal read/realtime API contract; no browser/provider bypass.
## Не решено этим ADR
- конкретный deployment topology и HA/PITR target для каждого volume;
- выбор object storage после real-volume measurement;
- L2 stream execution contract и Module Studio binding implementation;
- параметры first Gelios collection profile и owner-approved connection scope.
Gelios-specific применение этого решения описано в
`docs/ADR_GELIOS_DATA_PLANE.md`.