diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/ServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000..6f56dfa
--- /dev/null
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/ServiceCollectionExtensions.cs
@@ -0,0 +1,91 @@
+using Akka.Actor;
+using Akka.Cluster.Hosting;
+using Akka.Hosting;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using ZB.MOM.WW.OtOpcUa.Configuration;
+using ZB.MOM.WW.OtOpcUa.ControlPlane.AdminOperations;
+using ZB.MOM.WW.OtOpcUa.ControlPlane.Audit;
+using ZB.MOM.WW.OtOpcUa.ControlPlane.Coordinators;
+using ZB.MOM.WW.OtOpcUa.ControlPlane.Fleet;
+using ZB.MOM.WW.OtOpcUa.ControlPlane.Redundancy;
+
+namespace ZB.MOM.WW.OtOpcUa.ControlPlane;
+
+public static class ServiceCollectionExtensions
+{
+ public const string AdminRole = "admin";
+
+ public const string ConfigPublishSingletonName = "config-publish";
+ public const string AdminOperationsSingletonName = "admin-operations";
+ public const string AuditWriterSingletonName = "audit-writer";
+ public const string FleetStatusSingletonName = "fleet-status";
+ public const string RedundancyStateSingletonName = "redundancy-state";
+
+ ///
+ /// Registers all five admin-role cluster singletons + their proxies on the AkkaConfigurationBuilder.
+ /// Must be called against the same builder used by AkkaHostedService so the singletons
+ /// share the host's ActorSystem.
+ ///
+ /// Wire from the fused Host's Program.cs:
+ ///
+ /// builder.Services.AddAkka("otopcua", (ab, sp) =>
+ /// {
+ /// ab.WithRemoting(/* ... */).WithClustering(/* ... */);
+ /// ab.WithOtOpcUaControlPlaneSingletons();
+ /// });
+ ///
+ ///
+ public static AkkaConfigurationBuilder WithOtOpcUaControlPlaneSingletons(this AkkaConfigurationBuilder builder)
+ {
+ var singletonOptions = new ClusterSingletonOptions { Role = AdminRole };
+ var proxyOptions = new ClusterSingletonOptions { Role = AdminRole };
+
+ builder.WithSingleton(
+ ConfigPublishSingletonName,
+ (system, registry, resolver) =>
+ {
+ var dbFactory = resolver.GetService>();
+ return ConfigPublishCoordinator.Props(dbFactory);
+ },
+ singletonOptions);
+
+ builder.WithSingleton(
+ AdminOperationsSingletonName,
+ (system, registry, resolver) =>
+ {
+ var dbFactory = resolver.GetService>();
+ var coordinator = registry.Get();
+ return AdminOperationsActor.Props(dbFactory, coordinator);
+ },
+ singletonOptions);
+
+ builder.WithSingleton(
+ AuditWriterSingletonName,
+ (system, registry, resolver) =>
+ {
+ var dbFactory = resolver.GetService>();
+ return AuditWriterActor.Props(dbFactory);
+ },
+ singletonOptions);
+
+ builder.WithSingleton(
+ FleetStatusSingletonName,
+ (system, registry, resolver) => FleetStatusBroadcaster.Props(),
+ singletonOptions);
+
+ builder.WithSingleton(
+ RedundancyStateSingletonName,
+ (system, registry, resolver) => RedundancyStateActor.Props(),
+ singletonOptions);
+
+ return builder;
+ }
+}
+
+/// Marker key types used by Akka.Hosting to resolve singletons from the registry.
+public sealed class ConfigPublishCoordinatorKey { }
+public sealed class AdminOperationsActorKey { }
+public sealed class AuditWriterActorKey { }
+public sealed class FleetStatusBroadcasterKey { }
+public sealed class RedundancyStateActorKey { }