EVENTING-LAB · SPEC 0001 PHASE 0 + 0002 PHASE 1 + 0003 PHASE 2 · KUBECON NA 2026

The signed-event agent wake path

A Kafka message wakes a headless agent. The agent streams every step back out as CloudEvents. KEDA scales the consumer from zero and back. This page walks the wire, one message at a time, and shows the event that travels on each step. Press Next for one step. Press Prev to go back. The wire box shows the messages of the current step, and the panel under it shows that step's Kafka headers and data payload. Four flows: one agent, a batch of a hundred, a forged event, and scale-to-zero as a trust control.

request / data control / config lifecycle / scaling refusal / end success / result ours (2 services)
1 / 1

—

Commit the Kafka offset after the terminal event, not when the message is read. Consumer lag then means "work not finished", not "work not read". KEDA scales on that lag, so the queue gauge and the agent lifetime are the same fact. It is structurally impossible for KEDA to remove a pod mid-run. One decision settles both "never miss an event" and "do not kill a running agent".

eventrunner/config.py:82 — commit_after_terminal: bool = True

Who signs what

EVENTSIGNEDRULE
request yesEventBridge signs every wake
response, final=true yesthe terminal event only
response, intermediate nopassed through by policy
group.* yesno final attribute, so treated as terminal

A signature proves who finished a run. It does not prove what the run said along the way. shared/signing.py:430 _is_terminal

A group event carries no final attribute at all. Testing final alone would class it as an intermediate frame and wave it through — which is exactly the forged group.completed that would end a live batch. It also carries groupid and no correlationid, so the responses consumer routes on is_group_event rather than on the key. shared/ce.py:121

Measured

OPENSHIFTKIND
e2e assertions 49/4937/37
POST → scale up 1.7–3.0 s2.2–4.3 s
POST → pod Ready ~14 s—
back to zero 22 s—

3000 ms of the wake is the broker group.initial.rebalance.delay.ms. It is not signing overhead. Kind sets it to 0, so Kind timings do not compare to cluster timings.

The batch of 100, measured

submitted100 agents, one POST
finished / failed 100 / 0
wall clock 1m20s
slowest agent 79.6 s
peak replicas 10 — the cap, reached at t=6s
notifications 2 — not 100, not 102

KEDA does 0 → 1 and hands 1 → N to an HPA, whose scaleUp policy here jumps straight to the cap instead of climbing. Partitions are the real ceiling — Kafka gives each partition to one consumer in a group, so maxReplicaCount: 10 sits under the topic's 12.

While a group is open its members' own notifications are suppressed, keyed on membership rather than on the group still being open — so a redelivered request whose duplicate terminal arrives after completion stays quiet too.

Two identities, one derivation

Humans read brave-otter-4718. The agent CLI requires a real UUID. So both services derive the session id from the correlation id:

sessionuuid = uuid5(NAMESPACE, correlationid)

No mapping table and no database read on the resume path. Both sides compute the same answer from the slug alone.

Drift: spec §2.3 prints the namespace as …-rossoctlkeda1, which is not hexadecimal and raises ValueError. The code uses …-000000000001 (shared/ce.py:19), and the spec's own §6a.4 line 972 shows that correct value.

Defaults that matter

FLAGDEFAULT
ER_COMMIT_AFTER_TERMINAL true
ER_REQUIRE_SIGNATURE false
EB_AUTH_TOKENS unset — open
ER_MAX_CONCURRENT 4

Enforcement is opt-in. An unconfigured deployment verifies nothing and accepts an unauthenticated POST. The cluster run turned both on deliberately through the kind-signed overlay.