RFC 003 — Common Event Schema

Approved

RFC 003 — Common Event Schema

Approved Content Companion: observe/observability RFC 001

  • Tracking ticket: backlogdone003rfccommoneventschema.md
  • Depends on: RFC 001 — Ecosystem Map (Approved), RFC 002 — Architecture (Approved)
  • Companion: infra/observe/observability/docs/rfcs/001-schema-registry-ownership.kmd (Approved) — owns the registry that publishes this schema
  • Unblocks: tickets across infra/jet, observe/log, observe/apm, observe/mon, observe/probe, observe/uptime, observe/notify
  • Status: Approved (20260408)

1. Summary

This RFC defines the content of the unified event schema that every Koder product emits and that Kortex consumes. It is the third in the Kortex RFC series and the content companion to observe/observability RFC 001, which defines the ownership, governance, and publication channels of the schema. The two RFCs are deliberately split: the registry product owns the runtime; this RFC owns the wire format.

The schema is built in three layers:

  1. OpenTelemetry Protocol (OTLP) as the base wire format for logs, traces, and metrics. OTLP is the de-facto industry standard, has mature SDKs in every language Koder uses, and gives the ecosystem free interoperability with external tools (Grafana, Jaeger, Honeycomb, Datadog OTLP intake, etc.).
  2. Koder extensions — a set of resource attributes and span/log attributes prefixed with koder.* that carry Koderspecific identity, deployment, tenant, and correlation metadata. These are namespaced so they survive transit through any OTLPcompliant collector.
  3. Special Koder events — a small catalogue of highvalue events that do not map cleanly to logs, traces, or metrics (deploys, config changes, healthstate changes, crashes, drains, admin actions, anomaly detections). These ride on top of OTLP Logs records with a structured body and a type discriminator under koder.event.type.

The schema is defined in Protobuf (canonical) with generated JSON Schema for documentation, validation tooling, and language bindings without a Protobuf compiler. This decision is inherited from observe/observability RFC 001 §13.1 and is not relitigated here.

This RFC is consumed by:

  • Producers — every Koder product that emits telemetry. Each one vendors the generated SDK, attaches the Koder resource attributes at startup, and emits special events using the typed builders.
  • Kortex Senses — the OTLP receiver in platform/kortex that validates incoming events against the schema in audit mode today and strict mode after the six-month soak (per observe/observability RFC 001 §13.3).

The RFC closes with a per-product migration audit, sampling and privacy guidance, a tooling sketch (owned by the registry), and a list of open questions for review.

Scope reminder

This RFC defines what is in the schema. The schema lives in infra/observe/observability/schemas/. The schema is published by the registry runtime. The schema is consumed by Kortex Senses and every other downstream tool. Three different concerns, three different RFCs. This is the middle one.


2. Context and dependencies

2.1 Where this RFC fits in the Kortex series

RFC Topic Status Relationship
Kortex 001 Ecosystem Map Approved Audit that uncovered schema heterogeneity (§6) and decided ownership (§12.3)
Kortex 002 Architecture Approved Defines Senses, the consumer side of this schema (§4)
Kortex 003 Common Event Schema (this document) Draft Defines the wire format both sides agree on
Kortex 004 Common Control Plane Pending Disjoint topic — control plane is the reverse direction (Kortex calling products)
Kortex 005 LLM Provider Abstraction Pending Disjoint topic
Kortex 006 Auto-remediation Rules Engine Pending Consumes events defined here as rule inputs
Observability 001 Schema Registry Ownership Approved Owns the registry; this RFC defines the content it publishes

This RFC is content-only. It does not propose any new product, runtime, package, or release process. Everything operational lives in observe/observability.

2.2 The five binding decisions inherited from observe/observability RFC 001 §13

The companion RFC resolved every meta-decision about the registry. They are restated here verbatim because every section of this RFC is shaped by them.

Observability RFC 001 §13.1 — Hybrid format

The canonical schema is Protobuf. JSON Schema is generated from the Protobuf source on every release for documentation and for languages without a Protobuf compiler. There is no hand-maintained JSON Schema. The Protobuf files live under infra/observe/observability/schemas/<domain>/v<MAJOR>/.

Observability RFC 001 §13.2 — HTTP API

The registry exposes a minimal static-file HTTP API served by koder-jet. There is no dynamic registry server. Producers and consumers fetch schema artifacts by URL, with content-addressed paths. No write API.

Observability RFC 001 §13.3 — Validation mode

Validation is audit mode by default: invalid events are accepted, counted, and logged, but not rejected. Strict mode is opt-in per consumer. After a six-month soak, strict mode becomes the default automatically.

Observability RFC 001 §13.4 — CLI location

The bindinggeneration CLI is `koderschemas, a sub-binary of the observeobservability` product. It is /not a separate repository and not part of koder-jet, kortex, or any individual observe engine.

Observability RFC 001 §13.5 — MAJOR coordination

Producers declare the schema MAJOR they speak in their koder.toml under [schema]. Consumers can override perrequest via the optional `XKoderSchemaMajor` header. The registry tracks MAJOR rollouts with a sixmonth deprecation window before the previous MAJOR is autoremoved.

2.3 The five binding decisions inherited from Kortex RFC 001 §12

Decision Section Effect on this RFC
Hybrid push+pull ingestion §12.1 The schema must work for push (urgent events over OTLP) and for pull responses (query-API JSON shapes from observe products). This RFC normalizes both onto OTLP.
Postgres + in-memory cache §12.2 Kortex does not store raw events. The schema does not need to optimize for long-term columnar storage — the upstream products handle that.
Schema owner is observe/observability §12.3 This RFC defines content, not ownership.
Renames §12.4 This RFC uses observe/wire and observe/apm from first mention. Old names appear only as (formerly observe/trace) and (formerly observe/trace-apm) parentheticals.
platform/{log,wire,apm} as Phase 0 §12.5 Tenant scoping happens inside each platform product before Kortex sees the event. This RFC reserves koder.tenant.id for that scoping but does not define a multi-tenant transport layer.

3. Scope of this RFC vs. observe/observability RFC 001

The two RFCs answer different questions:

Question Answered by
Who owns the schema? observe/observability RFC 001 §2
Where do the .proto files live? observe/observability RFC 001 §7.2
How is a new schema version published? observe/observability RFC 001 §7.3
How does a producer fetch the schema? observe/observability RFC 001 §7.5
How is the schema validated at runtime? observe/observability RFC 001 §7.4, §13.3
How is a breaking change rolled out? observe/observability RFC 001 §9, §13.5
What format is the canonical source? observe/observability RFC 001 §13.1
What fields are in the schema? This RFC §5–§7
What special events exist? This RFC §6
What naming conventions apply? This RFC §8
How does each existing product migrate? This RFC §12
What are the sampling and privacy guidelines? This RFC §13

A reader who needs both ownership and content must read both. Neither RFC duplicates the other; they are two halves of one specification.

Do not change governance here

If a reviewer of this RFC wants to change ownership, publication, validation modes, CLI location, or MAJOR coordination, the change belongs in observe/observability RFC 001, not here. This RFC will be re-aligned automatically once governance shifts.


4. Base layer: OTLP

4.1 Why OTLP

OpenTelemetry Protocol (OTLP) is the convergence point of every modern telemetry effort. By 2026 it is supported by:

  • Every major APM vendor (Datadog, New Relic, Honeycomb, Lightstep, Elastic, Dynatrace) as an accept format.
  • Every major dashboard tool (Grafana, Kibana, Chronograf) through OTLP receivers.
  • Every major collector (OpenTelemetry Collector, Vector, Fluent Bit, Logstash) as both source and sink.
  • Native SDKs in Go, Java, Python, JavaScript/TypeScript, Ruby, Rust, .NET, PHP, C++, Swift, Kotlin, Erlang.

Adopting OTLP gives the Koder ecosystem three benefits at zero runtime cost:

  1. Interoperability with external tools. A Koder customer who already runs Grafana can point their existing collector at observe/log with no glue code.
  2. Free SDKs. Producers do not have to write a Koder-specific client library — they extend the OTLP SDK they already have.
  3. Future-proofing. OTLP is governed by a neutral standards body (CNCF). It is not going to be deprecated. Any investment in OTLP-shaped pipelines pays off across the entire industry.

The audit in Kortex RFC 001 §6 confirmed that two of the eight `observe

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/kortex-003-common-event-schema.kmd