You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The codebase-wide index of the sanctioned ways to extend Elsa without modifying the framework (framework §2.6.1, §2.24.2, §2.22.2). This is the map; the authoritative per-domain detail lives in each domain's own EXTENSION_POINTS.md.
Two axes: override vs. extend
Every seam below is one of two kinds (framework §2.22.1):
Axis
What you do
Mechanism
Override
Replace a default implementation of a .Core contract — "bring my own data access / my own commands".
One implementation wins: services.Replace(...) / register-your-own. You can override one contract and keep the rest (e.g. swap the commands, keep the built-in queries).
Extend
Add an implementation alongside the built-ins.
A single aggregating handler resolves all registered implementations and runs each. Adding one never removes another.
Intra-domain vs. cross-domain contributions
When a contributor-interface implementation ships in the same domain as the .Core contract it satisfies it is an intra-domain default — the feature delivers on its Core's promises. When it ships from an unrelated domain it is a cross-domain contribution — the primary mechanism by which domains extend each other's pipelines without direct coupling (framework §2.6.1).
Each per-domain catalog lists Known implementations for every contributor interface, tagged *(intra-domain — default)* or *(cross-domain)*. Features that implement contracts from other domains note it in their own README.md under Cross-domain contributions.
How to read the kinds
Per framework §2.6.1 contributor sub-pattern, an extension interface is one of:
Kind
Shape
Naming
Source
Returns values (pull). GetX() / Read().
I…Source
Contributor
Receives a context and acts on it (push). Contribute(ctx).
I…Contributor
PreProcessor / PostProcessor
Receives a context and acts at a specific phase.
I…PreProcessor / I…PostProcessor
Validator
Action-named contributor: inspects and returns findings.
I…Validator
entity Handler
Action-named contributor: receives ctx + entity and acts at a persistence lifecycle point.
I…Handler
The action-named suffixes (…Validator, …Handler) are semantically sanctioned alongside Source / Contributor / PreProcessor / PostProcessor (framework §2.6.1).
The rule for fan-in contribution flows: when contributing to a domain's fan-in contribution flow, features implement the typed contributor interface and register it via DI — they do NOT register a dedicated IEventHandler<T> for that contribution purpose. Exactly one aggregating handler per contribution event resolves IEnumerable<TContributor> and dispatches every implementation. Independent subscriptions — auditing, cache invalidation, reacting to an event for a feature's own unrelated purpose — are unrestricted and use IEventHandler<T> directly.
The doc layering
per-feature READMEs — what THIS feature registers/provides; includes a Cross-domain contributions section when the feature implements contracts from other domains.
per-domain EXTENSION_POINTS.md — the authoritative catalog for THAT domain: its overridable contracts, its implementable contributor interfaces, and (as an Events section) the events it publishes.
this file — the repo-wide index that points into each per-domain catalog.
Root-indexing policy: this root index includes every discovered src/**/EXTENSION_POINTS.md
catalog. Source/contribution-module catalogs are indexed here even when they point back to an
authoritative owner lifecycle catalog. Generated maps report index/catalog drift as review signals,
not automatic constitution violations.