using Nexus.Api.Repositories;
namespace Nexus.Api.Services;
///
/// Process-local projection of the persisted, owner-approved OpenClaw
/// management boundary. The database profile remains the durable authority;
/// this projection lets synchronous capability checks use the same decision.
///
public interface IOpenClawManagementState
{
bool Enabled { get; }
void SetEnabled(bool enabled);
}
public sealed class OpenClawManagementState : IOpenClawManagementState
{
private int enabled;
public bool Enabled => Volatile.Read(ref enabled) == 1;
public void SetEnabled(bool value)
=> Interlocked.Exchange(ref enabled, value ? 1 : 0);
}
///
/// Hydrates the local projection from the primary persisted connection profile
/// once application services are available.
///
public sealed class OpenClawManagementStateInitializer(
IServiceScopeFactory scopeFactory,
IOpenClawManagementState state,
ILogger logger) : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
state.SetEnabled(false);
try
{
await using var scope = scopeFactory.CreateAsyncScope();
var profiles = scope.ServiceProvider
.GetRequiredService();
var profile = await profiles.GetPrimaryAsync(cancellationToken);
state.SetEnabled(profile?.ManagementEnabled ?? false);
}
catch (Exception exception)
{
logger.LogWarning(
exception,
"OpenClaw management state could not be hydrated from the primary profile");
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}