Skip to content

Connections ​

A connection is a typed, reusable resource that connects Hantera to an external broker or messaging service. One connection definition carries the endpoint, the credentials, and the recovery policy — so ingresses and egresses reference the connection by id and never see the credentials themselves.

AMQP 1.0 is the initial shared protocol. The connection's type identifies the external service and its semantics, while the ingress type (queue or stream) identifies the delivery behavior on top of it:

TypeWhat it connects toDelivery
rabbitmqRabbitMQ 4.x (AMQP 1.0 is core in 4.x)Queue ingress, egress send
azureServiceBusAzure Service Bus namespacesQueue ingress (queue/topic entities), egress send
azureEventHubsAzure Event Hubs namespacesStream ingress, egress send

Defining a connection ​

A connection can be created through the HTTP API, applied as a CLI manifest file, or declared in an app's manifest — whichever fits how you work:

PUT /resources/connections/partner-rabbit
Content-Type: application/json
json
{
  "type": "rabbitmq",
  "properties": {
    "protocol": "amqp10",
    "endpoint": "amqp://localhost:5672",
    "authentication": {
      "mechanism": "plain",
      "username": "integration",
      "password": "secret"
    },
    "reconnect": {
      "initialDelaySeconds": 1,
      "maxDelaySeconds": 60
    }
  }
}

The complete definition is replaced on every PUT.

Configuring an app-provided connection per tenant ​

The literal values in an app manifest are defaults. To let each tenant's administrator configure the endpoint or credentials without shipping a new app version, bind those fields to app settings:

yaml
# h_app.yaml
connections:
  partner-rabbit:
    type: rabbitmq
    properties:
      protocol: amqp10
      endpoint: amqp://localhost:5672   # default until the setting is configured
      authentication:
        mechanism: plain
        username: integration

settings:
  amqpEndpoint:
    label:
      default: AMQP endpoint
    bindings:
      connections:
        partner-rabbit: $.properties.endpoint

  amqpPassword:
    label:
      default: AMQP password
    secret: true
    bindings:
      connections:
        partner-rabbit: $.properties.authentication.password

A configured setting overlays its bound field on the effective connection (reads and the connection runtime both see it); an unset setting leaves the literal default. Mark credential settings secret: true — the resolved value never appears in resource reads or logs. See Settings Bindings for the full model.

Properties ​

PropertyRequiredDescription
protocolYesMust be amqp10.
endpointYesAbsolute amqp:// or amqps:// URI with a host.
authenticationYes for most typesAuthentication material; the shape depends on the mechanism (below).
reconnect.initialDelaySecondsNoFirst reconnect delay after a dropped connection (default 1).
reconnect.maxDelaySecondsNoCeiling for the exponential back-off (default 60).
traceContext.receiveNoSet to ignore to discard trace metadata carried by incoming messages (see Trace propagation).

Authentication mechanisms ​

RabbitMQ — SASL PLAIN:

yaml
authentication:
  mechanism: plain
  username: integration
  password: secret

Azure Service Bus and Azure Event Hubs — claims-based security (CBS) with a SAS policy. Accept either a full connection string or the policy name and key directly:

yaml
authentication:
  sharedAccessKeyName: send-listen
  sharedAccessKey: SGVsbG8=
yaml
authentication:
  connectionString: Endpoint=sb://example.servicebus.windows.net/;SharedAccessKeyName=send-listen;SharedAccessKey=SGVsbG8=

For local testing against the Azure Event Hubs emulator, which accepts unauthenticated AMQP and does not implement CBS, use the anonymous mechanism instead:

yaml
authentication:
  mechanism: anonymous

mechanism defaults to cbs for the Azure types. Anything other than cbs or anonymous is rejected with guidance.

WARNING

Credentials are secrets. They are validated by the adapter at write time and never appear in signals, audit records, traffic captures, or dev-session output. Store the values through the registry's secret mechanisms or your deployment pipeline rather than committing them.

Connection status ​

The platform reconciles each connection definition into a live transport and monitors it. A connection's status is distinct from its definition:

GET /resources/connections/{id}

The response always includes a status object:

json
{
  "id": "partner-rabbit",
  "type": "rabbitmq",
  "properties": { "protocol": "amqp10", "endpoint": "amqp://localhost:5672" },
  "status": {
    "state": "active",
    "lastReconciledAt": "2026-09-20T10:12:35Z",
    "health": { "healthy": true }
  }
}
StateMeaning
startingNo transport yet — the first reconcile has not completed.
activeA transport is established and ready.
failedNo active transport: reconcile failed and no last-known-good definition exists.

To include status on list responses, add ?status=true:

GET /resources/connections?status=true

A definition update that fails validation or cannot connect keeps the previous transport serving traffic (last-known-good) — a re-serialized but identical definition never churns the connection.

Status signals ​

Connection state is also published as transient registry signals, so portals and monitoring can subscribe without polling:

  • signals/connections/{id}/status — an informational, non-issue status signal while the connection is active.
  • signals/connections/{id}/reconciliation — an error signal when a connection cannot be established, carrying the failure reason.

Signals are read through the registry like any other signal entry.

Collisions ​

Two queue ingresses on the same connection and address would compete for the same deliveries. Instead of double-consuming, the platform elects a single winner by priority and the contenders stay installed but inactive, with a warning signal on the losing ingress naming the winner. The same applies to stream ingresses, where the durable subscription id is part of the collision identity.

Egress sending through a connection ​

Components running inside an egress can send messages over a connection with the send macro — see Egresses: Sending over a connection. The egress resource's ACL grants the use of the connection with connections/{id}:use; callers never learn the address or the credentials.

Trace propagation ​

Outbound sends stamp the ambient trace onto the message, and messages consumed through a queue or stream ingress restore that trace — the ingress names the sending egress as its trace parent, connecting the two request rows across the broker.

Trace metadata from a remote producer is observability input, not authorization. Connections to untrusted partners can opt out with:

yaml
traceContext:
  receive: ignore

Authorization ​

Connections carry no ACL of their own — nothing executes under a connection. Access is decided by the standard permission system:

connections/{id}:read    # View the connection definition and status
connections/{id}:write   # Create, update, or delete the definition
connections/{id}:use     # Granted inside an egress ACL: send through the connection

© 2026 Hantera AB. Org. no.: 559242-9582