search and ai stabilization work, localization stablized.

This commit is contained in:
master
2026-02-24 23:29:36 +02:00
parent 4f947a8b61
commit b07d27772e
766 changed files with 55299 additions and 3221 deletions

View File

@@ -3,6 +3,7 @@ using StellaOps.Authority.Persistence.Documents;
using StellaOps.Authority.Persistence.Sessions;
using System.Collections.Concurrent;
using System.Threading;
using static StellaOps.Localization.T;
namespace StellaOps.Authority.Persistence.InMemory.Stores;
@@ -716,7 +717,7 @@ public sealed class InMemoryRevocationExportStateStore : IAuthorityRevocationExp
{
if (state.Sequence != expectedSequence)
{
throw new InvalidOperationException($"Revocation export sequence mismatch. Expected {expectedSequence}, current {state.Sequence}.");
throw new InvalidOperationException(_t("auth.persistence.revocation_sequence_mismatch", expectedSequence, state.Sequence));
}
state = new AuthorityRevocationExportStateDocument

View File

@@ -1,15 +1,15 @@
using System;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using StellaOps.Authority.Persistence.EfCore.CompiledModels;
using StellaOps.Authority.Persistence.EfCore.Context;
namespace StellaOps.Authority.Persistence.Postgres;
/// <summary>
/// Runtime factory for creating <see cref="AuthorityDbContext"/> instances.
/// Uses the static compiled model when schema matches the default; falls back to
/// reflection-based model building for non-default schemas (integration tests).
/// Always uses reflection-based model building from <see cref="AuthorityDbContext.OnModelCreating"/>.
/// When a real compiled model is generated via <c>dotnet ef dbcontext optimize</c>,
/// re-enable UseModel() here.
/// </summary>
internal static class AuthorityDbContextFactory
{
@@ -22,12 +22,6 @@ internal static class AuthorityDbContextFactory
var optionsBuilder = new DbContextOptionsBuilder<AuthorityDbContext>()
.UseNpgsql(connection, npgsql => npgsql.CommandTimeout(commandTimeoutSeconds));
if (string.Equals(normalizedSchema, AuthorityDataSource.DefaultSchemaName, StringComparison.Ordinal))
{
// Use the static compiled model when schema mapping matches the default model.
optionsBuilder.UseModel(AuthorityDbContextModel.Instance);
}
return new AuthorityDbContext(optionsBuilder.Options, normalizedSchema);
}
}

View File

@@ -109,7 +109,7 @@ public sealed class ApiKeyRepository : IApiKeyRepository
await dbContext.Database.ExecuteSqlRawAsync(
"UPDATE authority.api_keys SET last_used_at = NOW() WHERE tenant_id = {0} AND id = {1}",
tenantId, id,
[tenantId, id],
cancellationToken).ConfigureAwait(false);
}
@@ -123,7 +123,7 @@ public sealed class ApiKeyRepository : IApiKeyRepository
UPDATE authority.api_keys SET status = 'revoked', revoked_at = NOW(), revoked_by = {0}
WHERE tenant_id = {1} AND id = {2} AND status = 'active'
""",
revokedBy, tenantId, id,
[revokedBy, tenantId, id],
cancellationToken).ConfigureAwait(false);
}

View File

@@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using StellaOps.Authority.Persistence.EfCore.Models;
using StellaOps.Authority.Persistence.Postgres.Models;
using static StellaOps.Localization.T;
namespace StellaOps.Authority.Persistence.Postgres.Repositories;
@@ -58,7 +59,7 @@ public sealed class RevocationExportStateRepository
if (affected == 0)
{
throw new InvalidOperationException($"Revocation export state update rejected. Expected sequence {expectedSequence}.");
throw new InvalidOperationException(_t("auth.persistence.revocation_update_rejected", expectedSequence));
}
}

View File

@@ -119,7 +119,7 @@ public sealed class SessionRepository : ISessionRepository
await dbContext.Database.ExecuteSqlRawAsync(
"UPDATE authority.sessions SET last_activity_at = NOW() WHERE tenant_id = {0} AND id = {1} AND ended_at IS NULL",
tenantId, id,
[tenantId, id],
cancellationToken).ConfigureAwait(false);
}
@@ -133,7 +133,7 @@ public sealed class SessionRepository : ISessionRepository
UPDATE authority.sessions SET ended_at = NOW(), end_reason = {0}
WHERE tenant_id = {1} AND id = {2} AND ended_at IS NULL
""",
reason, tenantId, id,
[reason, tenantId, id],
cancellationToken).ConfigureAwait(false);
}
@@ -147,7 +147,7 @@ public sealed class SessionRepository : ISessionRepository
UPDATE authority.sessions SET ended_at = NOW(), end_reason = {0}
WHERE tenant_id = {1} AND user_id = {2} AND ended_at IS NULL
""",
reason, tenantId, userId,
[reason, tenantId, userId],
cancellationToken).ConfigureAwait(false);
}
@@ -158,6 +158,7 @@ public sealed class SessionRepository : ISessionRepository
await dbContext.Database.ExecuteSqlRawAsync(
"DELETE FROM authority.sessions WHERE expires_at < NOW() - INTERVAL '30 days'",
[],
cancellationToken).ConfigureAwait(false);
}

View File

@@ -106,7 +106,7 @@ public sealed class TokenRepository : ITokenRepository
UPDATE authority.tokens SET revoked_at = NOW(), revoked_by = {0}
WHERE tenant_id = {1} AND id = {2} AND revoked_at IS NULL
""",
revokedBy, tenantId, id,
[revokedBy, tenantId, id],
cancellationToken).ConfigureAwait(false);
}
@@ -120,7 +120,7 @@ public sealed class TokenRepository : ITokenRepository
UPDATE authority.tokens SET revoked_at = NOW(), revoked_by = {0}
WHERE tenant_id = {1} AND user_id = {2} AND revoked_at IS NULL
""",
revokedBy, tenantId, userId,
[revokedBy, tenantId, userId],
cancellationToken).ConfigureAwait(false);
}
@@ -131,6 +131,7 @@ public sealed class TokenRepository : ITokenRepository
await dbContext.Database.ExecuteSqlRawAsync(
"DELETE FROM authority.tokens WHERE expires_at < NOW() - INTERVAL '7 days'",
[],
cancellationToken).ConfigureAwait(false);
}
@@ -251,9 +252,7 @@ public sealed class RefreshTokenRepository : IRefreshTokenRepository
UPDATE authority.refresh_tokens SET revoked_at = NOW(), revoked_by = {0}, replaced_by = {1}
WHERE tenant_id = {2} AND id = {3} AND revoked_at IS NULL
""",
revokedBy,
(object?)replacedBy ?? DBNull.Value,
tenantId, id,
[revokedBy, (object?)replacedBy ?? DBNull.Value, tenantId, id],
cancellationToken).ConfigureAwait(false);
}
@@ -267,7 +266,7 @@ public sealed class RefreshTokenRepository : IRefreshTokenRepository
UPDATE authority.refresh_tokens SET revoked_at = NOW(), revoked_by = {0}
WHERE tenant_id = {1} AND user_id = {2} AND revoked_at IS NULL
""",
revokedBy, tenantId, userId,
[revokedBy, tenantId, userId],
cancellationToken).ConfigureAwait(false);
}
@@ -278,6 +277,7 @@ public sealed class RefreshTokenRepository : IRefreshTokenRepository
await dbContext.Database.ExecuteSqlRawAsync(
"DELETE FROM authority.refresh_tokens WHERE expires_at < NOW() - INTERVAL '30 days'",
[],
cancellationToken).ConfigureAwait(false);
}

View File

@@ -191,7 +191,7 @@ public sealed class UserRepository : IUserRepository
SET password_hash = {0}, password_salt = {1}, password_changed_at = NOW()
WHERE tenant_id = {2} AND id = {3}
""",
passwordHash, passwordSalt, tenantId, userId,
[passwordHash, passwordSalt, tenantId, userId],
cancellationToken).ConfigureAwait(false);
return rows > 0;
@@ -238,7 +238,7 @@ public sealed class UserRepository : IUserRepository
SET failed_login_attempts = 0, locked_until = NULL, last_login_at = NOW()
WHERE tenant_id = {0} AND id = {1}
""",
tenantId, userId,
[tenantId, userId],
cancellationToken).ConfigureAwait(false);
}

View File

@@ -4,6 +4,7 @@ using StellaOps.Authority.Persistence.EfCore.Models;
using System.Collections.Immutable;
using System.Text.Json;
using System.Text.Json.Serialization;
using static StellaOps.Localization.T;
namespace StellaOps.Authority.Persistence.Postgres;
@@ -61,14 +62,17 @@ public sealed class PostgresVerdictManifestStore : IVerdictManifestStore
signature_base64 = EXCLUDED.signature_base64,
rekor_log_id = EXCLUDED.rekor_log_id
""",
manifest.ManifestId, manifest.Tenant, manifest.AssetDigest, manifest.VulnerabilityId,
JsonSerializer.Serialize(manifest.Inputs, s_jsonOptions),
StatusToString(manifest.Result.Status),
manifest.Result.Confidence,
JsonSerializer.Serialize(manifest.Result, s_jsonOptions),
manifest.PolicyHash, manifest.LatticeVersion, manifest.EvaluatedAt, manifest.ManifestDigest,
(object?)manifest.SignatureBase64 ?? DBNull.Value,
(object?)manifest.RekorLogId ?? DBNull.Value,
new object[]
{
manifest.ManifestId, manifest.Tenant, manifest.AssetDigest, manifest.VulnerabilityId,
JsonSerializer.Serialize(manifest.Inputs, s_jsonOptions),
StatusToString(manifest.Result.Status),
manifest.Result.Confidence,
JsonSerializer.Serialize(manifest.Result, s_jsonOptions),
manifest.PolicyHash, manifest.LatticeVersion, manifest.EvaluatedAt, manifest.ManifestDigest,
(object?)manifest.SignatureBase64 ?? DBNull.Value,
(object?)manifest.RekorLogId ?? DBNull.Value,
},
ct).ConfigureAwait(false);
return manifest;
@@ -226,9 +230,9 @@ public sealed class PostgresVerdictManifestStore : IVerdictManifestStore
private static VerdictManifest ToManifest(VerdictManifestEfEntity ef)
{
var inputs = JsonSerializer.Deserialize<VerdictInputs>(ef.InputsJson, s_jsonOptions)
?? throw new InvalidOperationException("Failed to deserialize inputs");
?? throw new InvalidOperationException(_t("auth.persistence.deserialize_inputs_failed"));
var result = JsonSerializer.Deserialize<VerdictResult>(ef.ResultJson, s_jsonOptions)
?? throw new InvalidOperationException("Failed to deserialize result");
?? throw new InvalidOperationException(_t("auth.persistence.deserialize_result_failed"));
return new VerdictManifest
{

View File

@@ -35,6 +35,7 @@
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.EfCore\StellaOps.Infrastructure.EfCore.csproj" />
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Determinism.Abstractions\StellaOps.Determinism.Abstractions.csproj" />
<ProjectReference Include="..\StellaOps.Authority.Core\StellaOps.Authority.Core.csproj" />
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Localization\StellaOps.Localization.csproj" />
</ItemGroup>
</Project>