Integration

Message Catalog Framework

Registry format for facts exchanged between zones

Audience: Schema owners, integrators. Use: Define and govern the catalog of facts exchanged in a BSFG deployment.

Overview

BSFG transports facts rather than RPC commands or request/response messages. A fact is an immutable statement about the world, with semantic meaning shared across zones.

Systems integrating with BSFG must establish a fact vocabulary — an agreed-upon set of predicates, subject types, and object schemas that describe the domain and maintain semantic consistency across producers and consumers.

The Message Catalog Framework provides a standardized format to document and register all facts used in a deployment. It becomes the semantic contract between systems and serves as the definitive reference for what facts are exchanged, who produces them, and what they mean.

Why Facts, Not Messages?

Traditional integrations exchange messages or events, which are often imperative or instructional:

"Process this order now"
"Run batch #42"
"Update temperature reading"

BSFG instead exchanges facts, which are declarative statements about what has happened or what is true:

order:ENT-12345 order_created {...}
batch:PlantA/B1042 batch_started {...}
sensor:T-023 temperature_recorded {...}

This shift from imperative to declarative enables:

Fact Structure

Every fact transported by BSFG has a canonical structure:

message
├── envelope (system-level metadata)
│   ├── message_id
│   ├── from_zone
│   ├── to_zone
│   ├── produced_at_unix_ms
│   ├── correlation_id
│   ├── causation_id
│   ├── labels
│   ├── object_media_type
│   └── object_schema
└── fact (domain-level semantics)
	├── subject
	├── predicate
	└── object_json

The envelope is handled by BSFG infrastructure and remains consistent across all facts. The fact is where domain semantics live.

Subject

The subject identifies the entity the fact is about:

subject := kind:id | kind:scope/id

Examples:

Predicate

The predicate expresses the relationship or state transition. It defines semantic meaning:

predicate := stable lower_snake_case relation

Examples:

Predicates are stable: once deployed, they do not change. New predicates are added; old ones are never removed or renamed (maintaining replay compatibility).

Object JSON

The object carries the payload — domain-specific data in canonical JSON format.

{
	"order_id": "ENT-12345",
	"customer_id": "CUST-999",
	"total_amount": 15000.0,
	"currency": "USD",
	"ship_to": "Plant A",
	"created_at": "2026-03-06T14:30:00Z"
}

The structure and semantics of the object are registered in the message catalog (see Catalog Table section below).

Message Catalog Table

Every fact type used in an integration must be registered in a message catalog table. This table serves as the authoritative reference for fact vocabulary.

Use this template to document facts:

Predicate Subject Type Producer(s) Consumer(s) Schema ID Description
[predicate_name] [kind] [system name] [system names] [schema_id_v1] [semantic meaning in one sentence]

Example Entries

Here are realistic catalog entries for a typical manufacturing integration:

Predicate Subject Type Producer(s) Consumer(s) Schema ID Description
order_created order ERP MES, Data Lake order_created_v1 New sales order received from customer or internal demand
order_modified order ERP MES, Data Lake order_modified_v1 Order quantity, destination, or deadline changed in ERP
order_shipped order ERP Data Lake, Analytics order_shipped_v1 Order fulfilled and shipped to customer or plant
batch_started batch MES ERP, Data Lake, Historian batch_started_v1 Production batch began execution on the plant floor
batch_completed batch MES ERP, Data Lake, Quality System batch_completed_v1 Production batch finished and passed all quality gates
step_completed batch_step MES / Equipment Controller ERP, Data Lake step_completed_v1 A manufacturing step (e.g., mixing, heating, cooling) finished within a batch
temperature_recorded sensor_reading Data Logger / IoT Historian, Data Lake temperature_recorded_v1 Temperature measurement from equipment sensor at a point in time
quality_result_recorded quality_test Quality System / Lab ERP, Data Lake, Batch System quality_result_recorded_v1 Lab result or quality inspection outcome for a batch or material lot
maintenance_completed equipment Maintenance System ERP, Data Lake, MES maintenance_completed_v1 Preventive or corrective maintenance work finished on equipment

Schema Governance

Every fact type has an associated object schema that defines the structure, field names, types, and required vs. optional fields.

Schema Ownership

The producer owns the schema. The producer defines what fields the object contains. Consumers must accept the schema as-is and adapt their processing accordingly.

Examples:

Schema Immutability

Once a schema is deployed in production, it becomes immutable. The object structure must not change. If a new field is needed:

Examples:

order_created_v1  (original)
order_created_v2  (added optional "internal_notes" field)
order_created_v3  (changed "total_amount" type, breaking change)

Schema Registration

For each fact type, register the schema JSON Schema (or equivalent description). Example:

{
	"$schema": "http://json-schema.org/draft-07/schema#",
	"$id": "order_created_v1",
	"title": "Order Created",
	"description": "A new sales order was created",
	"type": "object",
	"properties": {
		"order_id": { "type": "string" },
		"customer_id": { "type": "string" },
		"total_amount": { "type": "number" },
		"currency": {
			"type": "string",
			"enum": ["USD", "EUR"]
		},
		"ship_to": { "type": "string" },
		"created_at": {
			"type": "string",
			"format": "date-time"
		}
	},
	"required": ["order_id", "customer_id", "total_amount"]
}

Store these schemas in a central registry (e.g., Git, schema registry, or documentation wiki) so all systems can reference them.

Versioning Rules

BSFG fact predicates and schemas follow strict versioning rules to maintain compatibility and prevent silent failures.

Predicate Versioning

Predicates are never versioned. Once order_created is defined, it remains stable forever. New predicates are created for genuinely new semantic meanings; old predicates are never renamed or removed.

If a different order creation flow emerges, create a new predicate:

order_created         (original flow)
order_created_manual  (new: manually entered order)
order_created_import  (new: imported from legacy system)

Schema Versioning

Schemas are versioned using semantic versioning tied to the predicate:

[predicate]_v[major]
order_created_v1
order_created_v2
batch_started_v1

Versioning policy:

Backwards compatibility rule: Consumers written for order_created_v1 must continue to work when they receive order_created_v2 facts.

Breaking Changes

When a breaking change is necessary, increment the schema version and both producer and all consumers must be updated simultaneously:

  1. Producer releases new code that emits both old and new schema versions (dual-emit)
  2. All consumers upgrade to handle the new schema
  3. Producer switches off the old schema version

Message Catalog as Semantic Contract

The message catalog is the definitive contract between all systems. It serves as:

Treat the message catalog as you would treat an API contract: update it when facts change, review it before deployment, and maintain it as the authoritative source of truth.

Catalog Checklist

Before deployment, verify:

Cross-Links to Related Documentation