Sarvex V1 — Sync Plane Event Contract
The sync plane is event-driven, eventually-consistent, and retryable. Its
interface is therefore a message contract, not a REST API — this AsyncAPI document
is the counterpart to sarvex-v1-openapi.yaml (which covers the synchronous
control plane and the /connector/* ingest edge).
What this specifies
The internal event bus over which sync-plane components communicate: the normalised change events produced from store signals, the derived scoring/consistency events, the checkout lifecycle and checkout→order handoff events, and the task/journey/monitoring signals that cross into the control plane.
What this does NOT specify
- The
/connector/*HTTP ingest endpoints (in the OpenAPI doc) — they are the source of thesync.*.changedandsync.order.status_changedevents here, but the wire call itself is synchronous. - The pull side: Sarvex’s connector calling the merchant store’s own REST API to fetch full entities. That is the store’s API, governed by the platform, not by Sarvex.
- The serving-plane UCP/checkout endpoints (external UCP/Google schema).
Bus conventions (true for every message)
- Naming. Events are named
source.resource.something_happened(past tense) — e.g.sync.price.changed,sync.order.created,serving.snapshot.swapped. Thesourceis the emitting plane (sync.*,serving.*), with one exception:ops.*names the endpoint-health probe/evaluator workers (internal/planes/control/endpointhealth), a cross-cutting operational concern that isn’t owned by one plane (its probes call the serving plane over HTTP, its evaluator consumes serving-plane telemetry, and its read API lives in the control plane). This document specifies events only. Imperative commands (source.resource.operation, e.g.control.catalog.import) are a separate contract — see the control→sync commands catalogue — because a command is a directed “do this”, not a fan-out “this happened”. - Topic-per-event-type, partitioned by store. Channels are event-type topics,
not topic-per-store. Every message carries
ordering_key = store_idin its headers. The bus guarantees ordering within a store; messages for different stores (and different merchants) are processed fully in parallel. (This is the messaging expression of the tenant-isolation and per-store-sequencing invariants; a store belongs to exactly one merchant per architecture §2a.) - Delivery is at-least-once. Every consumer must be idempotent. De-duplication is
by
message_id; ordering/replay protection on ingest is by the monotonicsequencecarried from the originating store signal. - Retries with backoff, then dead-letter. A message that exhausts retries goes to
the matching
*.dlqchannel (not enumerated per-channel here; it is a uniform convention) and raises an operator alert. Nothing is silently dropped on the derived-event side. (Lost ingest signals are the exception — the reconciliation sweeper is their safety net.) - Priority lane.
sync.price.changedandsync.inventory.changedare compliance-critical and consumed on a priority lane so they cannot queue behind a bulk catalog import. - Envelope: all payloads are JSON, snake_case, and wrapped by the common
message_envelopeheaders (id, ordering key, timestamps, sequence, trace, schema version). Money is integer minor units plus currency. Timestamps are RFC 3339 UTC. - One producer per event type. Each channel names exactly one producing component
(
x-producer) and its consumers (x-consumers) — the messaging expression of the one-writer-per-store rule.
Version 1.0.0
Servers
pubsub://pubsub.sarvex.internalsync.consistency.finding_raised
sync.reconciliation.discrepancy_found
serving.snapshot.swapped
serving.request.telemetry_recorded
serving.catalog.query_recorded
ucp.negotiation.succeeded
ucp.negotiation.failed
ops.health.probe_completed
ops.health.threshold_breached
ops.health.recovered
serving.surface_artifact.fetched
sync.surface_artifact.updated
serving.checkout.session_initiated
serving.checkout.cart_updated
serving.checkout.payment_submitted
- RECEIVEA checkout session's payment was submitted to the connector
serving.checkout.payment_submitted