up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Policy.Engine.TrustWeighting;
|
||||
|
||||
internal sealed record TrustWeightingEntry(
|
||||
[property: JsonPropertyName("source")] string Source,
|
||||
[property: JsonPropertyName("weight")] decimal Weight,
|
||||
[property: JsonPropertyName("justification")] string? Justification,
|
||||
[property: JsonPropertyName("updated_at")] string UpdatedAt);
|
||||
|
||||
internal sealed record TrustWeightingProfile(
|
||||
[property: JsonPropertyName("weights")] IReadOnlyList<TrustWeightingEntry> Weights,
|
||||
[property: JsonPropertyName("profile_hash")] string ProfileHash);
|
||||
@@ -0,0 +1,77 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.Policy.Engine.TrustWeighting;
|
||||
|
||||
/// <summary>
|
||||
/// In-memory trust weighting profile store (stub for POLICY-ENGINE-30-101).
|
||||
/// Deterministic ordering and hashing.
|
||||
/// </summary>
|
||||
internal sealed class TrustWeightingService
|
||||
{
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly object _lock = new();
|
||||
private TrustWeightingProfile _current;
|
||||
|
||||
public TrustWeightingService(TimeProvider timeProvider)
|
||||
{
|
||||
_timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
|
||||
_current = BuildProfile(DefaultWeights());
|
||||
}
|
||||
|
||||
public TrustWeightingProfile Get() => _current;
|
||||
|
||||
public TrustWeightingProfile Set(IReadOnlyList<TrustWeightingEntry> entries)
|
||||
{
|
||||
var normalized = Normalize(entries);
|
||||
var profile = BuildProfile(normalized);
|
||||
lock (_lock)
|
||||
{
|
||||
_current = profile;
|
||||
}
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
private TrustWeightingProfile BuildProfile(IReadOnlyList<TrustWeightingEntry> weights)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(weights, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = false
|
||||
});
|
||||
|
||||
var hash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(json)));
|
||||
return new TrustWeightingProfile(weights, hash);
|
||||
}
|
||||
|
||||
private IReadOnlyList<TrustWeightingEntry> Normalize(IReadOnlyList<TrustWeightingEntry> entries)
|
||||
{
|
||||
var now = _timeProvider.GetUtcNow().ToString("O");
|
||||
|
||||
var normalized = entries
|
||||
.Where(e => !string.IsNullOrWhiteSpace(e.Source))
|
||||
.Select(e => new TrustWeightingEntry(
|
||||
Source: e.Source.Trim().ToLowerInvariant(),
|
||||
Weight: Math.Round(e.Weight, 3, MidpointRounding.ToZero),
|
||||
Justification: string.IsNullOrWhiteSpace(e.Justification) ? null : e.Justification.Trim(),
|
||||
UpdatedAt: string.IsNullOrWhiteSpace(e.UpdatedAt) ? now : e.UpdatedAt))
|
||||
.OrderBy(e => e.Source, StringComparer.Ordinal)
|
||||
.ToList();
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<TrustWeightingEntry> DefaultWeights()
|
||||
{
|
||||
var now = TimeProvider.System.GetUtcNow().ToString("O");
|
||||
return new[]
|
||||
{
|
||||
new TrustWeightingEntry("cartographer", 1.000m, null, now),
|
||||
new TrustWeightingEntry("concelier", 1.000m, null, now),
|
||||
new TrustWeightingEntry("scanner", 1.000m, null, now),
|
||||
new TrustWeightingEntry("advisory_ai", 1.000m, null, now)
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user