Skip to main content
Nodes registered by Core. A handler is resolved by the pair (type, version); every Core node is currently at version 1. type is what a flow definition stores and what the registry resolves against. It is unique across every registered handler, Core and extension alike, so an extension picking a name that Core might later want is a collision waiting to happen — prefix yours.

Nodes the engine treats specially

Most nodes execute and return a handle. Four alter the shape of execution itself:

The call node and outbound addresses

A flow author controls the URL a call node requests, often through a template over live state, so Core treats the target as untrusted. A request never reaches a private, loopback, link-local, reserved or cloud-metadata address (for example 127.0.0.1, 10.0.0.0/8, 169.254.169.254, ::1, fd00::/8). The check holds however the address is reached: written directly, behind a DNS name, behind a name that answers differently the second time, or at the end of a redirect.
  • The host name is resolved by Core, every returned address must be public, and the connection is then made to exactly those addresses.
  • Every redirect hop is checked again. Redirects stay on, up to 5, http and https only.
  • Address forms that other software would read as an IPv4 address without being a canonical one (2130706433, 0x7f.1, 127.1, 0177.0.0.1) are refused.
  • Any port is allowed on a public address.
A refused call takes the error handle with error_code = egress_denied. The node metadata and the builder test call carry the host and a reason (private, loopback, link_local, reserved, multicast, unspecified, metadata, invalid_host or scheme_not_allowed), never the resolved address. A name that does not resolve is still transport_failure. A refused call still counts as one call execution. An operator can allow trusted internal targets with FLOW_EGRESS_ALLOW; see Configuration. Cloud metadata addresses can never be allowed.
An extension that makes its own HTTP request from a flow parameter is not covered by this check. Such a request must refuse private, loopback, link-local and cloud-metadata addresses after the name is resolved and on every redirect hop. A shared contract for this will arrive with the first Solution that needs outbound HTTP; until then the extension carries the requirement itself.

Declaring a node

type, version, label, and category come from the handler. Core handlers extend AbstractVersionedHandler, which derives them from a TYPE constant:
The base class defaults label() to a humanised form of the type and category() to Core; override either to place a node elsewhere in the builder’s palette. See Handler contract for the full interface and Versioning for when the version must change.