RFC #3 — Fallout.Plugin.Sdk versioning policy
Self-RFC. Once people ship plugins against the SDK, every breaking change has a real cost. This RFC pins the rules.
Context
Fallout.Plugin.Sdk is the abstractions package the whole plugin ecosystem compiles against. It depends only on Microsoft.Extensions.DependencyInjection.Abstractions. The core (Fallout.Core, Fallout.Build, Fallout.Common) can refactor freely as long as the SDK contract holds — that's the lever the v11 foundation work earns us.
Proposed policy
SemVer with strict additive-only minors
- Major (
1.x → 2.0) — any breaking change: renamed types, removed members, signature or behavioural changes that break plugin assumptions. Reserved for genuinely necessary changes; cadence every 2–3 years at most; always paired with a migration guide.
- Minor (
1.0 → 1.1) — additive only. New interfaces, new members on existing interfaces (default-implemented only — see DIM rule), new attributes, new extension points. Plugins targeting 1.0 keep working on 1.1 without recompile.
- Patch (
1.0.0 → 1.0.1) — docs, XML comments, type-forwarder additions, build metadata. No type or signature changes.
Default Interface Member (DIM) rule
Adding a non-DIM member to a published interface breaks implementers. So new members on existing public interfaces must be default-implemented (no-op or safe fallback). If a safe default isn't possible, ship a new interface (ITargetLifecycleListenerV2 : ITargetLifecycleListener) instead of mutating the existing one.
Plugin API version handshake
The SDK exposes PluginApiVersion.V1, V2, … Each plugin declares the highest version it needs (public PluginApiVersion ApiVersion => PluginApiVersion.V1). The host checks at load:
- Plugin requires ≤ host's version → load.
- Plugin requires newer → fail clearly ("plugin requires SDK v2; this host bundles v1; upgrade Fallout or downgrade the plugin").
Deprecation rules
- Deprecate with
[Obsolete("Use X instead", error: false)] in a minor.
- Remove only in the next major (no removals in minors).
- Document removals in the major-version migration guide.
Decoupled from the Fallout host
Fallout.Plugin.Sdk versions independently of Fallout.Core/Build/Common. The SDK version reflects the contract; the host version reflects everything else.
Why strict
A loose policy invites accidental breakage, and a casual minor-version break is paid for in lost ecosystem trust. Being conservative costs us internally (slower SDK iteration); being loose costs us externally (plugin authors leaving).
Questions for discussion
- Ship a Roslyn analyzer (
Fallout.Plugin.Sdk.Analyzers) that warns when an SDK change would be breaking (e.g. adding a non-default interface member)? Default: yes. Disagree?
- How long do deprecated members stay before the next major? Default: at least one full minor cycle (
1.5 → 1.6 deprecates → 2.0 removes). Disagree?
- Commit to a max major cadence (e.g. "no more than one major per 24 months")? Default: yes, as policy not tooling-enforced.
Out of scope (other RFCs)
How to engage
Comment if you've shipped a plugin SDK and have versioning war stories. Lessons from Roslyn analyzers, MSBuild SDKs, MEF, or other ecosystems are especially useful.
Decision lands in
When this RFC locks (2026-08-31), its shape becomes the spec for:
RFC #3 — Fallout.Plugin.Sdk versioning policy
Self-RFC. Once people ship plugins against the SDK, every breaking change has a real cost. This RFC pins the rules.
Context
Fallout.Plugin.Sdkis the abstractions package the whole plugin ecosystem compiles against. It depends only onMicrosoft.Extensions.DependencyInjection.Abstractions. The core (Fallout.Core,Fallout.Build,Fallout.Common) can refactor freely as long as the SDK contract holds — that's the lever the v11 foundation work earns us.Proposed policy
SemVer with strict additive-only minors
1.x → 2.0) — any breaking change: renamed types, removed members, signature or behavioural changes that break plugin assumptions. Reserved for genuinely necessary changes; cadence every 2–3 years at most; always paired with a migration guide.1.0 → 1.1) — additive only. New interfaces, new members on existing interfaces (default-implemented only — see DIM rule), new attributes, new extension points. Plugins targeting1.0keep working on1.1without recompile.1.0.0 → 1.0.1) — docs, XML comments, type-forwarder additions, build metadata. No type or signature changes.Default Interface Member (DIM) rule
Adding a non-DIM member to a published interface breaks implementers. So new members on existing public interfaces must be default-implemented (no-op or safe fallback). If a safe default isn't possible, ship a new interface (
ITargetLifecycleListenerV2 : ITargetLifecycleListener) instead of mutating the existing one.Plugin API version handshake
The SDK exposes
PluginApiVersion.V1,V2, … Each plugin declares the highest version it needs (public PluginApiVersion ApiVersion => PluginApiVersion.V1). The host checks at load:Deprecation rules
[Obsolete("Use X instead", error: false)]in a minor.Decoupled from the Fallout host
Fallout.Plugin.Sdkversions independently ofFallout.Core/Build/Common. The SDK version reflects the contract; the host version reflects everything else.Why strict
A loose policy invites accidental breakage, and a casual minor-version break is paid for in lost ecosystem trust. Being conservative costs us internally (slower SDK iteration); being loose costs us externally (plugin authors leaving).
Questions for discussion
Fallout.Plugin.Sdk.Analyzers) that warns when an SDK change would be breaking (e.g. adding a non-default interface member)? Default: yes. Disagree?1.5 → 1.6deprecates →2.0removes). Disagree?Out of scope (other RFCs)
PluginApiVersion— RFC [RFC #4] Plugin discovery and load model #100.How to engage
Comment if you've shipped a plugin SDK and have versioning war stories. Lessons from Roslyn analyzers, MSBuild SDKs, MEF, or other ecosystems are especially useful.
Decision lands in
When this RFC locks (2026-08-31), its shape becomes the spec for: