A governed master-data hub exchanging versioned, secure, and reconcilable data with enterprise systems.
Part 8: Integrating EBX with the Enterprise Data Ecosystem

MDM fails at the boundary more often than at the center. A source sends the same message twice. A consumer cannot tell whether a record is current. A bulk extract finishes halfway. A pipeline copies governed data into a lake and quietly becomes a new master.

Part 7 gave our records stable semantic context. This workshop builds the contracts that move those records safely: inbound commands, read APIs, change notifications, bulk distributions, and reconciliation.

Audience and prerequisites

This chapter is for integration architects, EBX developers, platform engineers, data engineers, security engineers, and MDM leads. You need:

  • EBX 6.2.3 with ebx-dataservices deployed and REST services activated by an administrator.
  • A non-production service identity with minimum required permissions.
  • The Customer/Product workshop dataset and snapshot from Part 7.
  • curl or an API client, plus a local folder for synthetic payloads.
  • Network, TLS, authentication, and secret-management decisions approved for the workshop environment.
Version note: Examples describe the EBX 6.2.x built-in REST concepts, not a copy-paste production endpoint. The base context, dataspace/dataset names, authentication scheme, permitted media type, and API category must be confirmed in your deployment. EBX 6.2.3 documentation states that built-in REST messages use UTF-8 JSON and REST/SOAP services are enabled by deploying ebx-dataservices (REST introduction).

Learning outcomes

You will be able to:

  1. Choose an integration pattern by purpose rather than fashion.
  2. Define idempotent inbound commands and versioned outbound records.
  3. Propagate correlation and provenance information.
  4. Separate change notification from state retrieval.
  5. Reconcile delivery without creating an uncontrolled copy.

Start with a pattern matrix

NeedPreferred patternWhy
Validate and propose a source changeSynchronous command/API into staging dataspaceImmediate validation and traceable response
Retrieve a current mastered recordRead-only REST querySmall, permission-aware lookup
Signal that a record changedEvent notification containing ID/versionKeeps event small; consumer fetches governed state
Load a warehouse or feature platformVersioned snapshot/exportReproducible bulk boundary
Serve high-volume SQL analyticsControlled relational replicationRead scaling without writes back to replica
Distribute official EBX state across EBX nodesD3 broadcastSnapshot-oriented, governed EBX distribution

EBX replication can mirror repository data into relational tables for SQL reads (EBX replication). D3 distributes official snapshots from a primary to replica nodes and is designed for controlled consistency and rollback (EBX D3 introduction). These are different tools; neither makes every downstream copy authoritative.

Synthetic contracts

Inbound customer command

json
{
  "messageId": "crm-20261104-000184",
  "sourceSystem": "CRM-WEST",
  "sourceRecordId": "008917",
  "occurredAt": "2026-11-04T14:22:31Z",
  "schemaVersion": "customer-command/1.0",
  "correlationId": "journey-7719",
  "operation": "UPSERT",
  "customer": {
    "givenName": "Amina",
    "familyName": "Okafor",
    "email": "amina.okafor@example.test",
    "countryCode": "US"
  }
}

Outbound mastered record envelope

json
{
  "contractVersion": "customer-master/1.0",
  "masterId": "C-10017",
  "recordVersion": 42,
  "releasedAt": "2026-11-04T14:25:06Z",
  "snapshotId": "CUSTOMER-2026-11-04T1425Z",
  "status": "ACTIVE",
  "provenance": {
    "sourceLinks": ["CRM-WEST:008917", "ERP:44102"],
    "decisionCaseId": "MC-006"
  },
  "data": {
    "displayName": "Amina Okafor",
    "countryCode": "US"
  }
}

Hands-on: implement the controlled flow

Step 1 — Create a contract register

Actions: In a non-production metadata workspace, create one contract-register record for customer-command/1.0 and one for customer-master/1.0. Assign a business owner and technical owner; record purpose, schema URI, producing system, permitted consumer roles, sensitivity, retention, availability/freshness SLO, compatibility policy, and deprecation date. Add a field-mapping child row for every payload field, pointing either to its EBX model path or to a named, version-controlled transformation.

Expected result: Both contracts have accountable owners, an immutable version, a resolvable schema, and no field whose authority or transformation is implicit. The inbound masterId, if supplied, is classified as an untrusted source claim and cannot overwrite the EBX identifier.

Validate: Export the two register records, resolve each schema URI, and run a completeness query that returns zero missing owner, sensitivity, compatibility, or field-lineage values. Have a reviewer trace sourceRecordId, masterId, and recordVersion end to end.

Stop/recovery: Stop before integration work if a schema cannot be resolved, a sensitive field lacks an allowed-use decision, or an owner is absent. Correct the register under review, preserve the rejected revision, and rerun completeness checks; do not invent mappings in application code.

The first rule is authority: inbound messages are claims from a source; outbound master envelopes are governed statements from MDM. Do not let inbound masterId overwrite the EBX identifier.

Step 2 — Stage inbound data

Actions: In a child dataspace and staging dataset, create SourceCommand with a unique, required messageId; required payloadHash, sourceSystem, sourceRecordId, receivedAt, schemaVersion, and status; and optional errorCode, caseId, and correlationId. Grant the workshop service identity create/read access only to this staging table and no direct write access to mastered Customer records.

Actions: Canonicalize the synthetic JSON using the contract’s documented rules, compute SHA-256 over the canonical bytes, then process in one transaction: authenticate; authorize the exact service/table operation; verify UTF-8 JSON, media type, size, and schema version; lock or insert by messageId; compare hashes; validate reference codes; and only then create one stewardship case. Persist the final response status and case ID before acknowledging success.

Expected result: The first message creates one command and at most one case. An exact retry returns the stored outcome. Reuse of the same ID with different canonical bytes is rejected as an idempotency conflict and creates no second case or master mutation.

Validate: Submit the original twice, then change one field without changing messageId. Query SourceCommand and workflow cases: expect one command, one case, identical outcomes for exact retries, and a conflict audit entry for the changed payload.

Stop/recovery: On timeout, do not resend with a new ID. Query by the original messageId; retry only if no durable outcome exists. On partial workflow failure, mark the command FAILED_RETRYABLE, retain its hash, and resume idempotently from the recorded step rather than deleting evidence.

  1. Authenticate and authorize the service identity.
  2. Validate content type and schema version.
  3. Reject an existing messageId with a different payload hash.
  4. Return the prior outcome for an exact retry.
  5. Validate reference codes before creating a stewardship case.

This is idempotency: retrying the same fact does not create a second business action.

Step 3 — Exercise built-in REST safely

Actions: Ask the EBX administrator for the non-production base URL, dataspace key, dataset key, table path, allowed REST category/version, and one approved authentication method. Store the credential in the shell’s secret facility, not in the command or URL. First call a harmless single-record query with an intentionally invalid credential and confirm denial; then use the valid identity to fetch only synthetic C-10017, with Accept: application/json, an explicit timeout, and redirects disabled.

Expected result: Invalid authentication returns 401 or 403; valid authentication returns one authorized JSON record and no unrelated rows. Combining authentication methods is rejected. TLS verification remains enabled.

Validate: Record status, response content type, row count, record ID/version, correlation ID, and latency. Verify logs contain neither authorization headers nor sensitive payload fields, and repeat with a second identity that lacks dataset permission to prove least privilege.

Stop/recovery: Stop on redirects, certificate errors, unexpected hostnames, multiple records, HTML responses, or authorization wider than planned. Revoke/rotate any exposed credential, delete local response files containing data, and involve the EBX administrator before retrying.

Illustrative—not deployable unchanged:

bash
curl --fail-with-body \
  -H "Authorization: Bearer <workshop-token>" \
  -H "Accept: application/json" \
  "https://ebx.example.test/ebx-dataservices/rest/data/v1/<dataspace>/<dataset>/<customer-path>?predicate=./customerId%3D%27C-10017%27"

Do not place credentials in URLs, scripts, screenshots, or article assets. Capture HTTP status, response schema version, correlation ID, and latency—not payloads containing sensitive fields.

Step 4 — Carry tracking information

Actions: Generate one opaque correlation ID with no personal data. Pass it in the integration envelope and, only where the selected EBX operation documents support, in trackingInfo. Copy it to the staging command, workflow case, release manifest, outbound event, and consumer acknowledgment; never overload it as an authorization decision.

Expected result: A support engineer can start from any one artifact and locate the remaining artifacts without searching payload contents.

Validate: Query history and each downstream log by correlation ID and build a five-link trace: receipt, case, release, event, acknowledgment. Confirm the value is present but contains no email, master data, token, or secret.

Stop/recovery: If any hop drops or rewrites the ID, quarantine the release notification, correct the mapping, and replay from the last durable artifact using the original event/idempotency ID.

Step 5 — Separate event from state

After an approved release, emit a notification such as:

json
{
  "eventType": "CustomerMasterReleased",
  "eventId": "evt-78b1a4",
  "masterId": "C-10017",
  "recordVersion": 42,
  "snapshotId": "CUSTOMER-2026-11-04T1425Z",
  "occurredAt": "2026-11-04T14:25:06Z",
  "correlationId": "journey-7719"
}

Actions: Publish the sample release event to a non-production topic with only event ID, entity ID, record version, snapshot ID, time, and correlation ID. On the consumer, begin a transaction, insert eventId into a unique inbox table, compare recordVersion with the last applied version, fetch authorized state only when newer, commit state plus inbox marker, and acknowledge the broker message after commit.

Expected result: A duplicate event becomes a no-op; an older version is quarantined or recorded as stale; a newer version updates state once. The broker never becomes a second store of full sensitive master records.

Validate: Deliver version 42 twice, then version 41, then 43. Expect applied versions [42,43], one duplicate metric, one stale metric, and a final consumer version of 43 matching the authorized source checksum.

Stop/recovery: Stop consumption when versions jump unexpectedly, authorization fails, or the fetched snapshot does not match the event. Retain the offset and inbox evidence, route the event to quarantine, repair access or release metadata, then replay without deleting deduplication records.

Step 6 — Prove reconciliation

Actions: Snapshot pre-test counts for SourceCommand, workflow cases, mastered Customer rows, outbound events, and consumer rows. Submit the original synthetic command; wait for its durable outcome. Resubmit identical canonical bytes with the same ID. Then submit an older occurredAt/source version using a new message ID so ordering—not idempotency—is tested.

Expected result: The original links to one case/release; the duplicate returns the prior outcome with no additional case; the older update is retained as evidence but cannot overwrite the current governed version without an explicit conflict policy.

Validate: Compare before/after counts, distinct IDs, maximum record version, release/snapshot IDs, rejects, and deterministic checksums on the same canonical field set. Require zero unexplained differences; 200 OK alone is insufficient.

Stop/recovery: If a duplicate creates work or the older update overwrites current state, disable the ingress identity or pause the consumer, preserve logs and rows, restore from the pre-test snapshot only through the approved recovery path, and fix locking/idempotency before resuming.

  • Original: accepted and linked to one case/release.
  • Exact duplicate: same outcome, no second case.
  • Older update: recorded but not allowed to overwrite version 42 without policy.

Compare EBX counts and version/checksum totals with the consumer. A successful HTTP call is not proof of synchronized business state.

Step 7 — Define bulk and high-volume boundaries

Actions: In non-production, run global validation on the release dataspace and require zero blocking errors. Create a named snapshot only after approval. Record snapshot ID, creation time, dataset/model versions, row counts, export schema version, and per-partition checksums in a manifest. Extract through an approved service or read-only relational replica into a new immutable landing prefix; grant the consumer read-only access.

Expected result: Every landed object identifies the same snapshot and contract version; counts/checksums reconcile; rerunning the load creates the same result or a separately versioned run, never a mixed overwrite of latest.

Validate: Compare EBX and landing counts by entity/status, verify manifest checksums, sample master IDs and versions, and attempt a write with the consumer credential to confirm denial. If D3 is used, verify supported version compatibility and the selected delivery/federation mode before distribution.

Stop/recovery: Stop publication on validation errors, checksum mismatch, partial partitions, incompatible EBX nodes, or any writable replica credential. Mark the landing run invalid, leave the prior approved snapshot active, remove access to incomplete output, and restart into a new run ID after correction.

If your topology is multiple EBX nodes, evaluate D3 delivery modes and version compatibility. EBX documents that D3 compatibility is not assured when primary and replica product versions differ, and that replicas can differ in federation mode (D3 overview and limitations).

AI-era integration controls

An AI pipeline should not ingest “latest.csv” and forget its origin. Pass the master ID, record version, snapshot ID, contract version, event/correlation ID, and allowed-use classification into feature, vector, or prompt indexes. A vector index is a derived serving layer—not a master. When an entity changes, invalidate or rebuild the derived chunks associated with that exact master ID.

Treat an agent’s proposed write as an inbound command with its own identity, policy, idempotency key, evidence, and approval route. An agent token must not inherit administrator permissions merely because its prompt says “data steward.”

Validation checklist

  • Not completed: Contract owner, version, sensitivity, consumers, and deprecation policy are recorded.
  • Not completed: Exact retries are idempotent; conflicting reuse of a message ID is rejected.
  • Not completed: One authentication method is used and secrets never enter logs or URLs.
  • Not completed: Service identity has least privilege on the exact dataspace/dataset/action.
  • Not completed: Correlation/tracking survives from source through release and acknowledgment.
  • Not completed: Events carry stable ID and version; consumers tolerate duplicates and disorder.
  • Not completed: Snapshot/bulk extracts are reproducible and reconciled.
  • Not completed: Derived AI stores retain master and snapshot provenance.

Failure modes

FailureSignalResponse
Retry creates duplicate caseMultiple cases for one message IDEnforce idempotency before workflow launch
Event contains full sensitive recordBroker becomes an uncontrolled databasePublish reference/version; fetch with authorization
“200 OK” treated as reconciliationCounts or versions driftCompare IDs, versions, checksums, rejects
Consumer writes replica tablesSilent corruption/divergenceRead-only credentials and supported APIs only
Agent has broad write tokenPrompt injection becomes data mutationNarrow service identity plus approval workflow
Snapshot/version omittedAI answer cannot be reproducedCarry immutable release identity end to end

Takeaway

Integration is not plumbing around MDM; it is where authority is either preserved or lost. The safe pattern is explicit contracts, idempotent commands, permission-aware reads, small versioned events, reproducible bulk boundaries, and continuous reconciliation.

Next in the series

Part 9 will use these contracts to serve analytics, machine learning, and generative AI. We will build an evidence envelope so every feature and grounded answer can point back to the mastered record and release that informed it.

Illustration brief

Hero concept: A light-background integration map with EBX as a governed central hub. Inbound source claims enter a staging gate; approved, versioned outputs leave through REST, event, snapshot, and replica lanes. Each lane carries the same ID/version badge into analytics, ML, and GenAI destinations.

Alt text: “Source commands enter EBX through validation and stewardship, while versioned master records leave through APIs, events, snapshots, and controlled replicas with shared provenance.”

Sources