Skip to content

FR: events emit projections — resolve the ADR-0007 vs ADR-0028 contradiction (a stream is a channel, not a source) #212

Description

@dmealing

Summary

There is a live contradiction between two accepted decisions, and it should be resolved before a streaming/CDC backend lands:

  • ADR-0007's source catalog includes source.event @topic @role:publish (CDC / outbox) — a stream as a source.
  • ADR-0028 rules that "message topics/queues are channels, not sources — they live at the surface layer as binding.* on operations (AsyncAPI's model), never in source.*."

Both are currently on the books.

Resolution — toward ADR-0028: a stream is a channel, not a source

A source.* answers "where can this object's data be READ from" — it must be addressable state the tool can get-by-id against and that a verify --db-style drift check can inspect as a schema. A topic is transport: you cannot get-by-id against it, and no drift check can inspect "its contents." So:

  1. Amend ADR-0007's catalog: drop event as a source paradigm (and remove the publish role's source-side home).
  2. Model emission at the surface layer FR-024 §9 already reserved: an event/streaming api sibling (api.eventing / operation.event / binding.messaging) whose payload references a projection.

This lands a clean CQRS + events symmetry: queries return projections, commands take values, events emit projections. A CDC event's shape is a projection (passthrough/computed origins evaluated at emit time); only its exposure is a channel binding instead of a source — the projection concept still does all the shape work.

Two edge cases, pre-decided

  1. Windowed / stateful stream aggregation (Kafka-Streams-style folds over history) violates the meta migrate: aggregate/monitoring read-model views can't be modeled as projections — 4 missing origin/field capabilities #195 determinism contract (a pure derivation over the current entity graph). It is stream processing, not projection — stays out permanently.
  2. A compacted changelog treated as a state store (KTable) is functionally addressable. If ever needed, it enters as an ordinary read-only-@kind paradigm source — because the doctrine has a principled escape: a stream becomes a source exactly when it is treated as addressable state. Record this clause in the ADR so the door is principled, not ad hoc.

Scope

Amend ADR-0007 (remove the event paradigm + the publish source role); design the reserved api eventing sibling (operation.event + binding.messaging + a payload→projection reference); record the "stream becomes a source when addressable" escape clause. No change to the projection/entity/value taxonomy — this is purely about where event exposure lives (surface layer, not source layer).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:metamodelMetamodel vocabulary / loaderenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions