Protocols
A message arrives at a door, leaves on a call, and comes back as a response. This page describes those three moments and what the platform decides at each.
Inbound: the gate runs before the body
The access gate is closed by default. Starting without credentials is an explicit option that announces itself on every boot — not a silent default.
The decision is taken before the body. An unauthenticated caller causes two indexed queries and nothing else: no body byte read, no parsing, no artifact load. A contract consequence: a caller with no credential announcing an oversized body gets an authentication refusal, not a size refusal — the ceiling is internal state and is not disclosed before authentication.
The gRPC door
The gRPC door is a separate listener, started explicitly on its own port. A routed call passes through the same gate as the HTTP routes and the same delivery bracket, so deduplication, correlation and response memoisation work there with nothing written for them.
What the gRPC door does not do: streaming explicitly refused, a routing table built at start-up, a fault sequence with no deliverable body.
HTTP egress
The address of an outbound call can be computed from the message and from the installation’s configuration: it is a template, checked at publication like any other template, not a string concatenated at runtime.
When the backend answers with an error, that error body is available to the flow: the fault sequence can read it and compose a response from it. The response headers are available too, minus the sensitive ones, which are withheld at capture — not filtered later.
gRPC egress
gRPC egress works with dynamically loaded protobuf descriptors, and supports mutual TLS, a cascade of endpoints, and a circuit breaker per endpoint.
The response contract
The response to the caller is the flow’s output, unwrapped. There is no envelope, and the content type is derived from the body’s shape.
| Flow output | Response body | Content type |
|---|---|---|
| Object, array, number, boolean | Its JSON | application/json |
| String | The text verbatim, unquoted | text/plain; charset=utf-8 |
| Nothing | No bytes | Absent |
| XML document | The serialised XML | application/xml; charset=utf-8 |
- The flow declares its response status, on any step, including proxy semantics: the backend’s status becomes the response’s status.
- The flow dictates the response headers, on any step; for a repeated name the last writer wins, in execution order.
- Headers received from the backend are returned to the caller only if the flow declared them on an allowlist. With no list, none is returned.
A message’s ceiling
There is no single installation-wide ceiling. The ceiling is resolved per access point, in three layers: the installation’s value, the flow’s value, and an egress step’s value. A body announcing a size above the ceiling is refused without a byte of it being read.
SOAP
A SOAP 1.1 or 1.2 request is unwrapped on /run, the flow works on the Body content, and the response leaves in an envelope of the same version. A malformed envelope is 400 with a SOAP Fault, and a failing flow returns a SOAP Fault, not a success body. On egress, a step that declares the version wraps the body and sends SOAPAction.
A soap_version: outside the {1.1, 1.2} vocabulary is refused at publication — on ordinary steps, on ## Fault: steps and inside expanded libraries — not a silent abandonment of SOAP mode.
GET /flows/{tenant}/{flow}/wsdl generates a WSDL 1.1 document/literal from the published flow’s SOAP configuration; a flow without SOAP configuration and a non-existent flow answer identically, 404.
The gate does not change for SOAP: a SOAP request goes through the same gate unchanged, and a refusal is plain HTTP 401/403, never a SOAP Fault.
Two limits remain. There is no WS-Security: a security element inside the message body authenticates nothing, because the gate decides before a body exists. And no foreign WSDL is consumed, while the contract an exposed service can publish is loosely typed, xsd:anyType — a typed schema, declared faults and several operations on one service are not built. If your project depends on a typed SOAP contract, that is the relevant fact, and you have it before the first conversation.