Integration

Integration Contract

Normative responsibilities for producers and consumers

Audience: Integrators, solution architects. Use: Apply the normative producer and consumer contract for BSFG integrations.

Purpose

The integration contract is a normative specification that defines exactly what producers and consumers must implement to interact correctly with BSFG. All systems integrating with BSFG via the four RPC operations must satisfy this contract.

Without explicit contract semantics, integrators often make incorrect assumptions about exactly-once delivery, synchronous semantics, or boundary-level business acceptance. This leads to integration defects: duplicate emissions, premature confirmation, or silent message loss.

Producer (Emitter) Responsibilities

A producer is any system that calls AppendFact to emit facts into BSFG.

Required Invariants

Required Call Sequence

IF artifact needed:
  PutObject(blob) → {digest, size, bucket, key}
  [wait for durability]

AppendFact({
  envelope: {message_id, from_zone, to_zone, produced_at_unix_ms, ...},
  fact: {subject, predicate, object_json}
})
[wait for durability at ISB/ESB]

IF timeout or error:
  retry AppendFact(same message_id, same payload)

Consumer (Receiver) Responsibilities

A consumer is any system that calls FetchFacts and ConfirmReceipt to retrieve and process facts from BSFG.

Required Invariants

Required Call Sequence

FetchFacts(consumer_name, limit) → batch of facts

FOR each fact in batch:
  apply business logic (idempotent)
  persist outcome to durable storage
  [if error, do NOT confirm]

IF all facts processed successfully:
  ConfirmReceipt(consumer_name, highest_offset)

IF error during processing:
  retry on next fetch from last cursor position

Delivery Semantics

BSFG guarantees the following about delivery:

The canonical guarantee ladder is: at-least-once transportidempotent materialization at the boundary via putIfAbsentapplication-owned idempotent consumption downstream.

At-Least-Once Transport

Every fact appended successfully will be delivered at least once to the receiving zone's forward buffer. Facts are never lost after successful append, as long as the store buffer is not truncated (default 7-day TTL).

Idempotent Materialization at the Boundary

The same message_id submitted multiple times is stored once. The boundary deduplicates automatically via putIfAbsent at the forward buffer. This is why retry with the same ID is safe.

Replay-Based Recovery

On boundary reconnection, facts are replayed from the last confirmed cursor position. No facts are skipped; no facts are lost or duplicated beyond what idempotent append ensures.

Application-Owned Idempotent Consumption

BSFG does not guarantee exactly-once delivery. Consumers must expect at-least-once and implement idempotent processing in their own application state and outcome handling.

Artifact Lifecycle

Producer Obligations

Consumer Retrieval

Common Misassumptions to Avoid

❌ Misassumption 1: "AppendFact confirms business acceptance"

WRONG. AppendFact confirms only that the fact was durably stored at the ingress boundary (ISB or ESB). It does not confirm delivery to or processing by any consumer. Business acceptance happens downstream, after the consumer processes and persists the outcome.

❌ Misassumption 2: "I should generate a new message_id on retry"

WRONG. Generating a new ID for a retry creates duplicate facts. The whole purpose of message_id is to make retries safe. Use the same ID and payload on every retry of the same business event.

❌ Misassumption 3: "Facts are delivered exactly once"

WRONG. BSFG guarantees at-least-once, not exactly-once. Consumer applications must implement idempotent processing. A fact may arrive multiple times due to producer retry, boundary replay, or consumer restart.

Integration Patterns

See the following guides for detailed implementation patterns: