Skip to content

Platform Events for Modules

This contract defines the platform → modules direction. It is an agreed architecture; the generic outbound bridge is not yet enabled in production.

Processing model

Platform business logic
    → EventBus::emit(internal_name, typed_payload, event_code)
    → MoleculerEventBridge
    → allowed-type and event-code check
    → explicit safe JSON formatter
    → external event-name mapping
    → MoleculerBroker::emit(event_name, data)
    → subscribed modules

The existing typed C++ EventBus remains the internal source of platform events. The bridge is an adapter and policy boundary; it is not a second business event system.

Event name

For ordinary record lifecycle events, the external name is derived from the payload type and event code:

<entity>.<operation>
Payload type Entity
TradeRecord trade
AccountRecord account
CustomerRecord customer
Event code Operation
EV_RECORD_ADD add
EV_RECORD_UPDATE update
EV_RECORD_DELETE delete

Examples:

TradeRecord + EV_RECORD_ADD       → trade.add
TradeRecord + EV_RECORD_UPDATE    → trade.update
AccountRecord + EV_RECORD_UPDATE  → account.update
CustomerRecord + EV_RECORD_DELETE → customer.delete

A specialised mapping is allowed when a domain event is not a CRUD operation. For example, a margin-state transition can map to account.margin_state. Every specialised mapping is an explicit part of the public contract.

The internal EventBus name is not used as an automatic external API name. The payload type and event code define the external semantic contract.

Explicit allow list

A type being present in EventBus::EventPayload does not make it public. The bridge publishes only types for which an external mapping and formatter were explicitly added.

If the type or event code is unknown, incompatible or not enabled, the bridge drops the event and records the reason. Adding a new type to the internal variant must never expose it automatically.

Quotes are never published through this bridge.

Safe formatter

Each public payload type has a dedicated formatter. The formatter creates a new JSON object with an explicit field list; it must not serialise the complete internal C++ record automatically.

A formatter must:

  • expose only fields declared by the external contract;
  • omit internal implementation fields;
  • omit or mask personal and sensitive data;
  • preserve stable field names and JSON types;
  • validate the combination of payload type and event code;
  • version incompatible schema changes.

Changing an internal C++ structure must not silently change the external event schema.

Common envelope

Every published event contains common metadata and event-specific data:

{
  "event_id": "0192f7d7-8bd5-7e1a-b6cb-0f1e37d1ad11",
  "event_code": 1,
  "occurred_at": 1789080000,
  "schema_version": 1,
  "data": {}
}
Field Type Meaning
event_id string Unique tracing and deduplication identifier
event_code integer Original platform event semantic code
occurred_at integer Unix time when the domain event occurred
schema_version integer Version of this event-family JSON schema
data object Explicitly formatted public fields

A formatter may add resource, brand or routing identifiers only when those fields are approved for that event family.

Delivery semantics

MoleculerBroker::emit() routes an event to remote nodes that announced a matching event subscription in Moleculer INFO. No subscriber is a valid state and is not a business error in the trading core.

The first contract does not promise durable storage, replay or exactly-once delivery. Consumers should use event_id for deduplication when their processing can be retried. Critical operations that require an acknowledgement must use actions.

The bridge must use a bounded queue and expose at least:

  • published event count by event name;
  • rejected event count by reason;
  • formatter and NATS publish errors;
  • queue overflow count;
  • queue depth and handler latency.

Transition events such as margin-call level changes must not be silently coalesced in a way that loses a real state transition.