Skip to content

Feat/manifest event catalog - #138

Merged
ucekmez merged 2 commits into
mainfrom
feat/manifest-event-catalog
Oct 18, 2026
Merged

ucekmez merged 2 commits into
mainfrom
feat/manifest-event-catalog

Conversation

@ucekmez

@ucekmez ucekmez commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Scope

  • Spec / schema only
  • TypeScript package(s)
  • Python package(s)
  • Tests / CI
  • Docs / examples
  • Other: ___

Checklist

  • I read CONTRIBUTING.md and CODE_OF_CONDUCT.md.
  • Tests added or updated where appropriate (npm test / pytest in affected packages).
  • Breaking change to public API or normative spec? If yes, describe impact and note CHANGELOG.md / migration path.
  • Documentation updated for user-visible behavior.

Notes for reviewers

Filtering was `event_types` glob only, and `subscription.request.json`
permits `*` solely in the final segment. A subscriber interested in one
field of one object still received every event of that type and
discarded the rest — after paying full delivery cost. For an LLM agent
that cost is tokens, which is precisely the "context bloat"
`docs/strategy/unmet-needs-map.md` claims EEP answers with "subscribers
choose what and when". The mechanism was thinner than the claim.

New §5.1.3 and an optional `filter` on the subscription request: a flat
list of comparisons over dotted paths into the envelope, combined with
`all` or `any`. Operators are `eq`, `ne`, `in`, `nin`, `prefix`,
`exists`, `gt`, `lt`.

Three design decisions worth stating:

- **No regex operator, and not Turing-complete.** The filter is
  evaluated by the publisher, on the delivery hot path, against every
  candidate event. A richer language would let a subscriber hand the
  publisher a catastrophically backtracking pattern to run at the
  publisher's expense. Conditions (20) and path depth (8) are bounded
  for the same reason. `ROADMAP.md` already plans ReDoS fuzzing on
  gate-config patterns; this avoids opening a second such surface.
- **A malformed filter is rejected with 400, not ignored.** A subscriber
  that believes it is filtering but is not receives traffic it thought
  it had asked to be spared, and cannot detect the difference from its
  own side.
- **Filters narrow, never widen**, and are not access control. Gates are
  applied before filters, and a filter cannot reach anything the
  subscriber's tier does not already grant.

An event that fails the filter is not delivered and does not count
toward the subscription's failure counter — it was never a candidate,
so treating it as a failed delivery would eventually pause a healthy
subscription.

Path traversal into `__proto__` / `constructor` / `prototype` is
rejected at validation, and the reader ignores inherited properties, so
a subscriber-supplied path can never reach a prototype lookup.

Webhook batching, the other half of audit finding O4, is deliberately
left to a separate change: it alters the delivery envelope and the
signing unit, which deserves its own review.

Refs: EEP audit 2026-08 finding O4 (filters)
Signed-off-by: Ugur Cekmez <ucekmez@gmail.com>
feat(spec,middleware): publisher-side subscription filters
Copilot AI balanced review requested due to automatic review settings October 18, 2026 11:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@ucekmez
ucekmez merged commit f6572b3 into main Oct 18, 2026
22 of 24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants