diff --git a/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterHealthCheck.cs b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterHealthCheck.cs
new file mode 100644
index 0000000..3deab3c
--- /dev/null
+++ b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterHealthCheck.cs
@@ -0,0 +1,51 @@
+using Akka.Actor;
+using Akka.Cluster;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+
+namespace ZB.MOM.WW.Health.Akka;
+
+///
+/// Health check that maps the local node's Akka cluster membership status to a
+/// through a configurable .
+/// Register to the tag (recommended [ready, active]).
+///
+///
+/// The is resolved lazily from the service provider. If it is not yet
+/// available — e.g. during startup before Akka is initialised — the check returns
+/// rather than throwing, so it is safe to register before Akka
+/// is fully up.
+///
+public sealed class AkkaClusterHealthCheck : IHealthCheck
+{
+ private readonly IServiceProvider _serviceProvider;
+ private readonly AkkaClusterStatusPolicy _policy;
+
+ /// Initializes a new .
+ ///
+ /// The application service provider. The is resolved lazily so the
+ /// check is startup-safe: if no is registered yet the result is Degraded.
+ ///
+ /// The status-to-health mapping policy to apply.
+ public AkkaClusterHealthCheck(IServiceProvider serviceProvider, AkkaClusterStatusPolicy policy)
+ {
+ _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+ _policy = policy ?? throw new ArgumentNullException(nameof(policy));
+ }
+
+ ///
+ public Task CheckHealthAsync(
+ HealthCheckContext context,
+ CancellationToken cancellationToken = default)
+ {
+ var system = _serviceProvider.GetService();
+ if (system is null)
+ return Task.FromResult(HealthCheckResult.Degraded("ActorSystem not yet available."));
+
+ var status = Cluster.Get(system).SelfMember.Status;
+ var health = _policy.Evaluate(status);
+ var description = $"Akka cluster member status: {status}";
+
+ return Task.FromResult(new HealthCheckResult(health, description));
+ }
+}
diff --git a/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterStatusPolicy.cs b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterStatusPolicy.cs
new file mode 100644
index 0000000..fd01a9b
--- /dev/null
+++ b/ZB.MOM.WW.Health/src/ZB.MOM.WW.Health.Akka/AkkaClusterStatusPolicy.cs
@@ -0,0 +1,56 @@
+using Akka.Cluster;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+
+namespace ZB.MOM.WW.Health.Akka;
+
+///
+/// Pure mapping from an Akka to a .
+///
+///
+///
+/// Wraps a so the decision logic is a deterministic,
+/// table-testable function — only supplies the live cluster
+/// status. Two named presets reconcile the divergence between the existing ScadaBridge and OtOpcUa
+/// implementations; construct a custom instance for project-specific overrides.
+///
+///
+public sealed class AkkaClusterStatusPolicy
+{
+ private readonly Func _evaluate;
+
+ /// Initializes a new .
+ /// The pure status-to-health mapping function.
+ public AkkaClusterStatusPolicy(Func evaluate)
+ {
+ _evaluate = evaluate ?? throw new ArgumentNullException(nameof(evaluate));
+ }
+
+ /// Applies the policy to the given member status.
+ /// The local node's Akka cluster member status.
+ /// The mapped .
+ public HealthStatus Evaluate(MemberStatus status) => _evaluate(status);
+
+ ///
+ /// ScadaBridge origin: Up/Joining → Healthy, Leaving/Exiting →
+ /// Degraded, everything else → Unhealthy. The convergence target for all projects.
+ ///
+ public static AkkaClusterStatusPolicy Default { get; } = new(static status => status switch
+ {
+ MemberStatus.Up or MemberStatus.Joining => HealthStatus.Healthy,
+ MemberStatus.Leaving or MemberStatus.Exiting => HealthStatus.Degraded,
+ _ => HealthStatus.Unhealthy,
+ });
+
+ ///
+ /// OtOpcUa origin: self-Up-among-reachable-members → Healthy, any non-Up state
+ /// (including Leaving/Exiting/Down) → Degraded. Provided for backward
+ /// compatibility during OtOpcUa's migration.
+ ///
+ ///
+ /// The original OtOpcUa check scanned the reachable member set for self with
+ /// Status == Up; any other state caused the scan to miss self and collapse to Degraded.
+ /// This preset reproduces that behavior: only is Healthy.
+ ///
+ public static AkkaClusterStatusPolicy OtOpcUaCompat { get; } = new(static status =>
+ status == MemberStatus.Up ? HealthStatus.Healthy : HealthStatus.Degraded);
+}
diff --git a/ZB.MOM.WW.Health/tests/ZB.MOM.WW.Health.Akka.Tests/AkkaClusterStatusPolicyTests.cs b/ZB.MOM.WW.Health/tests/ZB.MOM.WW.Health.Akka.Tests/AkkaClusterStatusPolicyTests.cs
new file mode 100644
index 0000000..3e2d347
--- /dev/null
+++ b/ZB.MOM.WW.Health/tests/ZB.MOM.WW.Health.Akka.Tests/AkkaClusterStatusPolicyTests.cs
@@ -0,0 +1,75 @@
+using Akka.Cluster;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+using ZB.MOM.WW.Health.Akka;
+
+namespace ZB.MOM.WW.Health.Akka.Tests;
+
+///
+/// Table-driven tests for the pure status-mapping function inside .
+/// The two presets ( and
+/// ) are the convergence targets for ScadaBridge
+/// and OtOpcUa respectively; every is exercised so a drift in either
+/// preset fails loudly. Also covers the startup-safety null-guard on .
+///
+public sealed class AkkaClusterStatusPolicyTests
+{
+ public static IEnumerable