fix: clean up worktree refs + remaining schema extraction + route fixes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,7 @@ public static class AuditEndpoints
|
||||
.RequireTenant();
|
||||
|
||||
// List and get operations
|
||||
group.MapGet(string.Empty, ListAuditEntries)
|
||||
group.MapGet(string.Empty, ListAuditEntriesHandler)
|
||||
.WithName("ReleaseOrchestrator_ListAuditEntries")
|
||||
.WithDescription(_t("orchestrator.audit.list_description"));
|
||||
|
||||
@@ -56,7 +56,7 @@ public static class AuditEndpoints
|
||||
return group;
|
||||
}
|
||||
|
||||
private static async Task<IResult> ListAuditEntries(
|
||||
internal static async Task<IResult> ListAuditEntriesHandler(
|
||||
HttpContext context,
|
||||
[FromServices] TenantResolver tenantResolver,
|
||||
[FromServices] IAuditRepository repository,
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using StellaOps.Auth.ServerIntegration.Tenancy;
|
||||
using StellaOps.JobEngine.Core.Domain;
|
||||
using StellaOps.JobEngine.Infrastructure.Repositories;
|
||||
using StellaOps.ReleaseOrchestrator.WebApi.Contracts;
|
||||
using StellaOps.ReleaseOrchestrator.WebApi.Services;
|
||||
|
||||
namespace StellaOps.ReleaseOrchestrator.WebApi.Endpoints;
|
||||
|
||||
@@ -42,7 +37,7 @@ public static class JobEngineLegacyEndpoints
|
||||
.RequireAuthorization(ReleaseOrchestratorPolicies.Read)
|
||||
.RequireTenant();
|
||||
|
||||
group.MapGet("events", AuditEndpoints.ListAuditEventsLegacy);
|
||||
group.MapGet("events", AuditEndpoints.ListAuditEntriesHandler);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Npgsql;
|
||||
using StellaOps.Infrastructure.Postgres.Connections;
|
||||
using StellaOps.Infrastructure.Postgres.Options;
|
||||
|
||||
namespace StellaOps.ReleaseOrchestrator.Persistence.Postgres;
|
||||
|
||||
/// <summary>
|
||||
/// PostgreSQL data source for the ReleaseOrchestrator module.
|
||||
/// </summary>
|
||||
public sealed class ReleaseOrchestratorDataSource : DataSourceBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Default schema name for release-orchestrator tables.
|
||||
/// </summary>
|
||||
public const string DefaultSchemaName = "release_orchestrator";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ReleaseOrchestrator data source.
|
||||
/// </summary>
|
||||
public ReleaseOrchestratorDataSource(IOptions<PostgresOptions> options, ILogger<ReleaseOrchestratorDataSource> logger)
|
||||
: base(CreateOptions(options.Value), logger)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string ModuleName => "ReleaseOrchestrator";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void ConfigureDataSourceBuilder(NpgsqlDataSourceBuilder builder)
|
||||
{
|
||||
base.ConfigureDataSourceBuilder(builder);
|
||||
}
|
||||
|
||||
private static PostgresOptions CreateOptions(PostgresOptions baseOptions)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(baseOptions.SchemaName))
|
||||
{
|
||||
baseOptions.SchemaName = DefaultSchemaName;
|
||||
}
|
||||
return baseOptions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using StellaOps.ReleaseOrchestrator.Persistence.Domain;
|
||||
|
||||
namespace StellaOps.ReleaseOrchestrator.Persistence.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Repository for audit log entries.
|
||||
/// </summary>
|
||||
public interface IAuditRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Appends a new audit entry to the log.
|
||||
/// </summary>
|
||||
Task<AuditEntry> AppendAsync(
|
||||
string tenantId,
|
||||
AuditEventType eventType,
|
||||
string resourceType,
|
||||
Guid resourceId,
|
||||
string actorId,
|
||||
ActorType actorType,
|
||||
string description,
|
||||
string? oldState = null,
|
||||
string? newState = null,
|
||||
string? actorIp = null,
|
||||
string? userAgent = null,
|
||||
string? httpMethod = null,
|
||||
string? requestPath = null,
|
||||
string? correlationId = null,
|
||||
string? metadata = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an audit entry by ID.
|
||||
/// </summary>
|
||||
Task<AuditEntry?> GetByIdAsync(
|
||||
string tenantId,
|
||||
Guid entryId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Lists audit entries with optional filters.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<AuditEntry>> ListAsync(
|
||||
string tenantId,
|
||||
AuditEventType? eventType = null,
|
||||
string? resourceType = null,
|
||||
Guid? resourceId = null,
|
||||
string? actorId = null,
|
||||
DateTimeOffset? startTime = null,
|
||||
DateTimeOffset? endTime = null,
|
||||
int limit = 100,
|
||||
int offset = 0,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets audit entries by sequence range.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<AuditEntry>> GetBySequenceRangeAsync(
|
||||
string tenantId,
|
||||
long startSequence,
|
||||
long endSequence,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest audit entry for a tenant.
|
||||
/// </summary>
|
||||
Task<AuditEntry?> GetLatestAsync(
|
||||
string tenantId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets audit entries for a specific resource.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<AuditEntry>> GetByResourceAsync(
|
||||
string tenantId,
|
||||
string resourceType,
|
||||
Guid resourceId,
|
||||
int limit = 100,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of audit entries.
|
||||
/// </summary>
|
||||
Task<long> GetCountAsync(
|
||||
string tenantId,
|
||||
AuditEventType? eventType = null,
|
||||
DateTimeOffset? startTime = null,
|
||||
DateTimeOffset? endTime = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the chain integrity for a range of entries.
|
||||
/// </summary>
|
||||
Task<ChainVerificationResult> VerifyChainAsync(
|
||||
string tenantId,
|
||||
long? startSequence = null,
|
||||
long? endSequence = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets audit summary statistics.
|
||||
/// </summary>
|
||||
Task<AuditSummary> GetSummaryAsync(
|
||||
string tenantId,
|
||||
DateTimeOffset? since = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result of chain verification.
|
||||
/// </summary>
|
||||
public sealed record ChainVerificationResult(
|
||||
bool IsValid,
|
||||
Guid? InvalidEntryId,
|
||||
long? InvalidSequence,
|
||||
string? ErrorMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Audit summary statistics.
|
||||
/// </summary>
|
||||
public sealed record AuditSummary(
|
||||
long TotalEntries,
|
||||
long EntriesSince,
|
||||
long EventTypes,
|
||||
long UniqueActors,
|
||||
long UniqueResources,
|
||||
DateTimeOffset? EarliestEntry,
|
||||
DateTimeOffset? LatestEntry);
|
||||
@@ -0,0 +1,50 @@
|
||||
using StellaOps.ReleaseOrchestrator.Persistence.Domain;
|
||||
|
||||
namespace StellaOps.ReleaseOrchestrator.Persistence.Services;
|
||||
|
||||
public interface IFirstSignalService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the first signal for a run, checking cache first.
|
||||
/// </summary>
|
||||
Task<FirstSignalResult> GetFirstSignalAsync(
|
||||
Guid runId,
|
||||
string tenantId,
|
||||
string? ifNoneMatch = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the first signal snapshot for a run and invalidates any cached copies.
|
||||
/// </summary>
|
||||
Task UpdateSnapshotAsync(
|
||||
Guid runId,
|
||||
string tenantId,
|
||||
FirstSignal signal,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates cached first signal for a run.
|
||||
/// </summary>
|
||||
Task InvalidateCacheAsync(
|
||||
Guid runId,
|
||||
string tenantId,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
public sealed record FirstSignalResult
|
||||
{
|
||||
public required FirstSignalResultStatus Status { get; init; }
|
||||
public FirstSignal? Signal { get; init; }
|
||||
public string? ETag { get; init; }
|
||||
public bool CacheHit { get; init; }
|
||||
public string? Source { get; init; }
|
||||
}
|
||||
|
||||
public enum FirstSignalResultStatus
|
||||
{
|
||||
Found,
|
||||
NotModified,
|
||||
NotFound,
|
||||
NotAvailable,
|
||||
Error
|
||||
}
|
||||
Reference in New Issue
Block a user