NexusFabricRequest a walkthrough

Use cases

Six situations teams bring to an integration platform, and how each one is built on NexusFabric. Then two industries where several of them meet in one chain: energy and utilities, and the public sector.

A façade over a legacy service

An internal service answers in a shape new callers cannot consume. The flow takes the new request, translates it, calls the old service, and composes the response.

  • What it covers

    The backend’s status can become the response’s status, declared by the flow. The backend’s error body is available to the flow, so an error can be translated rather than merely propagated. Response headers are dictated by the flow, and those coming from the backend return only through a declared allowlist.

Asynchronous intake with retries

A system emits events it cannot wait on. The platform accepts them, queues them, and delivers them onward, with retries.

  • What it covers

    The queue has its own write-ahead log: an accepted message survives a crash, and a scheduled retry survives a restart. A delivery that exits through the fault sequence is not committed as a success.

Request now, answer hours later

A partner takes a request and answers later, on another channel. The platform has to know what the answer refers to when it arrives.

  • What it covers

    Request/late-response correlation is declared in the flow and carries a mandatory deadline — an open-ended wait is a leak, not a policy. An overdue one is reconciled, and open waits can be listed from the command line. Declarative deduplication stops a second delivery of the same key from running the flow again.

Service-to-service integration over gRPC

Two services speak gRPC, and something between them has to translate, route, or hold a retry policy.

  • What it covers

    gRPC egress works with dynamically loaded descriptors, mutual TLS, a cascade of endpoints and a per-endpoint circuit breaker. The gRPC inbound door routes the call through the same gate and the same delivery bracket as the HTTP door.

Several organisations on one installation

A service provider runs integrations for several customers on the same platform.

  • What it covers

    The tenant is a registered entity, created deliberately; a typo does not become a tenant. A library reference resolves within the caller’s tenant. An unknown tenant and a disabled one answer identically from outside. The UI has roles with an enforced boundary, verified route by route.

Change control over integrations

A team wants a wrong integration to fail at publication, not at the first message on Monday morning.

The flow your team reviews. tests/battery/corpus/meridian/01-shipment-intake.flow.md — the egress step, lines 34-40, is left out.
## Step: check-booking
```validate
$.shipmentId != null    | "shipmentId is required"                    | syntactic
$.hubCode != null       | "hubCode is required"                       | syntactic
$.parcelCount > 0       | "parcelCount must be greater than zero"
$.weightKg > 0          | "weightKg must be greater than zero"
```

…

## Step: acknowledge
response_status: 202
```ntd
{
  "status": "ACCEPTED",
  "shipmentId": "{{ $.echo.shipmentId }}",
  "waybill": "{{ $.echo.waybill }}",
  "hubCode": "{{ $.echo.hubCode }}",
  "parcelCount": {{ $.echo.parcelCount }}
}
```
$ nexus validate flows/01-shipment-intake.flow.md
ok  flows/01-shipment-intake.flow.md
    flow:   shipment-intake
    tenant: meridian
    steps:  3
A flow with an XSLT construct outside the supported subset: refused at publication, not run some other way. tests/battery/corpus/acme/stricate/p10-xslt-necoborabil.flow.md, in full.
---
flowmarkdown_version: 0.1
flow: p10-xslt-necoborabil
tenant: acme
effects: []
---
## Step: x
```xslt
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:apply-templates select="*"/>
  </xsl:template>
  <xsl:template match="*">
    <copiat><xsl:value-of select="."/></copiat>
  </xsl:template>
</xsl:stylesheet>
```
$ nexus validate flows/p10-xslt-necoborabil.flow.md
error: step 'x': this XSLT sheet is outside the subset this platform compiles, and there is no XSLT engine at run time — unsupported XSLT construct <xsl:apply-templates>: recursive template application requires a runtime XSLT engine. Rewrite the step as `ntd`: it expresses the same transformations, and its failures are visible here rather than at the first message. `descendants()` covers `//name` searches, `string()` takes an element's text, and `{{ if }}` / `{{ for }}` cover `xsl:choose` and `xsl:for-each`
error: 1 validation error(s)
  • What it covers

    XSLT outside the supported subset, a malformed routing block, an illegal flow name or an invalid literal status are refusals at publication. A declared configuration key the installation does not supply stops the boot, naming the key.

  • When it goes wrong

    The refusal comes at publication, not at the first message on Monday morning.

Energy and utilities

A utility runs a customer portal, a metering system and a billing system, and exchanges requests with partner systems it does not run. Some partners speak SOAP. A partner that hears nothing sends the same request again, and its confirmation can arrive hours later, on another call.

  • A request sent twice is not processed twice

    The flow declares the key that makes two deliveries the same request. A second delivery with that key does not run the flow again. If the first one exited through the fault sequence, it was not committed as a success, so a corrected resend runs.

  • The late SOAP confirmation finds its request

    The request opens a correlation with a mandatory deadline, and the confirmation that arrives later is matched to it. A wait that passes its deadline is reconciled. The SOAP 1.1 or 1.2 envelope is unwrapped, the flow works on the Body content, and the answer leaves in an envelope of the same version.

How the chain is built

  1. The transform is compiled at publication: XSLT outside the supported subset is refused, not run some other way.
  2. A SOAP request goes through the same gate as any other, and a refusal is plain HTTP 401 or 403, never a SOAP Fault.
  3. The SOAP 1.1 or 1.2 envelope is unwrapped, and the flow works on the Body content.
  4. validate refuses explicitly, at the first rule that is false; condition filters silently.
  5. A second delivery of the same key does not run the flow again.
  6. The call to the system behind opens a correlation with a mandatory deadline; an overdue one is reconciled.
  7. The answer leaves in an envelope of the same version, and a failing flow returns a SOAP Fault, not a success body.
  8. A delivery that exits through the fault sequence is not committed as a success, so a corrected duplicate runs.

A worked flow

The flow takes a SOAP request, opens a wait on the system behind it, and answers in SOAP. web/src/content/samples/acme-request-awaiting-confirmation.flow.md, in full.
---
flowmarkdown_version: 0.1
flow: request-awaiting-confirmation
tenant: acme
effects: [http_egress]
config: [PARTNER_ENDPOINT]
soap_operation: SubmitRequest
soap_namespace: urn:acme:requests
log_level: event_only
log_project: Acme
log_scenario: request-awaiting-confirmation
---

**A SOAP request in, a wait opened on the system behind, a SOAP answer out.** The caller speaks
SOAP 1.1. The platform unwraps the envelope, and the flow works on the `Body` content.

The flow builds a JSON request for the system behind it and sends it. That call opens a
correlation on the reference the system behind returns, with a deadline of four hours. The
confirmation that comes back later, on another call, is matched to this wait; a wait that
passes its deadline is reconciled.

The answer leaves in a SOAP 1.1 envelope, the version the caller used.

## Step: build-request
```ntd
{
  "requestId": "{{ $.requestId }}",
  "reference": "{{ $.reference }}",
  "supplyPoint": "{{ $.supplyPoint }}",
  "source": "soap-intake"
}
```

## Step: notify-system
effects: [http_egress]
endpoint: {{ ctx.PARTNER_ENDPOINT }}/requests
method: POST
content_type: application/json
correlation_open: "{{ $.reference }}"
correlation_state: { "requestId": "{{ $.requestId }}" }
correlation_deadline_ms: 14400000

## Step: answer-caller
```ntd
<SubmitRequestResponse>
  <code>100</code>
  <reference>{{ $.reference }}</reference>
  <status>{{ $.status }}</status>
</SubmitRequestResponse>
```
$ nexus validate web/src/content/samples/acme-request-awaiting-confirmation.flow.md
ok  web/src/content/samples/acme-request-awaiting-confirmation.flow.md
    flow:   request-awaiting-confirmation
    tenant: acme
    steps:  3

Public sector

A service to a citizen often depends on data that other institutions hold. Their systems call each other in SOAP or REST, and the messages carry personal data. Every caller has to identify itself before its message is read, and an error must not repeat what the message contained.

  • Other institutions’ systems call in SOAP or REST, through the same closed door

    The authentication method is declared per tenant, and a method this build cannot perform is refused at registration. The gate is closed by default and runs before the body: an unauthenticated caller causes no body read and no parsing. A SOAP request goes through the same gate, and a refusal is plain HTTP 401 or 403, never a SOAP Fault.

  • An error message describes the shape of the data, not the personal data itself

    A runtime error message carries the shape, not the content: no error site in the executor interpolates a value. A backend’s error body is made available to the flow, and sensitive headers are withheld at capture time. A refusal that can be attributed enters the audit chain with its subject and never carries the credential.

How the chain is built

  1. The authentication method is the tenant’s declared property; a method this build cannot perform is refused at registration.
  2. The gate is closed by default: nexus serve requires a credential, and --no-auth is explicit and loud.
  3. The gate runs before the body: an unauthenticated caller causes no body read and no parsing.
  4. A SOAP request goes through the same gate, unchanged, and a refusal is plain HTTP 401 or 403, never a SOAP Fault.
  5. A refusal that can be attributed enters the audit chain with its subject, never carries the credential, and spends the caller’s ceiling.
  6. A backend’s error body is made available to the flow, and sensitive headers are withheld at capture time.
  7. A runtime error message carries the shape, not the content: no error site in the executor interpolates a value.

A worked flow

Each rule’s message names a field, never the value received. web/src/content/samples/acme-application-check.flow.md, in full.
---
flowmarkdown_version: 0.1
flow: application-check
tenant: acme
effects: []
log_level: event_only
log_project: Acme
log_scenario: application-check
---

**An application checked at the door, and an error body that repeats no submitted value.** The
three `validate` rules check that the application names itself and counts its documents. Each
message names the field it checks; none quotes the value received.

The `## Fault:` section writes the error body as a problem document: the status, the message of
the rule that refused, and the name of the step.

## Step: check-application
```validate
$.applicationId != null  | "applicationId is required"              | syntactic
$.documentCount != null  | "documentCount is required"              | syntactic
$.documentCount > 0      | "documentCount must be greater than zero"
```

## Step: accept
```ntd
{ "status": "ACCEPTED", "applicationId": "{{ $.applicationId }}" }
```

## Fault: error-response
fault_header_content_type: application/problem+json
```ntd
{
  "title": "Application refused",
  "status": {{ number(ctx.fault_response_status) }},
  "detail": "{{ $.fault_error }}",
  "step": "{{ $.fault_step }}"
}
```
$ nexus validate web/src/content/samples/acme-application-check.flow.md
ok  web/src/content/samples/acme-application-check.flow.md
    flow:   application-check
    tenant: acme
    steps:  2