Audience: Architects, integrators, schema designers. Use: Understand the envelope-plus-fact message structure and field semantics.
Structure: Envelope + Fact
A BSFG message consists of two parts: an envelope and a fact.
message = {
envelope: {
message_id
from_zone
to_zone
produced_at_unix_ms
correlation_id
causation_id
labels
object_media_type (if artifact reference)
object_schema (if artifact reference)
},
fact: {
subject
predicate
object_json
}
}
The envelope carries system-level metadata: transport semantics, correlation, and artifact references. The fact carries domain-level information: the semantic content that applications care about.
Envelope Fields
The envelope is required on every message. It provides the transport and traceability context.
| Field | Type | Purpose | Required? |
|---|---|---|---|
message_id |
string (UUID or stable hash) | Idempotency key for deduplication. Must be deterministically derived from the business event. | Yes |
from_zone |
string (zone name) | Source zone. Validated by BSFG peers against authenticated mTLS certificate. | Yes |
to_zone |
string (zone name) | Destination zone. Declarative, not a routing directive. | Yes |
produced_at_unix_ms |
integer (unix milliseconds) | Timestamp when the event was produced. Producer clock, not system clock. | Yes |
correlation_id |
string (optional) | Links related messages across zones. Application-defined semantics. | No |
causation_id |
string (optional) | Links a message to the event that caused it. Preserves causal ordering. | No |
labels |
map of string → string | Operational and routing metadata. Examples: priority=high, silo=A. |
No |
object_media_type |
string (MIME type) | Media type of the referenced artifact (if any). Examples: application/pdf, image/png. |
If artifact |
object_schema |
string (optional schema reference) | Optional schema identifier for the artifact or object_json. | No |
Fact Structure
The fact is the domain-level semantic unit. It represents a single, immutable event.
fact = {
subject: "kind:id" | "kind:scope/id",
predicate: "lower_snake_case_relation",
object_json: "<canonical JSON bytes>"
}
Subject
The subject identifies what the fact is about. Two formats:
kind:id— simple identity (e.g.,work_order:12345)kind:scope/id— scoped identity (e.g.,assembly:lineA/step42)
The kind determines the subject domain (manufacturing, logistics, etc.). The scope is optional and contextual (production line, plant, shift).
Predicate
The predicate is a relation name in lower_snake_case. It describes the relationship between the subject and the object. Examples:
was_createdtransitioned_tohas_defectwas_completed_by
Predicate names must be stable across versions. Renaming a predicate is a breaking change.
Object (Payload)
The object is the data associated with the subject-predicate pair. It is serialized as canonical JSON.
Canonical JSON means:
- No whitespace outside of string literals
- Keys sorted lexicographically
- UTF-8 encoding
- No duplicate keys
Why canonical JSON? The idempotency key for the message may be derived from a hash of the object. Canonical form ensures deterministic hashing.
Example:
{
"status":"completed",
"completed_at":"2026-03-06T14:30:00Z",
"duration_ms":1250,
"result_code":0
}
Idempotency Key Derivation
The message_id in the envelope is the idempotency key for the boundary. It must be deterministically derived from the business event. Three strategies:
- Default (Payload Hash):
message_id = SHA-256(canonical_json(object_json)). Detects duplicate events with identical payload. - Canonicalized Payload:
message_id = SHA-256(canonical_json(full_message)). Detects duplicates by full message content. - Explicit Producer ID:
message_id = producer_assigned_uuid. Producer generates a stable UUID from the business event ID, guaranteeing uniqueness.
The idempotency key strategy is a zone-level configuration decision, not a per-message choice.
System-Level vs Domain-Level
Envelope = System Level. The envelope is owned and interpreted by BSFG. It controls transport, deduplication, routing, and traceability. Applications do not create envelope fields.
Fact = Domain Level. The fact is owned and interpreted by applications. BSFG treats the fact body as opaque bytes. Applications define subject, predicate, and object semantics.
This boundary ensures that BSFG remains a generic boundary transport, not a semantic gateway.
Immutability
Once a message is appended via AppendFact, it is immutable. Facts are append-only; corrections are new facts. The same envelope and fact cannot be modified or deleted.