Fallout-build / Fallout-build/Fallout
[RFC #3] Fallout.Plugin.Sdk versioning policy
- Dominant language
- C#
- Stars
- 154
- Forks
- 19
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 15
Description
**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
1. 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?
2. 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?
3. 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)
- The contract being versioned — RFC #97, #98.
- The discovery mechanism reading `PluginApiVersion` — RFC #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:
- #150 — [SDK-5] Versioning policy & load-time SDK compat check
Contributor guide
Assessment
This issue has not been assessed yet.