Service that loads and validates host authority policy and owner data from an IAdminStore, keeps an in-memory PolicyResolver and OwnerSet, and exposes reload/initialization helpers and status properties. It serializes operations with a semaphore, reads stored policy and owners, applies validation checks, and reports audit/errors via provided delegates.
using SboxSuperuser.Core.Permissions;
using SboxSuperuser.Core.Storage;
using SboxSuperuser.Engine.Audit;
namespace SboxSuperuser.Engine.Authority;
internal sealed partial class HostPolicyService
{
private readonly IAdminStore _store;
private readonly Func<bool> _available;
private readonly Action<Exception> _report;
private readonly OwnerSet _bootstrapOwners;
private readonly StoreReadStatus _bootstrapOwnerStatus;
private readonly SemaphoreSlim _gate = new( 1, 1 );
private readonly PolicyResolver _resolver;
private OwnerSet _owners;
private long _ownerRevision;
private bool _managedOwners;
private readonly IAuditWriter _audit;
internal Task Initialization { get; }
internal StoreReadStatus PolicyStatus { get; private set; } = StoreReadStatus.Unknown;
internal StoreReadStatus OwnerStatus { get; private set; } = StoreReadStatus.Unknown;
internal StoreWriteStatus LastWriteStatus { get; private set; } = StoreWriteStatus.Unknown;
internal long PolicyRevision => _resolver.Policy.Revision;
internal long OwnerRevision => _ownerRevision;
internal IReadOnlyList<string> RegisteredPermissions => _resolver.RegisteredPermissions;
internal bool IsUsable => _available() && (PolicyStatus is StoreReadStatus.Found or StoreReadStatus.Missing)
&& (OwnerStatus is StoreReadStatus.Found or StoreReadStatus.Missing);
internal int OwnerCount => OwnerStatus == StoreReadStatus.Found ? _owners?.Ids.Count ?? 0 : 0;
internal string OwnerSource => _managedOwners ? "managed" : "bootstrap";
internal static StoreKey PolicyKey { get; } = new( "security", "policy" );
internal static StoreKey OwnersKey { get; } = new( "security", "owners" );
internal HostPolicyService( IAdminStore store, IEnumerable<string> bootstrapOwners,
StoreReadStatus bootstrapOwnerStatus, Func<bool> available, Action<Exception> report, IAuditWriter audit = null )
{
_store = store;
_available = available;
_report = report;
_audit = audit;
_bootstrapOwners = new OwnerSet( bootstrapOwners );
_bootstrapOwnerStatus = bootstrapOwnerStatus;
_owners = _bootstrapOwners;
var defaults = PolicySnapshot.CreateDefault().Graph;
var permissions = defaults.Groups.Values.SelectMany( group => group.Entries.Keys )
.Concat( new[] { "admin.permissions.explain", "admin.security.manage", "admin.audit.read" } )
.Distinct( StringComparer.Ordinal );
_resolver = new PolicyResolver( defaults, permissions );
Initialization = LoadAsync( CancellationToken.None );
}
internal async Task<CommandResult> ReloadAsync( CancellationToken cancellation )
{
return await SerializedAsync( async () =>
{
await LoadAsync( cancellation );
return new CommandResult( IsUsable ? CommandStatus.Success : CommandStatus.StorageUnavailable,
IsUsable ? "Validated authority state reloaded." : "Authority storage is degraded; existing files preserved." );
}, cancellation );
}
private async Task LoadAsync( CancellationToken cancellation )
{
var policy = await ReadStoredAsync( PolicyKey, cancellation );
PolicyStatus = policy.Status;
try
{
if ( policy.Status == StoreReadStatus.Found )
{
var graph = PolicyCodec.ReadPayload( policy.Document.PayloadJson, policy.Document.Revision );
if ( graph.Revision > _resolver.Policy.Revision )
{
_resolver.ReplacePolicy( graph );
}
else if ( graph.Revision != _resolver.Policy.Revision
|| PolicyCodec.WriteState( graph ) != PolicyCodec.WriteState( _resolver.Policy ) )
{
PolicyStatus = StoreReadStatus.Corrupt;
}
}
else if ( policy.Status == StoreReadStatus.Missing && _resolver.Policy.Revision > 0 )
{
PolicyStatus = StoreReadStatus.Corrupt;
}
}
catch ( Exception error )
{
PolicyStatus = error is UnsupportedStoreSchemaException ? StoreReadStatus.UnsupportedSchema : StoreReadStatus.Corrupt;
_report( error );
}
var owners = await ReadStoredAsync( OwnersKey, cancellation );
OwnerStatus = owners.Status;
try
{
if ( owners.Status == StoreReadStatus.Found )
{
var candidate = PolicyCodec.ReadOwners( owners.Document.PayloadJson );
if ( owners.Document.Revision < _ownerRevision
|| owners.Document.Revision == _ownerRevision && !_owners.Ids.SequenceEqual( candidate.Ids ) )
{
OwnerStatus = StoreReadStatus.Corrupt;
return;
}
_owners = candidate;
_ownerRevision = owners.Document.Revision;
_managedOwners = true;
}
else if ( owners.Status == StoreReadStatus.Missing && !_managedOwners )
{
_owners = _bootstrapOwners;
OwnerStatus = _bootstrapOwnerStatus;
}
else
{
_managedOwners = true;
OwnerStatus = owners.Status == StoreReadStatus.Missing ? StoreReadStatus.Corrupt : owners.Status;
}
}
catch ( Exception error )
{
_managedOwners = true;
OwnerStatus = error is UnsupportedStoreSchemaException ? StoreReadStatus.UnsupportedSchema : StoreReadStatus.Corrupt;
_report( error );
}
}
private async Task<StoreReadResult> ReadStoredAsync( StoreKey key, CancellationToken cancellation )
{
try
{
return await _store.ReadAsync( key, 1, cancellation );
}
catch ( OperationCanceledException )
{
return new StoreReadResult( StoreReadStatus.Cancelled );
}
catch ( Exception error )
{
_report( error );
return new StoreReadResult( StoreReadStatus.Unavailable );
}
}
private async Task<CommandResult> SerializedAsync( Func<Task<CommandResult>> action, CancellationToken cancellation )
{
var entered = false;
try
{
await Initialization;
await _gate.WaitAsync( cancellation );
entered = true;
cancellation.ThrowIfCancellationRequested();
if ( !_available() )
{
return new CommandResult( CommandStatus.Unsupported, "Authority runtime is unavailable." );
}
return await action();
}
catch ( OperationCanceledException )
{
return new CommandResult( CommandStatus.Cancelled, "Request cancelled before a confirmed change." );
}
catch ( ArgumentException error )
{
_report( error );
return new CommandResult( CommandStatus.InvalidArguments, "Invalid policy edit; no candidate was activated." );
}
catch ( Exception error )
{
_report( error );
return new CommandResult( CommandStatus.Unknown, "Authority operation failed without a confirmed outcome; inspect storage." );
}
finally
{
if ( entered )
{
_gate.Release();
}
}
}
}