16 KiB
ADR: внешние коннекторы принадлежат NDC L2 workflow
Статус: accepted. Дата: 2026-07-16. Владелец решения: NODE.DC Platform.
Контекст
NODE.DC состоит из двух разных слоёв:
- платформенный слой даёт NDC L1, NDC L2, Ontology, credentials, Data Products и Foundry-boundaries;
- пользовательские автоматизации собирают из этих возможностей конкретную бизнес-логику.
Новый account, provider credential, tenant, расписание или интерфейс не должны создавать новый platform service и не должны требовать изменения NODE.DC source. Команда NODE.DC подключается только для нового поставщика либо для расширения подтверждённых capabilities и ontology уже поддержанного поставщика.
Gelios — первый живой источник и acceptance-кейс этого канона, а не отдельная
архитектурная ветка. Документ заменяет provider-runtime решения из
ADR_EXTERNAL_PROVIDER_DATA_PLANE.md и ADR_GELIOS_DATA_PLANE.md; те
документы остаются только историей решения.
Решение
1. Пакет поставщика создаётся один раз
Каждый поддержанный поставщик получает один версионируемый provider package. Он является знанием платформы о внешнем API и содержит:
- стабильный
providerIdи версии подтверждённого API; - credential contract без значения секрета;
- каталог safe-read capabilities, pagination/rate-limit metadata и response shapes;
- mappings из provider fields в версии Ontology;
- совместимые Data Products и scrubbed contract fixtures;
- явно отделённый каталог команд без активного command transport.
Пакет не является runtime service, scheduler, базой данных или customer configuration. Он расширяется только когда фактически подтверждён новый API, новый тип данных или новая ontology revision.
Одна учётная запись поставщика задаётся данными, а не кодом:
provider package + credential reference + connection profile + NDC L2 workflow instance
Поэтому второй account или другая provider credential pair создаёт ещё один credential/profile и workflow instance. Платформенный source, Data Plane и Foundry при этом не меняются.
2. NDC L1 проектирует, NDC L2 workflow исполняет
NDC L1 получает пользовательское намерение, проверяет доступные capabilities и Ontology, проектирует или изменяет разрешённый NDC L2 workflow через NDC MCP и анализирует execution evidence.
Один изолированный NDC L2 workflow представляет один connection instance и владеет исполняемой механикой:
- safe-read вызовами provider API через credential reference;
- pagination, cursor, retry, rate limit, batch size и collection cadence;
- проверкой response shape и разбиением ответа на items;
- mapping к точной ontology revision;
- idempotency, watermark и публикацией canonical facts;
- private workflow state, когда он действительно нужен.
Provider-specific mapping сначала реализуется штатными workflow nodes и малым Code-преобразователем. Это позволяет проверить реальный API без преждевременного создания custom nodes. В custom NDC nodes переносится только повторившаяся и доказанная платформенная boundary-механика, а не уникальная логика поставщика.
3. Credentials являются данными connection instance
Gelios выдаёт ровно два provider secrets: access token и refresh token. Текущий
HTTP request binding httpBearerAuth использует access token. Автоматический
refresh в принятом runtime не доказан, поэтому provider package фиксирует его
как operator_managed; ни один из token values не попадает в graph, package,
Ontology, Data Plane, Foundry, execution logs, MCP или Ops. Новый account или
provider-issued token pair означает новые native credential records и
connection instance, но не новую Platform-сущность.
Локальное имя credential (например, с суффиксом read access) не является
provider scope. В target-контракте Read-классификацию задаёт allowlisted
method/endpoint в capability catalog и Engine workflow policy; тот же access
token нельзя называть отдельным «read token» или «write token» только из-за
label. Сейчас deployed Engine safe-ref policy ограничивает generic HTTP
credential только по host, но ещё не связывает его с package/version и exact
method/path. Поэтому Gelios GET /api/v1/units пока является декларативной
capability, а не завершённой runtime-security гарантией; canonical acceptance
требует capability-bound Engine policy и её MCP proof.
Writer capability для публикации Data Product — отдельный внутренний native NDC L2 credential, не третий Gelios token. Generic Engine/Platform control plane генерирует capability внутри native credential boundary, сохраняет её там же и передаёт EDP только SHA-256 digest вместе с точным provider, connection и набором Data Products. Пользователь и MCP получают только opaque reference/status. Capability не записывается в graph, provider package, env, file, Ops или trace и не копируется через пользовательский UI.
Широкий credential sink, resolver/daemon с произвольной записью secret и любой
provider-specific credential service запрещены. Нужна одна узкая операция
ensure data-product publish grant: scope выводится из granted L1→L2 target,
зарегистрированного connection profile и разрешённого Data Product; issuance,
rotation и native binding должны быть idempotent, CAS/crash-safe и auditable.
Engine генерирует capability внутри credential boundary и передаёт EDP только
SHA-256 digest через idempotent binding key + generation; EDP не возвращает
plaintext. Новая generation создаётся до переключения node reference, а старая
отзывается только после успешного bind/acceptance.
Старые ручные EDP POST/rotate endpoints, которые возвращают capability один
раз, включаются отдельным legacy-флагом и не входят в canonical acceptance.
Digest-only managed endpoint имеет независимый флаг и принимает только
Ed25519-signed Engine service requests: exact audience/method/request target/raw
body hash входят в подпись, timestamp ограничен по skew, nonce защищён bounded
fail-closed replay cache. Legacy provisioner bearer на managed routes не
действует. EDP получает только deployment public key; matching private key
остаётся только внутри Engine server boundary. Endpoint остаётся выключенным,
пока key provisioning, Engine signer и exact native credential binding policy
не пройдут runtime acceptance.
В deployed Engine MCP этой операции пока нет — это текущий platform gap перед
canonical publish proof, а не действие пользователя. Это решение не заявляет
автоматический refresh Gelios: до отдельного runtime proof он остаётся
operator_managed.
4. External Data Plane нейтрален к поставщику
Platform предоставляет один versioned External Data Plane. Он принимает canonical facts через scoped writer binding, хранит current/history projections и публикует snapshot/patch contracts. В нём запрещены:
- ветвления по provider, customer, account, entity или renderer;
- provider field mapping и бизнес-фильтрация;
- provider credential, endpoint, schedule или command transport;
- caller-supplied tenant/connection scope.
NDC Data Product Publish отправляет только
nodedc.data-product.publish/v1. External Data Plane materializes immutable
scope из writer binding, проверяет разрешённый Data Product и его ontology
revision, затем сохраняет batch.
EDP runtime импортирует только package subpath
@nodedc/external-provider-contract/data-plane. Его deploy artifact и image
содержат только provider-neutral wire validators; providers/gelios, mappings,
fixtures и tests туда не входят. Изменение или добавление provider package не
пересобирает и не перезапускает EDP: каталог поставщиков разворачивается через
Engine/Ontology/control-plane путь отдельно.
Collection cadence, history cadence и presentation cadence независимы:
- NDC L2 забирает источник с частотой, нужной бизнес-задаче;
- current projection принимает каждое валидное изменение;
- declarative history policy может хранить все точки или sampling;
- Foundry читает snapshot+patch и отдельно ограничивает частоту render.
Для разной частоты БД и интерфейса не создаются второй provider sink, отдельный gateway или параллельный прямой push в renderer.
5. Полнота означает все сущности разрешённой capability
Connection profile выбирает safe-read capabilities, а не зашитый в Platform список entity IDs. Если разрешённый endpoint возвращает все доступные credential сущности, NDC L2 обрабатывает каждый валидный item. Новый объект появляется автоматически.
Пользовательская фильтрация, слои и видимость находятся после сбора — в automation/Data Product/Foundry. Технические ограничения допустимы только как pagination, quota, batch size, backpressure и защита от повреждённого ответа.
6. Custom NDC nodes ограничены платформенными границами
Первый канонический набор:
NDC Data Product Publish— NDC L2 → External Data Plane;NDC Data Product Read— scoped snapshot/patch read;NDC Foundry Binding— control-plane связь Data Product сApplication → Page → typed slot.
Эти nodes не содержат provider ID, tenant ID, connection ID, endpoint, token,
mapping или cadence. Runtime package сохраняет технический namespace
n8n-nodes-ndc.*, но пользовательские документы и интерфейсы используют
только терминологию NDC.
NDC Foundry Binding не транспортирует каждый realtime tick. Он создаёт
постоянную связь интерфейса с Data Product; Foundry затем читает его
snapshot+patch contract.
7. Реальный Gelios acceptance-кейс
Первая версия provider package должна доказать путь:
Gelios safe read → все доступные units → map.moving_object facts → fleet.positions.current.v1 → Foundry map
Canonical product использует ontology revision
ontology.map.moving_object.v1 и только объявленные snake_case поля. NDC L2
не передаёт caller scope и не собирает собственный batch envelope вокруг
NDC Data Product Publish.
Acceptance выполняется по порядку:
- Platform выполняет generic
ensure data-product publish grant, выпускает scoped EDP binding и атомарно сохраняет capability в native NDC L2 Credentials; - NDC MCP видит только совместимый opaque writer credential reference/status;
- применить подтверждённый graph patch без legacy intake;
- validate/preflight;
- один успешный manual run и проверка execution/trace/Data Product;
- только затем отдельным изменением добавить Schedule Trigger;
- после доказанного snapshot+patch подключить Foundry binding.
8. Capacity и topology
Количество одновременно активных NDC L2 проектов ограничивается фактическими ресурсами железа и профилем нагрузки. Пока capacity проверяется оператором и не автоматизируется. Канон не объявляет отдельные worker/webhook generations или high-load topology, которых ещё нет в принятом runtime.
Последствия
services/<provider>-gatewayне является частью канона и не создаётся для новых provider integrations. Существующий self-hosted Gelios Gateway и его Timescale volume остаются frozen compatibility contour, воспроизводятся из source/deploy и не изменяются новым L2 pilot без отдельного решения.- Новый account или provider-issued access/refresh pair — configuration change, а не platform release.
- Новый provider или неподдержанная capability — versioned provider/Ontology change с contract tests.
- Существующий legacy L1/SDK workflow является frozen compatibility boundary: новый L2 pilot его не редактирует, не отзывает его credential и не ставит его вывод условием acceptance.
- Legacy
/internal/data-plane/v1/intakeостаётся выключенным migration-only route и не используется новыми NDC L2 workflows. - Команды устройствам остаются отдельным red-domain контуром с явным подтверждением, scope, idempotency и аудитом.
- Foundry развивается после доказанного Data Product path; provider API и credentials в Foundry не попадают.