Lds.IntegrationHub.Models 1.4.1
The Lds Integration Hub — Overview
Read this before you integrate with the hub. It explains what the two systems are, which one you need, and what you have to build.
Where the rest of this documentation is
This file is the README of the Lds.IntegrationHub.Models package. Two more documents ship inside
the package, and the links in this file point at them:
| File | What it covers |
|---|---|
docs/building-an-arm.md |
The step-by-step guide: project setup, base classes, statuses, registration, hosting, deployment |
docs/arm-cmd-interface.md |
The host/arm CLI, environment variables and settings contract |
They are not served by the package feed, so the links below 404 in a browser looking at the feed page. Read them from one of these instead:
- After a restore, on disk at
%USERPROFILE%\.nuget\packages\lds.integrationhub.models\<version>\docs\ - Without referencing the package, download and unzip the
.nupkg— a nupkg is a zip file:https://components.datalogik.dk/v3/package/lds.integrationhub.models/<version>/lds.integrationhub.models.<version>.nupkg - In the hub repository, at https://dev.azure.com/datalogiklds/Lds.IntegrationHub/_git/Lds.IntegrationHub?path=/docs (Azure DevOps, needs access)
If you are an agent working in an arm repository: read docs/building-an-arm.md from the package
folder before writing any arm code. It is written for you, and guessing the conventions it documents
is the failure it exists to prevent.
Two systems, one landscape
The Integration Hub is a message bus. The DataHub is a central store. They share a database and a management UI, but they solve different problems, and most integrations touch only one of them.
ERP ──┐ ┌──> CRM
│ ┌──────────────────┐ │
TMS ──┼─────>│ Orkestrator │──────────┼──> Project management
│ │ ("the Ork") │ │
… ────┘ └────────┬─────────┘ └──> …
│
v
┌───────────────┐ ┌────────────────────┐
│ DataHub │<───────│ DataHub API │
│ (MongoDB) │ │ (direct lookups) │
└───────────────┘ └────────────────────┘
The Integration Hub: a message bus
Systems do not talk to each other. They talk to the Orkestrator — "the Ork" — and the Ork moves messages between them.
A participating service is called an arm. An arm sends messages in, receives messages out, or
both. A message carries a topic (Erp-Debtor) and a topic type (Insert, Update,
Delete, TableScan, Status, Debug) plus a JSON payload.
The Ork does not know what any message means. When a message arrives it looks up the expectations registered for that topic and type: which arms should receive it, in which order, and with which enrichment. Routing is configuration in the management UI, not code in anyone's service. A sender never names its recipients — it publishes to a topic and forgets. Adding a new consumer to an existing flow is a configuration change and touches no existing arm.
Arms pull; the Ork never pushes. An arm asks for its next message, processes it, and reports the
outcome — Success, Retry, Poison, OnHold. Nothing calls into an arm's process, so arms are
independently deployable, and an arm that is down queues work rather than losing it.
Order is explicit. Every recipient on an expectation has a Sequence. An arm in sequence 2 is
not offered the message until every arm in sequence 1 has reported success. That is where "the
debtor must exist before the invoice" lives — in configuration, not in a chain of service calls.
Core vocabulary:
| Term | Meaning |
|---|---|
| Arm | A service that produces and/or consumes messages. Has an ArmId and an API key. |
| ArmType | The deployable kind of an arm, with a declared configuration-field schema. |
| PolyArm | One host process running several arms under one registration. |
| Topic | The named subject of a message (Erp-Debtor). |
| Expectation | The routing rule: for a topic and type, who receives it, in what order. |
| Lookup | A query attached to a recipient that enriches the message with data the payload lacks. |
| Message | Topic + type + payload + originator + per-recipient state + activity log. |
The DataHub: central storage
The DataHub is a MongoDB store of business data — master and transactional. It is a replication hub, not a cache.
The difference matters. The ERP owns debtors. The DataHub subscribes to Erp-Debtor/Updated, stores
the debtor, and — only if something actually changed — publishes a message saying the DataHub
updated a debtor. Other systems subscribe to that. The debtor spreads across the landscape and the
ERP never learns who consumes it. Nothing is coupled to the source system except the one arm that
reads it.
DataHub collections are plain documents. Their shape is owned by the source systems, not by the hub.
Which one do you need?
You need an arm if your system produces data others want, or must react when something changes
elsewhere. This is the normal case. The work is a console application built on the
Lds.IntegrationHub.Models package — see building-an-arm.md.
You need a DataHub API client if your application just wants to look something up and does not
want a local replica of the data. Read methods are authored in the management UI as queries with
declared parameters and output fields, and your application calls
GET /api/v1/{methodName} with an API key. There is no package to reference and no process to
host — it is an HTTP call. Write methods and bulk ingest through the API are not built yet; today
data enters the DataHub over the bus.
You may need both. An application that both replicates data and does occasional lookups is registered twice.
Arm and ApiClient are never the same registration
An Arm talks to the Ork and exchanges messages. An ApiClient talks to the DataHub API and
reads data directly. They are separate registrations with separate, unrelated keys, and nothing links
them. An application that only reads through the API needs no arm at all. Do not attempt to use one
key for the other — the two systems do not share an identity by design.
What you have to do
- Decide what you are: a producer, a consumer, both, or an API client.
- Agree the topics and payload shapes with whoever owns the other end. A payload shape carries a
version in its
PayloadType(DebtorModelV1); changing the shape without changing the version breaks messages already in flight. - Build the arm — building-an-arm.md covers the project setup, the base classes, the statuses, and the deployment.
- Register it in the Hub.Management UI: an ArmType with its configuration schema, an Arm with its key and configuration, and the expectations that route messages to it. Code with no expectation pointing at it receives nothing — that is the single most common reason a new arm looks dead.
- Host it with
ArmServiceorPolyArmServiceon the target machine.
Everything an arm needs at runtime — its configuration, its cursor state, its assemblies, its log destination — comes from the Ork. An arm carries no local configuration file beyond what its host needs to find the Ork.
Reference
- building-an-arm.md — the practical guide: write, register, host, deploy
- arm-cmd-interface.md — the host/arm CLI, environment and settings contract
No packages depend on Lds.IntegrationHub.Models.
Deploying an arm is now an upload and a release from Hub.Management instead of a file copy to the Orkestrator server followed by a version bump: publish the arm with the default layout, zip it, upload it on the arm type's package card, approve the configuration schema read out of the assemblies, and release the version. Set
.NET 10.0
- Polly (>= 8.7.0)
- Serilog (>= 4.4.0)
- Serilog.Sinks.Console (>= 6.1.1)
| Version | Downloads | Last updated |
|---|---|---|
| 1.4.1.1 | 5 | 9/10/2026 |
| 1.4.1 | 2 | 9/8/2026 |
| 1.3.3 | 6 | 9/3/2026 |
| 1.3.2 | 53 | 5/6/2026 |
| 1.3.1 | 40 | 5/6/2026 |
| 1.3.0 | 40 | 5/1/2026 |
| 1.2.2 | 41 | 4/28/2026 |
| 1.2.1 | 40 | 4/21/2026 |
| 1.2.0 | 43 | 4/21/2026 |
| 1.1.3 | 49 | 3/26/2026 |
| 1.1.2 | 39 | 3/26/2026 |
| 1.1.1 | 37 | 3/13/2026 |
| 1.1.0 | 42 | 3/5/2026 |
| 1.0.19 | 43 | 2/24/2026 |
| 1.0.18 | 43 | 2/18/2026 |
| 1.0.17 | 43 | 1/29/2026 |
| 1.0.16 | 45 | 1/29/2026 |
| 1.0.15 | 43 | 1/29/2026 |
| 1.0.14 | 48 | 1/21/2026 |
| 1.0.13 | 43 | 1/21/2026 |
| 1.0.12 | 42 | 1/19/2026 |
| 1.0.11 | 42 | 1/6/2026 |
| 1.0.10 | 44 | 1/6/2026 |
| 1.0.9 | 44 | 1/5/2026 |
| 1.0.8 | 45 | 12/18/2025 |
| 1.0.7 | 48 | 11/21/2025 |
| 1.0.6 | 47 | 11/21/2025 |
| 1.0.5 | 42 | 11/20/2025 |
| 1.0.4 | 47 | 11/20/2025 |
| 1.0.3 | 47 | 11/19/2025 |
| 1.0.2 | 42 | 11/19/2025 |
| 1.0.1 | 46 | 11/18/2025 |
| 1.0.0 | 43 | 11/17/2025 |