Renaming a hook, changing its payload shape, or removing a plugin context method without a major version bump breaks every plugin in the ecosystem instantly and silently. Plugin authors discover the change when their code crashes, not from a deprecation warning or migration guide. ISO 25010 maintainability.modifiability requires that the scope of a change be predictable; semver applied to the plugin API is the mechanism that communicates scope. Without it, every minor host release carries hidden risk for the plugin ecosystem.
High because breaking plugin API changes shipped in minor or patch releases break the installed plugin ecosystem without warning, removing the signal plugin authors rely on to assess upgrade risk.
Apply semver discipline to the plugin API independently of the host application version: hook renames or payload changes = major bump; new hooks = minor; behavioral bug fixes = patch. Forward deprecated hook names to their replacements and emit a warning.
on(hook: string, handler: Function) {
if (DEPRECATED_HOOKS[hook]) {
console.warn(
`[PluginAPI] Hook "${hook}" is deprecated and will be removed in API v${
DEPRECATED_HOOKS[hook].removeInVersion
}. Use "${DEPRECATED_HOOKS[hook].replacement}" instead.`
);
hook = DEPRECATED_HOOKS[hook].replacement;
}
// ... register handler
}
ID: plugin-extension-architecture.versioning-contracts.backwards-compat
Severity: high
What to look for: Check whether the plugin API follows semantic versioning for breaking changes. A breaking change for the plugin API includes: removing a hook, changing a hook's payload type, changing a hook's return type, removing a method from the plugin context, or changing the plugin manifest schema. Look for:
Pass criteria: Count all deprecated API methods. The plugin API follows semver or an equivalent versioning scheme. Breaking changes result in a major version bump (or are documented as intentional breaking changes). Deprecated APIs are marked and given a deprecation period before removal. OR the project documents a commitment to semver for the plugin API. At least 1 major version must be supported alongside the current version for backward compatibility.
Fail criteria: Breaking changes to the plugin API are made without version bumps. Hooks are renamed, payloads changed, or methods removed in minor/patch updates. No deprecation process exists — APIs disappear without warning.
Skip (N/A) when: The plugin API has never had a breaking change (version 1.0.0 or earlier with no history of API changes). Also skip when the API is explicitly pre-1.0 with a documented "unstable" warning.
Detail on fail: "The host renamed the 'onRequest' hook to 'beforeRequest' in version 1.2.0 (a minor bump). This broke all plugins using the old hook name with no deprecation warning, no migration guide, and no major version bump. The changelog does not mention plugin API changes."
Remediation: Semver for the plugin API means: removing or changing hooks = major bump. Adding new hooks = minor bump. Bug fixes in hook behavior = patch bump. Deprecate before removing.
// Deprecation warning pattern:
on(hook: string, handler: Function) {
if (DEPRECATED_HOOKS[hook]) {
console.warn(
`[PluginAPI] Hook "${hook}" is deprecated and will be removed in API v${DEPRECATED_HOOKS[hook].removeInVersion}. ` +
`Use "${DEPRECATED_HOOKS[hook].replacement}" instead.`
);
hook = DEPRECATED_HOOKS[hook].replacement; // Forward to new hook
}
// ... register handler
}