Write plugin versions while loading configs

The staging copy made by Config.set() went through the constructor, so
plugin migrations ran a second time on the live fields. A version-gated
migration was applied twice when setPluginVersions() changed the version.
Staging now copies the fields with update() instead.

A config saved without <plugin>.version got the running version as its
default, so setPluginVersions() saw no change and nothing saved the stamp.
The constructor now writes the registered plugin versions after the
migrations run and marks the config dirty when that changes a loaded value.
Controller.bootstrap() saves the instances that came out dirty, and
setPluginVersions() is gone.

Restructure the SyncHook and plugin config tests by method, and suggest the
controller config version for role migrations in the docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bbassieandClaude Opus 5.5 committed 2026-10-14 16:37:03 +00:00
1 parent aec0fc7a1e
commit e455d17bb7
10 files changed
+188 -119

No files matched your search

+1 -4
View File
@@ -430,9 +430,6 @@ async function initialize(): Promise<InitializeParameters> {
);
controllerConfig.set("controller.version", packageConfig.version); // Allows tracking last loaded version
if (!args.recovery) {
lib.setPluginVersions(controllerConfig, pluginInfos);
}
if (!controllerConfig.get("controller.auth_secret")) {
logger.info("Generating new controller authentication secret");
@@ -483,7 +480,7 @@ async function startup() {
controllerConfig,
Boolean(args.canRestart),
Boolean(args.recovery),
...await Controller.bootstrap(controllerConfig, args.recovery ? [] : pluginInfos)
...await Controller.bootstrap(controllerConfig)
);
// Refuse to start if there are no users loaded