ADR 0047 — the shape of an event on the wire #16

Closed
jschoubben wants to merge 0 commits from design/adr-0047-event-wire-shape into main
Owner

The wire contract 0046 left open — exchanges, routing keys, headers, queues and their config — so the sdk and runtime implement one contract instead of reinventing it (the ADR 0043 precedent, for events).

  • Two exchanges: mesh.events and mesh.rpc, kept apart so a # subscription is a clean audit without RPC traffic.
  • Routing key = the event type, namespaced by origin: module.*, mesh.*, node.*.
  • Metadata in headers, payload in the body: required x-event-id / x-source / x-node / x-time / content-type; optional x-causation-id / x-schema; unknown x- headers ignored (an event is observed by parties that needn't understand every header).
  • Persistent messages (an audit that loses events on restart isn't one).
  • Queues: per-consumer <node>.<module>.events, durable, bound to consumed patterns, manual ack, prefetch, dead-letter mesh.events.dead; the audit logger's # queue the same shape; RPC reply queues exclusive/auto-delete, serve queues durable/shared.
  • At-least-once, idempotent consumers (x-event-id for dedup); exactly-once not offered, because no broker keeps that promise honestly.

Supersedes the sdk's first cut (metadata was in the body → moves to headers); that + the queue config are code to align in mesh-sdk and mesh-tools.

https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF

The wire contract 0046 left open — exchanges, routing keys, headers, queues and their config — so the sdk and runtime implement one contract instead of reinventing it (the ADR 0043 precedent, for events). - **Two exchanges:** `mesh.events` and `mesh.rpc`, kept apart so a `#` subscription is a clean audit without RPC traffic. - **Routing key = the event type, namespaced by origin:** `module.*`, `mesh.*`, `node.*`. - **Metadata in headers, payload in the body:** required `x-event-id` / `x-source` / `x-node` / `x-time` / `content-type`; optional `x-causation-id` / `x-schema`; unknown `x-` headers ignored (an event is observed by parties that needn't understand every header). - **Persistent messages** (an audit that loses events on restart isn't one). - **Queues:** per-consumer `<node>.<module>.events`, durable, bound to consumed patterns, manual ack, prefetch, dead-letter `mesh.events.dead`; the audit logger's `#` queue the same shape; RPC reply queues exclusive/auto-delete, serve queues durable/shared. - **At-least-once, idempotent consumers** (`x-event-id` for dedup); exactly-once not offered, because no broker keeps that promise honestly. Supersedes the sdk's first cut (metadata was in the body → moves to headers); that + the queue config are code to align in mesh-sdk and mesh-tools. https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
jschoubben added 1 commit 2026-09-03 21:48:12 +00:00
The wire contract ADR 0046 left open: two topic exchanges (mesh.events,
mesh.rpc, kept apart so # is a clean audit); the routing key as the event
type namespaced by origin (module.*, mesh.*, node.*); metadata in AMQP
headers (required x-event-id/x-source/x-node/x-time/content-type; optional
x-causation-id/x-schema; unknown x- headers ignored) with the body only the
payload; persistent messages; per-consumer durable dead-lettered queues
with prefetch; at-least-once with idempotent consumers (no false exactly-
once). The precedent is ADR 0043 for declarations.

Supersedes the sdk's first cut (metadata in body -> headers); that and the
queue config are code to align in mesh-sdk and mesh-tools.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
jschoubben closed this pull request 2026-09-05 01:17:49 +00:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/hq#16