NODEDC_PLATFORM/packages/n8n-nodes-ndc
Codex 3446f3edc2 feat(platform): add replaceable geozone data layer 2026-07-20 21:48:27 +03:00
..
credentials feat(n8n): add rotating provider access credential 2026-07-19 10:11:56 +03:00
icons feat(engine): add private NDC nodes and ontology bridge 2026-07-16 02:23:45 +03:00
nodes feat(platform): add replaceable geozone data layer 2026-07-20 21:48:27 +03:00
test feat(platform): add replaceable geozone data layer 2026-07-20 21:48:27 +03:00
README.md feat(n8n): add rotating provider access credential 2026-07-19 10:11:56 +03:00
eslint.config.mjs feat(engine): add private NDC nodes and ontology bridge 2026-07-16 02:23:45 +03:00
package-lock.json feat(platform): add replaceable geozone data layer 2026-07-20 21:48:27 +03:00
package.json feat(platform): add replaceable geozone data layer 2026-07-20 21:48:27 +03:00
tsconfig.json feat(engine): add private NDC nodes and ontology bridge 2026-07-16 02:23:45 +03:00

README.md

n8n-nodes-ndc

Private NODE.DC node package for provider-neutral L2 workflows. It extends n8n through the supported private-node mechanism and does not patch Engine or n8n core.

Every custom node has an NDC display-name prefix. Runtime types are package qualified:

  • n8n-nodes-ndc.ndcDataProductPublish — publishes canonical facts into an approved Data Product.
  • n8n-nodes-ndc.ndcDataProductRead — reads the current snapshot or a bounded, cursor-paged history window of an approved Data Product.
  • n8n-nodes-ndc.ndcFoundryBinding — creates or updates a declarative Foundry page-slot binding. This is a control-plane operation, not a runtime data transport.

Security and scope

Workflow parameters contain no service URL, provider, tenant, connection, raw secret, or credential selector. Product selection is loaded from the catalog visible to the selected opaque capability. Service locations are operator-owned runtime overrides (the package defaults to the canonical internal service names, so the first deployment needs no extra Engine environment):

  • NDC_DATA_PLANE_BASE_URL
  • NDC_FOUNDRY_BASE_URL

The defaults are http://external-data-plane:18106 and http://nodedc-module-foundry:3333. They are provider-neutral Platform service addresses, not workflow configuration.

The writer, reader, and Foundry credential types contain only one password-protected opaque capability and are intentionally distinct. The separate NDC Provider Rotating Access API credential keeps the Gelios REST access and refresh pair inside native Engine Credentials. It exchanges the refresh token only against the fixed Gelios refresh endpoint, persists both rotated tokens through the supported expirable-credential lifecycle, and injects only the current access token into provider requests. Concurrent refresh attempts in the single-service L2 runtime are coalesced and briefly replay the same rotated pair so a stale caller cannot immediately spend the invalidated predecessor refresh token again. Provider identity, product version, ontology revision, persistence policy, and tenant scope are materialized by the receiving service from the grant. The node never accepts them from a workflow.

Fixed routes

  • GET /internal/data-plane/v1/writer/data-products
  • GET /internal/data-plane/v1/reader/data-products
  • POST /internal/data-plane/v1/data-products/:dataProductId/publish
  • GET /internal/data-plane/v1/data-products/:dataProductId/snapshot
  • GET /internal/data-plane/v1/data-products/:dataProductId/history
  • GET /internal/foundry/v1/data-products
  • POST /internal/foundry/v1/data-product-bindings

There is no fallback to a legacy intake route. NDC Foundry Binding uses the dedicated internal control-plane endpoint implemented by Foundry and fails closed when that route or its scoped workload grant is unavailable. Its canonical Map entity-stream slot defaults to points.

The binding command uses the versioned nodedc.foundry.binding-upsert/v1 schema. Its opaque ndc_fndbg_* workload grant is separate from the short-lived Foundry MCP capability used by AI Workspace and from the shared Platform service token. The receiving service materializes actor, owner and exact application/page/binding/product scope from that grant; none of those authorization claims are accepted from headers or workflow data.

NDC Data Product Read supports the bounded nodedc.data-product.snapshot/v1 contract. Its snapshot Page Size parameter is a safety ceiling, not pagination: the complete scoped current projection must fit within 5000 entity keys. A larger product returns data_product_snapshot_limit_exceeded; the node must not assemble independent pages or start a patch stream from an incomplete snapshot. Large products need stable partition Data Products.

History mode uses nodedc.data-product.history/v1 and requires a closed from/to interval. It supports provider-neutral sourceIds, a resolution that is a multiple of the Data Product native sampling interval, a limit up to 5000 points and an opaque keyset continuation cursor. The response stays as one envelope item so L2 logic can preserve query and nextCursor while iterating. The workflow never selects a database, provider, tenant or connection.

Publish input

Each incoming item must be either a canonical fact or { "fact": <fact> }:

{
  "sourceId": "fleet.unit.42",
  "semanticType": "map.moving_object",
  "observedAt": "2026-07-15T12:00:00.000Z",
  "attributes": {},
  "geometry": { "type": "Point", "coordinates": [37.61, 55.75] }
}

The node emits nodedc.data-product.publish/v1, enforces the 5000-fact and 64-KiB-per-attributes limits, rejects secret-like material in attributes, and derives stable run/idempotency identifiers from workflow execution context.

Build and verification

npm install
npm test
npm run lint

The package must be installed as an n8n private community package under the runtime user's community-package root:

/home/node/.n8n/nodes/node_modules/n8n-nodes-ndc

The parent /home/node/.n8n/nodes/package.json owns the pinned package registration. ~/.n8n/custom and N8N_CUSTOM_EXTENSIONS are deliberately not used: n8n loads those through the CUSTOM namespace, which would destroy the required n8n-nodes-ndc.* runtime types.

Deployment boundary

The Platform MCP catalog bridge preserves package-qualified custom runtime types, but Engine can expose these schemas only after this private package is installed through the community-package path and the bridge slice is deployed. Production installation uses a verified offline tarball, an immutable root-owned release, an atomic current/previous switch and a read-only mount; it does not run npm install inside a live container. This package deliberately does not patch Engine or n8n core.

The Platform-side release builder is:

node ../../infra/deploy-runner/build-n8n-private-extension-artifact.mjs \
  n8n-nodes-ndc-release-YYYYMMDD-NNN

Its canonical deploy component only stages and seals a digest-bound release under /volume1/docker/nodedc-platform/n8n-private-extensions; it does not activate anything in Engine. Activation is intentionally blocked until an Engine-owned deployment slice provides the exact read-only community-package mount, atomic release selection, all-process restart and MCP schema acceptance. The v2 rollback contract accepts a pre-activation, explicitly verified inactive baseline for the first activation; subsequent upgrades prefer a previous verified immutable release. The staged v1 0.1.0 release is never overwritten: this contract is published as a separate 0.1.1 release.