feat: Initialize Zastava Webhook service with TLS and Authority authentication

- Added Program.cs to set up the web application with Serilog for logging, health check endpoints, and a placeholder admission endpoint.
- Configured Kestrel server to use TLS 1.3 and handle client certificates appropriately.
- Created StellaOps.Zastava.Webhook.csproj with necessary dependencies including Serilog and Polly.
- Documented tasks in TASKS.md for the Zastava Webhook project, outlining current work and exit criteria for each task.
This commit is contained in:
master
2025-10-19 18:36:22 +03:00
parent 2062da7a8b
commit d099a90f9b
966 changed files with 91038 additions and 1850 deletions

View File

@@ -0,0 +1,57 @@
using Microsoft.Extensions.Caching.Memory;
namespace StellaOps.Excititor.WebService.Services;
internal sealed class MirrorRateLimiter
{
private readonly IMemoryCache _cache;
private readonly TimeProvider _timeProvider;
private static readonly TimeSpan Window = TimeSpan.FromHours(1);
public MirrorRateLimiter(IMemoryCache cache, TimeProvider timeProvider)
{
_cache = cache ?? throw new ArgumentNullException(nameof(cache));
_timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
}
public bool TryAcquire(string domainId, string scope, int limit, out TimeSpan? retryAfter)
{
retryAfter = null;
if (limit <= 0 || limit == int.MaxValue)
{
return true;
}
var key = CreateKey(domainId, scope);
var now = _timeProvider.GetUtcNow();
var counter = _cache.Get<Counter>(key);
if (counter is null || now - counter.WindowStart >= Window)
{
counter = new Counter(now, 0);
}
if (counter.Count >= limit)
{
var windowEnd = counter.WindowStart + Window;
retryAfter = windowEnd > now ? windowEnd - now : TimeSpan.Zero;
return false;
}
counter = counter with { Count = counter.Count + 1 };
var absoluteExpiration = counter.WindowStart + Window;
_cache.Set(key, counter, absoluteExpiration);
return true;
}
private static string CreateKey(string domainId, string scope)
=> string.Create(domainId.Length + scope.Length + 1, (domainId, scope), static (span, state) =>
{
state.domainId.AsSpan().CopyTo(span);
span[state.domainId.Length] = '|';
state.scope.AsSpan().CopyTo(span[(state.domainId.Length + 1)..]);
});
private sealed record Counter(DateTimeOffset WindowStart, int Count);
}