Skip to content

[RFC #3] Fallout.Plugin.Sdk versioning policy #99

@ChrisonSimtian

Description

@ChrisonSimtian

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)

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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFCDesign discussion / RFC. Comment with feedback; consensus shapes the implementation.target/2027Targets the 2027 calendar-version line. See ADR-0004.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions