1.4 Reading an Event

Four rules govern every consumer of this stream.

1.4.1 Ignore unknown keys #

Future versions may add fields to an event without changing the existing ones. A consumer that processes the keys it knows and ignores the rest keeps working across upgrades. A consumer that rejects unrecognised keys breaks on the first addition.

1.4.2 Read absence by the field's presence #

A key that is absent means the emitter had no value for it (§1.3) — nothing more. Each event page says when each field is present: required, optional, or when a condition on another field holds. Read absence against that, not as a signal of its own. A field that is optional today may become always present later.

1.4.3 Delivery is best-effort #

KMES is a ring buffer. The kernel writes; keeping up is the subscriber's problem.

  • A subscriber that falls behind loses events. eventd notices and records an eventd.events.lost, which is how a gap becomes visible rather than silent.
  • There is no replay. An event missed is gone. Nothing can ask for it back.
  • Buffers are per-subscriber. One slow reader does not affect another.
  • Order is per-subscriber, not global.

For durable audit, read events from eventd's stores rather than from KMES directly. eventd drains its subscription continuously and persists what it reads; from that point the store is the record, not the ring.

1.4.4 Events are not authenticated #

Events are trusted because they came through KMES, not because they are signed. Nothing in an event carries a signature. What the kernel vouches for is the header: emitter.class says which path wrote a record, and a program can write any event type it likes with class 0 (§1.2).

Cryptographic non-repudiation is a userspace concern applied after events leave the kernel. If a deployment needs it, it is added on the far side of eventd, not here.

1.4.5 Versioning #

Event types are not versioned by a field. Some changes to the catalogue are additive and can arrive in any update: a new event type, a new field, a new value of an open enumeration. A consumer that ignores what it does not know, and treats an unknown value of an open enumeration as a value, keeps working across them.

Renaming an event type or a field, moving a field to another path, changing a field's type, or adding a value to a closed enumeration is not additive. Each needs a new version of the event vocabulary, because every query and descriptor written against the old shape stops matching (PGSS §6.11).

Edit this page