Files
git.stella-ops.org/src/AirGap/StellaOps.AirGap.Controller/Services/AirGapStateService.cs
StellaOps Bot d63af51f84
Some checks failed
api-governance / spectral-lint (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
up
2025-11-26 20:23:28 +02:00

71 lines
2.2 KiB
C#

using StellaOps.AirGap.Controller.Domain;
using StellaOps.AirGap.Controller.Stores;
using StellaOps.AirGap.Time.Models;
using StellaOps.AirGap.Time.Services;
namespace StellaOps.AirGap.Controller.Services;
public sealed class AirGapStateService
{
private readonly IAirGapStateStore _store;
private readonly StalenessCalculator _stalenessCalculator;
public AirGapStateService(IAirGapStateStore store, StalenessCalculator stalenessCalculator)
{
_store = store;
_stalenessCalculator = stalenessCalculator;
}
public async Task<AirGapState> SealAsync(
string tenantId,
string policyHash,
TimeAnchor timeAnchor,
StalenessBudget budget,
DateTimeOffset nowUtc,
CancellationToken cancellationToken = default)
{
ArgumentException.ThrowIfNullOrWhiteSpace(policyHash);
budget.Validate();
var newState = new AirGapState
{
TenantId = tenantId,
Sealed = true,
PolicyHash = policyHash,
TimeAnchor = timeAnchor,
StalenessBudget = budget,
LastTransitionAt = nowUtc
};
await _store.SetAsync(newState, cancellationToken);
return newState;
}
public async Task<AirGapState> UnsealAsync(
string tenantId,
DateTimeOffset nowUtc,
CancellationToken cancellationToken = default)
{
var current = await _store.GetAsync(tenantId, cancellationToken);
var newState = current with
{
Sealed = false,
LastTransitionAt = nowUtc
};
await _store.SetAsync(newState, cancellationToken);
return newState;
}
public async Task<AirGapStatus> GetStatusAsync(
string tenantId,
DateTimeOffset nowUtc,
CancellationToken cancellationToken = default)
{
var state = await _store.GetAsync(tenantId, cancellationToken);
var staleness = _stalenessCalculator.Evaluate(state.TimeAnchor, state.StalenessBudget, nowUtc);
return new AirGapStatus(state, staleness, nowUtc);
}
}
public sealed record AirGapStatus(AirGapState State, StalenessEvaluation Staleness, DateTimeOffset EvaluatedAt);