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

@@ -23,6 +23,8 @@ public interface IScanQueueLease
string? IdempotencyKey { get; }
string? TraceId { get; }
IReadOnlyDictionary<string, string> Attributes { get; }
Task AcknowledgeAsync(CancellationToken cancellationToken = default);

View File

@@ -501,6 +501,10 @@ internal sealed class NatsScanQueue : IScanQueue, IAsyncDisposable
? idemValues[0]
: null;
var traceId = headers.TryGetValue(QueueEnvelopeFields.TraceId, out var traceValues) && traceValues.Count > 0
? string.IsNullOrWhiteSpace(traceValues[0]) ? null : traceValues[0]
: null;
var enqueuedAt = headers.TryGetValue(QueueEnvelopeFields.EnqueuedAt, out var enqueuedValues) && enqueuedValues.Count > 0
&& long.TryParse(enqueuedValues[0], out var unix)
? DateTimeOffset.FromUnixTimeMilliseconds(unix)
@@ -535,6 +539,7 @@ internal sealed class NatsScanQueue : IScanQueue, IAsyncDisposable
leaseExpires,
consumer,
idempotencyKey,
traceId,
attributes);
}
@@ -597,6 +602,11 @@ internal sealed class NatsScanQueue : IScanQueue, IAsyncDisposable
{ "deadletter-reason", reason }
};
if (!string.IsNullOrWhiteSpace(lease.TraceId))
{
headers.Add(QueueEnvelopeFields.TraceId, lease.TraceId!);
}
foreach (var kvp in lease.Attributes)
{
headers.Add(QueueEnvelopeFields.AttributePrefix + kvp.Key, kvp.Value);

View File

@@ -23,6 +23,7 @@ internal sealed class NatsScanQueueLease : IScanQueueLease
DateTimeOffset leaseExpiresAt,
string consumer,
string? idempotencyKey,
string? traceId,
IReadOnlyDictionary<string, string> attributes)
{
_queue = queue;
@@ -35,6 +36,7 @@ internal sealed class NatsScanQueueLease : IScanQueueLease
LeaseExpiresAt = leaseExpiresAt;
Consumer = consumer;
IdempotencyKey = idempotencyKey;
TraceId = traceId;
Attributes = attributes;
}
@@ -54,6 +56,8 @@ internal sealed class NatsScanQueueLease : IScanQueueLease
public string? IdempotencyKey { get; }
public string? TraceId { get; }
public IReadOnlyDictionary<string, string> Attributes { get; }
internal NatsJSMsg<byte[]> Message => _message;

View File

@@ -405,7 +405,7 @@ internal sealed class RedisScanQueue : IScanQueue, IAsyncDisposable
{
IdempotencyKey = lease.IdempotencyKey,
Attributes = lease.Attributes,
TraceId = null
TraceId = lease.TraceId
};
var now = _timeProvider.GetUtcNow();
@@ -463,7 +463,7 @@ internal sealed class RedisScanQueue : IScanQueue, IAsyncDisposable
{
IdempotencyKey = lease.IdempotencyKey,
Attributes = lease.Attributes,
TraceId = null
TraceId = lease.TraceId
},
now,
lease.Attempt);
@@ -644,7 +644,8 @@ internal sealed class RedisScanQueue : IScanQueue, IAsyncDisposable
}
else if (name.Equals(QueueEnvelopeFields.TraceId, StringComparison.Ordinal))
{
traceId = field.Value.ToString();
var value = field.Value.ToString();
traceId = string.IsNullOrWhiteSpace(value) ? null : value;
}
else if (name.StartsWith(QueueEnvelopeFields.AttributePrefix, StringComparison.Ordinal))
{
@@ -674,6 +675,7 @@ internal sealed class RedisScanQueue : IScanQueue, IAsyncDisposable
leaseExpires,
consumer,
idempotency,
traceId,
attributeView);
}

View File

@@ -20,6 +20,7 @@ internal sealed class RedisScanQueueLease : IScanQueueLease
DateTimeOffset leaseExpiresAt,
string consumer,
string? idempotencyKey,
string? traceId,
IReadOnlyDictionary<string, string> attributes)
{
_queue = queue;
@@ -31,6 +32,7 @@ internal sealed class RedisScanQueueLease : IScanQueueLease
LeaseExpiresAt = leaseExpiresAt;
Consumer = consumer;
IdempotencyKey = idempotencyKey;
TraceId = traceId;
Attributes = attributes;
}
@@ -50,6 +52,8 @@ internal sealed class RedisScanQueueLease : IScanQueueLease
public string? IdempotencyKey { get; }
public string? TraceId { get; }
public IReadOnlyDictionary<string, string> Attributes { get; }
public Task AcknowledgeAsync(CancellationToken cancellationToken = default)