consolidation of some of the modules, localization fixes, product advisories work, qa work
This commit is contained in:
@@ -7,7 +7,7 @@ using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Platform.Analytics.Models;
|
||||
|
||||
public sealed record OrchestratorEventEnvelope
|
||||
public sealed record JobEngineEventEnvelope
|
||||
{
|
||||
[JsonPropertyName("eventId")]
|
||||
public Guid EventId { get; init; }
|
||||
@@ -40,13 +40,13 @@ public sealed record OrchestratorEventEnvelope
|
||||
public string? TraceId { get; init; }
|
||||
|
||||
[JsonPropertyName("scope")]
|
||||
public OrchestratorEventScope? Scope { get; init; }
|
||||
public JobEngineEventScope? Scope { get; init; }
|
||||
|
||||
[JsonPropertyName("payload")]
|
||||
public JsonElement? Payload { get; init; }
|
||||
}
|
||||
|
||||
public sealed record OrchestratorEventScope
|
||||
public sealed record JobEngineEventScope
|
||||
{
|
||||
[JsonPropertyName("namespace")]
|
||||
public string? Namespace { get; init; }
|
||||
@@ -157,7 +157,7 @@ public sealed record ScanCompletedEventPayload
|
||||
public ReportReadyEventPayload? ReportReady { get; init; }
|
||||
}
|
||||
|
||||
public static class OrchestratorEventKinds
|
||||
public static class JobEngineEventKinds
|
||||
{
|
||||
public const string ScannerReportReady = "scanner.event.report.ready";
|
||||
public const string ScannerScanCompleted = "scanner.scan.completed";
|
||||
@@ -30,7 +30,7 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
private readonly IParsedSbomParser _sbomParser;
|
||||
private readonly IVulnerabilityCorrelationService? _correlationService;
|
||||
private readonly ILogger<AnalyticsIngestionService> _logger;
|
||||
private readonly IEventStream<OrchestratorEventEnvelope>? _eventStream;
|
||||
private readonly IEventStream<JobEngineEventEnvelope>? _eventStream;
|
||||
private readonly string? _scannerCheckpointFilePath;
|
||||
private readonly SemaphoreSlim _scannerCheckpointLock = new(1, 1);
|
||||
private readonly JsonSerializerOptions _jsonOptions = new()
|
||||
@@ -58,7 +58,7 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
|
||||
if (eventStreamFactory is not null && !string.IsNullOrWhiteSpace(_options.Streams.ScannerStream))
|
||||
{
|
||||
_eventStream = eventStreamFactory.Create<OrchestratorEventEnvelope>(new EventStreamOptions
|
||||
_eventStream = eventStreamFactory.Create<JobEngineEventEnvelope>(new EventStreamOptions
|
||||
{
|
||||
StreamName = _options.Streams.ScannerStream
|
||||
});
|
||||
@@ -105,7 +105,7 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleEventAsync(OrchestratorEventEnvelope envelope, CancellationToken cancellationToken)
|
||||
private async Task HandleEventAsync(JobEngineEventEnvelope envelope, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!IsSupportedScannerEventKind(envelope.Kind))
|
||||
{
|
||||
@@ -151,12 +151,12 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
|
||||
internal static bool IsSupportedScannerEventKind(string? eventKind)
|
||||
{
|
||||
return string.Equals(eventKind, OrchestratorEventKinds.ScannerReportReady, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(eventKind, OrchestratorEventKinds.ScannerScanCompleted, StringComparison.OrdinalIgnoreCase);
|
||||
return string.Equals(eventKind, JobEngineEventKinds.ScannerReportReady, StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(eventKind, JobEngineEventKinds.ScannerScanCompleted, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
internal static bool TryResolveScannerPayload(
|
||||
OrchestratorEventEnvelope envelope,
|
||||
JobEngineEventEnvelope envelope,
|
||||
JsonSerializerOptions serializerOptions,
|
||||
out ReportReadyEventPayload payload,
|
||||
out string? error)
|
||||
@@ -194,7 +194,7 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!string.Equals(eventKind, OrchestratorEventKinds.ScannerScanCompleted, StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.Equals(eventKind, JobEngineEventKinds.ScannerScanCompleted, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -506,7 +506,7 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
}
|
||||
|
||||
private async Task IngestSbomAsync(
|
||||
OrchestratorEventEnvelope envelope,
|
||||
JobEngineEventEnvelope envelope,
|
||||
ReportReadyEventPayload payload,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -767,7 +767,7 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
: $"sha256:{trimmed.ToLowerInvariant()}";
|
||||
}
|
||||
|
||||
internal static string ResolveArtifactName(OrchestratorEventEnvelope envelope)
|
||||
internal static string ResolveArtifactName(JobEngineEventEnvelope envelope)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(envelope.Scope?.Repo))
|
||||
{
|
||||
@@ -777,7 +777,7 @@ public sealed class AnalyticsIngestionService : BackgroundService
|
||||
return envelope.Scope?.Image ?? envelope.Scope?.Component ?? "unknown";
|
||||
}
|
||||
|
||||
internal static string? ResolveArtifactVersion(OrchestratorEventEnvelope envelope)
|
||||
internal static string? ResolveArtifactVersion(JobEngineEventEnvelope envelope)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(envelope.Scope?.Image))
|
||||
{
|
||||
|
||||
@@ -458,6 +458,90 @@ public sealed record AdvisoryWeightsDto
|
||||
public double PatchProof { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Canonical response for score explanation.
|
||||
/// </summary>
|
||||
public sealed record ScoreExplainResponse
|
||||
{
|
||||
[JsonPropertyName("contract_version")]
|
||||
public required string ContractVersion { get; init; }
|
||||
|
||||
[JsonPropertyName("digest")]
|
||||
public required string Digest { get; init; }
|
||||
|
||||
[JsonPropertyName("score_id")]
|
||||
public required string ScoreId { get; init; }
|
||||
|
||||
[JsonPropertyName("final_score")]
|
||||
public required int FinalScore { get; init; }
|
||||
|
||||
[JsonPropertyName("bucket")]
|
||||
public required string Bucket { get; init; }
|
||||
|
||||
[JsonPropertyName("computed_at")]
|
||||
public required DateTimeOffset ComputedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("deterministic_input_hash")]
|
||||
public required string DeterministicInputHash { get; init; }
|
||||
|
||||
[JsonPropertyName("replay_link")]
|
||||
public required string ReplayLink { get; init; }
|
||||
|
||||
[JsonPropertyName("factors")]
|
||||
public required IReadOnlyList<ScoreExplainFactor> Factors { get; init; }
|
||||
|
||||
[JsonPropertyName("sources")]
|
||||
public required IReadOnlyList<ScoreExplainSource> Sources { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factor-level explanation row.
|
||||
/// </summary>
|
||||
public sealed record ScoreExplainFactor
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public required string Name { get; init; }
|
||||
|
||||
[JsonPropertyName("weight")]
|
||||
public required double Weight { get; init; }
|
||||
|
||||
[JsonPropertyName("value")]
|
||||
public required double Value { get; init; }
|
||||
|
||||
[JsonPropertyName("contribution")]
|
||||
public required double Contribution { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Source reference used by score explanation.
|
||||
/// </summary>
|
||||
public sealed record ScoreExplainSource
|
||||
{
|
||||
[JsonPropertyName("source_type")]
|
||||
public required string SourceType { get; init; }
|
||||
|
||||
[JsonPropertyName("source_ref")]
|
||||
public required string SourceRef { get; init; }
|
||||
|
||||
[JsonPropertyName("source_digest")]
|
||||
public required string SourceDigest { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deterministic error payload for score explanation.
|
||||
/// </summary>
|
||||
public sealed record ScoreExplainErrorResponse
|
||||
{
|
||||
[JsonPropertyName("code")]
|
||||
public required string Code { get; init; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public required string Message { get; init; }
|
||||
|
||||
[JsonPropertyName("digest")]
|
||||
public string? Digest { get; init; }
|
||||
}
|
||||
|
||||
#region TSF-011: Score Replay Models
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -70,9 +70,9 @@ public static class EnvironmentSettingsEndpoints
|
||||
Issuer = platform.Authority.Issuer,
|
||||
ClientId = env.ClientId,
|
||||
AuthorizeEndpoint = env.AuthorizeEndpoint
|
||||
?? $"{platform.Authority.Issuer}/connect/authorize",
|
||||
?? $"{platform.Authority.Issuer.TrimEnd('/')}/connect/authorize",
|
||||
TokenEndpoint = env.TokenEndpoint
|
||||
?? $"{platform.Authority.Issuer}/connect/token",
|
||||
?? $"{platform.Authority.Issuer.TrimEnd('/')}/connect/token",
|
||||
LogoutEndpoint = env.LogoutEndpoint,
|
||||
RedirectUri = env.RedirectUri,
|
||||
SilentRefreshRedirectUri = env.SilentRefreshRedirectUri,
|
||||
|
||||
@@ -31,6 +31,7 @@ public static class ScoreEndpoints
|
||||
.RequireTenant();
|
||||
|
||||
MapEvaluateEndpoints(score);
|
||||
MapExplainEndpoints(score);
|
||||
MapHistoryEndpoints(score);
|
||||
MapWeightsEndpoints(score);
|
||||
MapReplayEndpoints(score);
|
||||
@@ -162,6 +163,76 @@ public static class ScoreEndpoints
|
||||
.RequireAuthorization(PlatformPolicies.ScoreRead);
|
||||
}
|
||||
|
||||
private static void MapExplainEndpoints(IEndpointRouteBuilder score)
|
||||
{
|
||||
// GET /api/v1/score/explain/{digest} - Get deterministic score explanation
|
||||
score.MapGet("/explain/{digest}", async Task<IResult> (
|
||||
HttpContext context,
|
||||
PlatformRequestContextResolver resolver,
|
||||
IScoreEvaluationService service,
|
||||
string digest,
|
||||
CancellationToken cancellationToken) =>
|
||||
{
|
||||
if (!TryResolveContext(context, resolver, out var requestContext, out var failure))
|
||||
{
|
||||
return failure!;
|
||||
}
|
||||
|
||||
if (!TryNormalizeDigest(digest, out var normalizedDigest))
|
||||
{
|
||||
return Results.BadRequest(new ScoreExplainErrorResponse
|
||||
{
|
||||
Code = "invalid_input",
|
||||
Message = "Digest must be a non-empty hash with optional algorithm prefix.",
|
||||
Digest = digest
|
||||
});
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await service.GetExplanationAsync(
|
||||
requestContext!,
|
||||
normalizedDigest,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (result.Value is null)
|
||||
{
|
||||
return Results.NotFound(new ScoreExplainErrorResponse
|
||||
{
|
||||
Code = "not_found",
|
||||
Message = "No score explanation exists for the requested digest.",
|
||||
Digest = normalizedDigest
|
||||
});
|
||||
}
|
||||
|
||||
return Results.Ok(new PlatformItemResponse<ScoreExplainResponse>(
|
||||
requestContext!.TenantId,
|
||||
requestContext.ActorId,
|
||||
result.DataAsOf,
|
||||
result.Cached,
|
||||
result.CacheTtlSeconds,
|
||||
result.Value));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return Results.Json(new ScoreExplainErrorResponse
|
||||
{
|
||||
Code = "backend_unavailable",
|
||||
Message = "Score explanation backend is unavailable.",
|
||||
Digest = normalizedDigest
|
||||
}, statusCode: StatusCodes.Status503ServiceUnavailable);
|
||||
}
|
||||
})
|
||||
.WithName("GetScoreExplanation")
|
||||
.WithSummary("Get score explanation by digest")
|
||||
.WithDescription("Retrieves a deterministic score explanation contract for an existing score digest.")
|
||||
.Produces<PlatformItemResponse<ScoreExplainResponse>>(StatusCodes.Status200OK)
|
||||
.Produces<ScoreExplainErrorResponse>(StatusCodes.Status400BadRequest)
|
||||
.Produces<ScoreExplainErrorResponse>(StatusCodes.Status404NotFound)
|
||||
.Produces<ScoreExplainErrorResponse>(StatusCodes.Status503ServiceUnavailable)
|
||||
.RequireAuthorization(PlatformPolicies.ScoreRead);
|
||||
}
|
||||
|
||||
private static void MapWeightsEndpoints(IEndpointRouteBuilder score)
|
||||
{
|
||||
var weights = score.MapGroup("/weights").WithTags("Score Weights");
|
||||
@@ -355,4 +426,28 @@ public static class ScoreEndpoints
|
||||
failure = Results.BadRequest(new { error = error ?? "tenant_missing" });
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryNormalizeDigest(string rawDigest, out string normalizedDigest)
|
||||
{
|
||||
normalizedDigest = string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(rawDigest))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var trimmed = rawDigest.Trim();
|
||||
if (!trimmed.Contains(':', StringComparison.Ordinal))
|
||||
{
|
||||
trimmed = $"sha256:{trimmed}";
|
||||
}
|
||||
|
||||
var parts = trimmed.Split(':', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2 || string.IsNullOrWhiteSpace(parts[1]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
normalizedDigest = $"{parts[0].ToLowerInvariant()}:{parts[1].ToLowerInvariant()}";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"STELLAOPS_POLICY_ENGINE_URL": "https://policy-engine.stella-ops.local",
|
||||
"STELLAOPS_POLICY_GATEWAY_URL": "https://policy-gateway.stella-ops.local",
|
||||
"STELLAOPS_RISKENGINE_URL": "https://riskengine.stella-ops.local",
|
||||
"STELLAOPS_ORCHESTRATOR_URL": "https://orchestrator.stella-ops.local",
|
||||
"STELLAOPS_JOBENGINE_URL": "https://jobengine.stella-ops.local",
|
||||
"STELLAOPS_TASKRUNNER_URL": "https://taskrunner.stella-ops.local",
|
||||
"STELLAOPS_SCHEDULER_URL": "https://scheduler.stella-ops.local",
|
||||
"STELLAOPS_GRAPH_URL": "https://graph.stella-ops.local",
|
||||
|
||||
@@ -29,6 +29,14 @@ public interface IScoreEvaluationService
|
||||
string scoreId,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets score explanation by deterministic digest.
|
||||
/// </summary>
|
||||
Task<PlatformCacheResult<ScoreExplainResponse?>> GetExplanationAsync(
|
||||
PlatformRequestContext context,
|
||||
string digest,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Lists available weight manifests.
|
||||
/// </summary>
|
||||
|
||||
@@ -22,6 +22,11 @@ public interface IScoreHistoryStore
|
||||
/// </summary>
|
||||
Task<ScoreHistoryRecord?> GetByIdAsync(string id, string tenantId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the most recent score record by replay digest within a tenant.
|
||||
/// </summary>
|
||||
Task<ScoreHistoryRecord?> GetByReplayDigestAsync(string replayDigest, string tenantId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves score history for a given CVE (optionally filtered by purl).
|
||||
/// </summary>
|
||||
|
||||
@@ -34,6 +34,19 @@ public sealed class InMemoryScoreHistoryStore : IScoreHistoryStore
|
||||
return Task.FromResult(record);
|
||||
}
|
||||
|
||||
public Task<ScoreHistoryRecord?> GetByReplayDigestAsync(string replayDigest, string tenantId, CancellationToken ct = default)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(replayDigest);
|
||||
|
||||
var record = _records.Values
|
||||
.Where(r => r.TenantId == tenantId && string.Equals(r.ReplayDigest, replayDigest, StringComparison.Ordinal))
|
||||
.OrderByDescending(r => r.CreatedAt)
|
||||
.FirstOrDefault();
|
||||
|
||||
return Task.FromResult(record);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<ScoreHistoryRecord>> GetHistoryAsync(
|
||||
string tenantId,
|
||||
string cveId,
|
||||
|
||||
@@ -49,6 +49,17 @@ public sealed class PostgresScoreHistoryStore : IScoreHistoryStore
|
||||
LIMIT @limit
|
||||
""";
|
||||
|
||||
private const string SelectByReplayDigestSql = """
|
||||
SELECT id, tenant_id, project_id, cve_id, purl,
|
||||
score, band, weights_version, signal_snapshot,
|
||||
replay_digest, created_at
|
||||
FROM signals.score_history
|
||||
WHERE tenant_id = @tenant_id
|
||||
AND replay_digest = @replay_digest
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
""";
|
||||
|
||||
private const string SelectLatestSql = """
|
||||
SELECT id, tenant_id, project_id, cve_id, purl,
|
||||
score, band, weights_version, signal_snapshot,
|
||||
@@ -145,6 +156,25 @@ public sealed class PostgresScoreHistoryStore : IScoreHistoryStore
|
||||
return results;
|
||||
}
|
||||
|
||||
public async Task<ScoreHistoryRecord?> GetByReplayDigestAsync(string replayDigest, string tenantId, CancellationToken ct = default)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(replayDigest);
|
||||
|
||||
await using var conn = await _dataSource.OpenConnectionAsync(ct).ConfigureAwait(false);
|
||||
await using var cmd = new NpgsqlCommand(SelectByReplayDigestSql, conn);
|
||||
cmd.Parameters.AddWithValue("tenant_id", tenantId);
|
||||
cmd.Parameters.AddWithValue("replay_digest", replayDigest);
|
||||
|
||||
await using var reader = await cmd.ExecuteReaderAsync(ct).ConfigureAwait(false);
|
||||
if (await reader.ReadAsync(ct).ConfigureAwait(false))
|
||||
{
|
||||
return MapRecord(reader);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<ScoreHistoryRecord?> GetLatestAsync(
|
||||
string tenantId,
|
||||
string cveId,
|
||||
|
||||
@@ -12,6 +12,8 @@ using StellaOps.Signals.UnifiedScore;
|
||||
using StellaOps.Signals.UnifiedScore.Replay;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Platform.WebService.Services;
|
||||
|
||||
@@ -20,6 +22,18 @@ namespace StellaOps.Platform.WebService.Services;
|
||||
/// </summary>
|
||||
public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
{
|
||||
private const string ReplayPayloadType = "application/vnd.stellaops.score-replay+json";
|
||||
|
||||
private static readonly IReadOnlyList<(string Name, string SnapshotKey, double Weight)> ExplanationWeights =
|
||||
[
|
||||
("vex", "vex", 0.15),
|
||||
("epss", "epss", 0.20),
|
||||
("reachability", "reachability", 0.25),
|
||||
("runtime", "runtime", 0.20),
|
||||
("backport", "backport", 0.10),
|
||||
("sbom", "sbom", 0.10)
|
||||
];
|
||||
|
||||
private readonly IUnifiedScoreService _unifiedScoreService;
|
||||
private readonly IWeightManifestLoader _manifestLoader;
|
||||
private readonly IReplayLogBuilder _replayLogBuilder;
|
||||
@@ -71,7 +85,7 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
|
||||
var scoreId = GenerateScoreId(context, result);
|
||||
|
||||
var response = MapToResponse(scoreId, result, options);
|
||||
var response = MapToResponse(scoreId, result, signalSnapshot, options);
|
||||
|
||||
// Persist score to history store
|
||||
try
|
||||
@@ -129,6 +143,63 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
CacheTtlSeconds: 0);
|
||||
}
|
||||
|
||||
public async Task<PlatformCacheResult<ScoreExplainResponse?>> GetExplanationAsync(
|
||||
PlatformRequestContext context,
|
||||
string digest,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
_logger.LogDebug("Looking up score explanation for digest {Digest} tenant {TenantId}", digest, context.TenantId);
|
||||
|
||||
var normalizedDigest = NormalizeDigest(digest);
|
||||
var record = await _scoreHistoryStore.GetByReplayDigestAsync(normalizedDigest, context.TenantId, ct).ConfigureAwait(false);
|
||||
if (record is null)
|
||||
{
|
||||
return new PlatformCacheResult<ScoreExplainResponse?>(
|
||||
null,
|
||||
_timeProvider.GetUtcNow(),
|
||||
Cached: false,
|
||||
CacheTtlSeconds: 0);
|
||||
}
|
||||
|
||||
var factors = BuildExplainFactors(record.SignalSnapshot);
|
||||
var signalSnapshotDigest = $"sha256:{Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(record.SignalSnapshot)))}";
|
||||
var finalScore = (int)Math.Round(record.Score * 100m, MidpointRounding.AwayFromZero);
|
||||
|
||||
var response = new ScoreExplainResponse
|
||||
{
|
||||
ContractVersion = "score.explain.v1",
|
||||
Digest = normalizedDigest,
|
||||
ScoreId = record.Id,
|
||||
FinalScore = finalScore,
|
||||
Bucket = record.Band,
|
||||
ComputedAt = record.CreatedAt,
|
||||
DeterministicInputHash = normalizedDigest,
|
||||
ReplayLink = $"/api/v1/score/{Uri.EscapeDataString(record.Id)}/replay",
|
||||
Factors = factors,
|
||||
Sources =
|
||||
[
|
||||
new ScoreExplainSource
|
||||
{
|
||||
SourceType = "score_history",
|
||||
SourceRef = $"score-history:{record.Id}",
|
||||
SourceDigest = normalizedDigest
|
||||
},
|
||||
new ScoreExplainSource
|
||||
{
|
||||
SourceType = "signal_snapshot",
|
||||
SourceRef = $"score-history:{record.Id}/signal-snapshot",
|
||||
SourceDigest = signalSnapshotDigest
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return new PlatformCacheResult<ScoreExplainResponse?>(
|
||||
response,
|
||||
_timeProvider.GetUtcNow(),
|
||||
Cached: true,
|
||||
CacheTtlSeconds: 300);
|
||||
}
|
||||
|
||||
public async Task<PlatformCacheResult<IReadOnlyList<ScoreHistoryRecord>>> GetHistoryAsync(
|
||||
PlatformRequestContext context,
|
||||
string cveId,
|
||||
@@ -241,7 +312,7 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
};
|
||||
}
|
||||
|
||||
private static SignalSnapshot? BuildSignalSnapshot(ScoreEvaluateRequest request)
|
||||
private SignalSnapshot? BuildSignalSnapshot(ScoreEvaluateRequest request)
|
||||
{
|
||||
var signals = request.Signals;
|
||||
if (signals is null)
|
||||
@@ -259,7 +330,7 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
: SignalState.NotQueried(),
|
||||
Backport = signals.Backport.HasValue ? SignalState.Present() : SignalState.NotQueried(),
|
||||
Sbom = !string.IsNullOrEmpty(request.SbomRef) ? SignalState.Present() : SignalState.NotQueried(),
|
||||
SnapshotAt = DateTimeOffset.UtcNow
|
||||
SnapshotAt = _timeProvider.GetUtcNow()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -274,6 +345,7 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
private static ScoreEvaluateResponse MapToResponse(
|
||||
string scoreId,
|
||||
UnifiedScoreResult result,
|
||||
SignalSnapshot? signalSnapshot,
|
||||
ScoreEvaluateOptions options)
|
||||
{
|
||||
return new ScoreEvaluateResponse
|
||||
@@ -283,8 +355,8 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
Bucket = result.Bucket.ToString(),
|
||||
UnknownsFraction = result.UnknownsFraction,
|
||||
UnknownsBand = result.UnknownsBand?.ToString(),
|
||||
Unknowns = null, // TODO: Extract from signal snapshot
|
||||
ProofRef = null, // TODO: Generate proof bundle reference
|
||||
Unknowns = BuildUnknowns(signalSnapshot),
|
||||
ProofRef = BuildProofReference(result.EwsDigest),
|
||||
Breakdown = options.IncludeBreakdown
|
||||
? result.Breakdown.Select(d => new DimensionBreakdown
|
||||
{
|
||||
@@ -392,17 +464,38 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
var record = await _scoreHistoryStore.GetByIdAsync(scoreId, context.TenantId, ct).ConfigureAwait(false);
|
||||
if (record is not null)
|
||||
{
|
||||
var replayPayload = BuildReplayPayload(record);
|
||||
var replayPayloadJson = JsonSerializer.Serialize(replayPayload);
|
||||
var replayPayloadBytes = Encoding.UTF8.GetBytes(replayPayloadJson);
|
||||
var replayPayloadBase64 = Convert.ToBase64String(replayPayloadBytes);
|
||||
|
||||
var replayEnvelope = new ReplayEnvelopeDto
|
||||
{
|
||||
PayloadType = ReplayPayloadType,
|
||||
Payload = replayPayloadBase64,
|
||||
Signatures = []
|
||||
};
|
||||
|
||||
var replayEnvelopeJson = JsonSerializer.Serialize(replayEnvelope);
|
||||
var replayEnvelopeBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(replayEnvelopeJson));
|
||||
|
||||
var replayResponse = new ScoreReplayResponse
|
||||
{
|
||||
SignedReplayLogDsse = Convert.ToBase64String(
|
||||
Encoding.UTF8.GetBytes(record.SignalSnapshot)),
|
||||
SignedReplayLogDsse = replayEnvelopeBase64,
|
||||
RekorInclusion = null,
|
||||
CanonicalInputs = new List<CanonicalInputDto>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Name = "replay_payload",
|
||||
Sha256 = ComputeDigest(replayPayloadJson),
|
||||
SizeBytes = replayPayloadBytes.Length
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "signal_snapshot",
|
||||
Sha256 = record.ReplayDigest
|
||||
Sha256 = ComputeDigest(record.SignalSnapshot),
|
||||
SizeBytes = Encoding.UTF8.GetByteCount(record.SignalSnapshot)
|
||||
}
|
||||
},
|
||||
Transforms = new List<TransformStepDto>
|
||||
@@ -414,7 +507,7 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
}
|
||||
},
|
||||
AlgebraSteps = new List<AlgebraStepDto>(),
|
||||
FinalScore = (int)(record.Score * 100m),
|
||||
FinalScore = replayPayload.FinalScore ?? (int)Math.Round(record.Score * 100m, MidpointRounding.AwayFromZero),
|
||||
ComputedAt = record.CreatedAt
|
||||
};
|
||||
|
||||
@@ -439,9 +532,6 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
{
|
||||
_logger.LogDebug("Verifying replay for tenant {TenantId}", context.TenantId);
|
||||
|
||||
// TODO: Decode the DSSE envelope and extract the replay log
|
||||
// For now, return a placeholder verification result
|
||||
|
||||
// Build original inputs from request
|
||||
var ewsInput = new EvidenceWeightedScoreInput
|
||||
{
|
||||
@@ -463,17 +553,93 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
|
||||
var result = await _unifiedScoreService.ComputeAsync(unifiedRequest, ct).ConfigureAwait(false);
|
||||
|
||||
// Build verification response
|
||||
var differences = new List<VerificationDifferenceDto>();
|
||||
ReplayPayloadDto? replayPayload = null;
|
||||
bool? signatureValid = null;
|
||||
|
||||
if (TryParseReplayEnvelope(request.SignedReplayLogDsse, out replayPayload, out signatureValid, out var parseError))
|
||||
{
|
||||
if (parseError is not null)
|
||||
{
|
||||
differences.Add(new VerificationDifferenceDto
|
||||
{
|
||||
Field = "signed_replay_log_dsse",
|
||||
Expected = "valid_dsse_envelope",
|
||||
Actual = parseError
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
differences.Add(new VerificationDifferenceDto
|
||||
{
|
||||
Field = "signed_replay_log_dsse",
|
||||
Expected = "valid_dsse_envelope",
|
||||
Actual = parseError ?? "invalid_envelope"
|
||||
});
|
||||
}
|
||||
|
||||
var originalScore = replayPayload?.FinalScore ?? result.Score;
|
||||
var scoreMatches = originalScore == result.Score;
|
||||
if (!scoreMatches)
|
||||
{
|
||||
differences.Add(new VerificationDifferenceDto
|
||||
{
|
||||
Field = "final_score",
|
||||
Expected = originalScore.ToString(),
|
||||
Actual = result.Score.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
var replayDigest = replayPayload?.EwsDigest;
|
||||
var digestMatches = replayDigest is null
|
||||
|| string.Equals(replayDigest, NormalizeDigest(result.EwsDigest), StringComparison.Ordinal);
|
||||
if (!digestMatches)
|
||||
{
|
||||
differences.Add(new VerificationDifferenceDto
|
||||
{
|
||||
Field = "ews_digest",
|
||||
Expected = replayDigest!,
|
||||
Actual = NormalizeDigest(result.EwsDigest)
|
||||
});
|
||||
}
|
||||
|
||||
bool? rekorProofValid = null;
|
||||
if (request.VerifyRekor)
|
||||
{
|
||||
rekorProofValid = replayPayload?.RekorProofValid;
|
||||
if (replayPayload is not null && rekorProofValid is false)
|
||||
{
|
||||
differences.Add(new VerificationDifferenceDto
|
||||
{
|
||||
Field = "rekor_inclusion",
|
||||
Expected = "root_hash_and_log_index",
|
||||
Actual = "invalid_or_missing"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var verified = scoreMatches && digestMatches && differences.Count == 0;
|
||||
if (signatureValid.HasValue)
|
||||
{
|
||||
verified &= signatureValid.Value;
|
||||
}
|
||||
|
||||
if (request.VerifyRekor && rekorProofValid.HasValue)
|
||||
{
|
||||
verified &= rekorProofValid.Value;
|
||||
}
|
||||
|
||||
var response = new ScoreVerifyResponse
|
||||
{
|
||||
Verified = true, // Placeholder - needs actual DSSE verification
|
||||
Verified = verified,
|
||||
ReplayedScore = result.Score,
|
||||
OriginalScore = result.Score, // TODO: Extract from DSSE payload
|
||||
ScoreMatches = true,
|
||||
DigestMatches = true,
|
||||
SignatureValid = null, // TODO: Verify DSSE signature
|
||||
RekorProofValid = request.VerifyRekor ? null : null, // TODO: Verify Rekor proof
|
||||
Differences = null,
|
||||
OriginalScore = originalScore,
|
||||
ScoreMatches = scoreMatches,
|
||||
DigestMatches = digestMatches,
|
||||
SignatureValid = signatureValid,
|
||||
RekorProofValid = request.VerifyRekor ? rekorProofValid : null,
|
||||
Differences = differences.Count > 0 ? differences : null,
|
||||
VerifiedAt = _timeProvider.GetUtcNow()
|
||||
};
|
||||
|
||||
@@ -485,4 +651,386 @@ public sealed class ScoreEvaluationService : IScoreEvaluationService
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static string NormalizeDigest(string digest)
|
||||
{
|
||||
var trimmed = digest.Trim();
|
||||
if (!trimmed.Contains(':', StringComparison.Ordinal))
|
||||
{
|
||||
trimmed = $"sha256:{trimmed}";
|
||||
}
|
||||
|
||||
var parts = trimmed.Split(':', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
return trimmed.ToLowerInvariant();
|
||||
}
|
||||
|
||||
return $"{parts[0].ToLowerInvariant()}:{parts[1].ToLowerInvariant()}";
|
||||
}
|
||||
|
||||
private static IReadOnlyList<ScoreExplainFactor> BuildExplainFactors(string signalSnapshotJson)
|
||||
{
|
||||
JsonElement snapshotRoot = default;
|
||||
var hasSnapshot = false;
|
||||
|
||||
try
|
||||
{
|
||||
using var snapshot = JsonDocument.Parse(signalSnapshotJson);
|
||||
snapshotRoot = snapshot.RootElement.Clone();
|
||||
hasSnapshot = true;
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
hasSnapshot = false;
|
||||
}
|
||||
|
||||
var factors = new List<ScoreExplainFactor>(ExplanationWeights.Count);
|
||||
foreach (var (name, snapshotKey, weight) in ExplanationWeights)
|
||||
{
|
||||
var value = hasSnapshot ? ReadSignalStateValue(snapshotRoot, snapshotKey) : 0.0;
|
||||
factors.Add(new ScoreExplainFactor
|
||||
{
|
||||
Name = name,
|
||||
Weight = weight,
|
||||
Value = value,
|
||||
Contribution = Math.Round(weight * value, 6, MidpointRounding.AwayFromZero)
|
||||
});
|
||||
}
|
||||
|
||||
return factors;
|
||||
}
|
||||
|
||||
private static double ReadSignalStateValue(JsonElement snapshotRoot, string signalKey)
|
||||
{
|
||||
if (!TryGetPropertyIgnoreCase(snapshotRoot, signalKey, out var state))
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (state.ValueKind == JsonValueKind.True)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (state.ValueKind == JsonValueKind.False)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (state.ValueKind == JsonValueKind.Number && state.TryGetDouble(out var number))
|
||||
{
|
||||
return Math.Clamp(number, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (state.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (TryGetPropertyIgnoreCase(state, "isPresent", out var isPresent) && isPresent.ValueKind == JsonValueKind.True)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private static bool TryGetPropertyIgnoreCase(JsonElement element, string propertyName, out JsonElement value)
|
||||
{
|
||||
foreach (var property in element.EnumerateObject())
|
||||
{
|
||||
if (string.Equals(property.Name, propertyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
value = property.Value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<string>? BuildUnknowns(SignalSnapshot? snapshot)
|
||||
{
|
||||
if (snapshot is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var unknowns = new List<string>(6);
|
||||
AddUnknownIfMissing(unknowns, "vex", snapshot.Vex);
|
||||
AddUnknownIfMissing(unknowns, "epss", snapshot.Epss);
|
||||
AddUnknownIfMissing(unknowns, "reachability", snapshot.Reachability);
|
||||
AddUnknownIfMissing(unknowns, "runtime", snapshot.Runtime);
|
||||
AddUnknownIfMissing(unknowns, "backport", snapshot.Backport);
|
||||
AddUnknownIfMissing(unknowns, "sbom", snapshot.Sbom);
|
||||
|
||||
return unknowns.Count == 0 ? null : unknowns;
|
||||
}
|
||||
|
||||
private static void AddUnknownIfMissing(ICollection<string> unknowns, string key, SignalState state)
|
||||
{
|
||||
if (!state.IsPresent)
|
||||
{
|
||||
unknowns.Add(key);
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildProofReference(string ewsDigest)
|
||||
{
|
||||
var normalizedDigest = NormalizeDigest(ewsDigest);
|
||||
return $"proof://score/{Uri.EscapeDataString(normalizedDigest)}";
|
||||
}
|
||||
|
||||
private static ReplayPayloadDto BuildReplayPayload(ScoreHistoryRecord record)
|
||||
{
|
||||
var normalizedDigest = NormalizeDigest(record.ReplayDigest);
|
||||
return new ReplayPayloadDto
|
||||
{
|
||||
ScoreId = record.Id,
|
||||
FinalScore = (int)Math.Round(record.Score * 100m, MidpointRounding.AwayFromZero),
|
||||
EwsDigest = normalizedDigest,
|
||||
WeightManifestVersion = record.WeightsVersion,
|
||||
SignalSnapshotSha256 = ComputeDigest(record.SignalSnapshot),
|
||||
ComputedAt = record.CreatedAt,
|
||||
RekorProofValid = null
|
||||
};
|
||||
}
|
||||
|
||||
private static string ComputeDigest(string data)
|
||||
{
|
||||
var hash = SHA256.HashData(Encoding.UTF8.GetBytes(data));
|
||||
return $"sha256:{Convert.ToHexStringLower(hash)}";
|
||||
}
|
||||
|
||||
private static bool TryParseReplayEnvelope(
|
||||
string signedReplayLogDsse,
|
||||
out ReplayPayloadDto? replayPayload,
|
||||
out bool? signatureValid,
|
||||
out string? parseError)
|
||||
{
|
||||
replayPayload = null;
|
||||
signatureValid = null;
|
||||
parseError = null;
|
||||
|
||||
if (!TryDecodeBase64Utf8(signedReplayLogDsse, out var envelopeJson))
|
||||
{
|
||||
parseError = "envelope_not_base64_utf8";
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonDocument envelope;
|
||||
try
|
||||
{
|
||||
envelope = JsonDocument.Parse(envelopeJson);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
parseError = "envelope_not_json";
|
||||
return false;
|
||||
}
|
||||
|
||||
using (envelope)
|
||||
{
|
||||
var root = envelope.RootElement;
|
||||
if (root.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
parseError = "envelope_root_not_object";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TryGetPropertyIgnoreCase(root, "signatures", out var signaturesElement)
|
||||
&& signaturesElement.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
var signatureCount = signaturesElement.GetArrayLength();
|
||||
if (signatureCount > 0)
|
||||
{
|
||||
signatureValid = signaturesElement.EnumerateArray().All(static signature =>
|
||||
signature.ValueKind == JsonValueKind.Object
|
||||
&& TryGetPropertyIgnoreCase(signature, "sig", out var sig)
|
||||
&& sig.ValueKind == JsonValueKind.String
|
||||
&& !string.IsNullOrWhiteSpace(sig.GetString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryGetPropertyIgnoreCase(root, "payload", out var payloadElement)
|
||||
|| payloadElement.ValueKind != JsonValueKind.String)
|
||||
{
|
||||
parseError = "payload_missing";
|
||||
return false;
|
||||
}
|
||||
|
||||
var payloadBase64 = payloadElement.GetString();
|
||||
if (string.IsNullOrWhiteSpace(payloadBase64))
|
||||
{
|
||||
parseError = "payload_empty";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryDecodeBase64Utf8(payloadBase64, out var payloadJson))
|
||||
{
|
||||
parseError = "payload_not_base64_utf8";
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonDocument payloadDocument;
|
||||
try
|
||||
{
|
||||
payloadDocument = JsonDocument.Parse(payloadJson);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
parseError = "payload_not_json";
|
||||
return false;
|
||||
}
|
||||
|
||||
using (payloadDocument)
|
||||
{
|
||||
var payloadRoot = payloadDocument.RootElement;
|
||||
if (payloadRoot.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
parseError = "payload_root_not_object";
|
||||
return false;
|
||||
}
|
||||
|
||||
replayPayload = new ReplayPayloadDto
|
||||
{
|
||||
ScoreId = ReadOptionalString(payloadRoot, "score_id", "scoreId"),
|
||||
FinalScore = ReadOptionalInt(payloadRoot, "final_score", "finalScore"),
|
||||
EwsDigest = NormalizeOptionalDigest(payloadRoot, "ews_digest", "ewsDigest"),
|
||||
WeightManifestVersion = ReadOptionalString(payloadRoot, "weight_manifest_version", "weightManifestVersion"),
|
||||
SignalSnapshotSha256 = ReadOptionalString(payloadRoot, "signal_snapshot_sha256", "signalSnapshotSha256"),
|
||||
ComputedAt = ReadOptionalDateTimeOffset(payloadRoot, "computed_at", "computedAt"),
|
||||
RekorProofValid = ReadRekorProofValidity(payloadRoot)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool? ReadRekorProofValidity(JsonElement payloadRoot)
|
||||
{
|
||||
if (!TryGetPropertyIgnoreCase(payloadRoot, "rekor_inclusion", out var rekorElement))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (rekorElement.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var hasRoot = TryGetPropertyIgnoreCase(rekorElement, "root_hash", out var rootHash)
|
||||
&& rootHash.ValueKind == JsonValueKind.String
|
||||
&& !string.IsNullOrWhiteSpace(rootHash.GetString());
|
||||
|
||||
var hasIndex = TryGetPropertyIgnoreCase(rekorElement, "log_index", out var logIndex)
|
||||
&& logIndex.ValueKind == JsonValueKind.Number
|
||||
&& logIndex.TryGetInt64(out _);
|
||||
|
||||
return hasRoot && hasIndex;
|
||||
}
|
||||
|
||||
private static string? ReadOptionalString(JsonElement element, string snakeCase, string camelCase)
|
||||
{
|
||||
if (TryGetPropertyIgnoreCase(element, snakeCase, out var value)
|
||||
|| TryGetPropertyIgnoreCase(element, camelCase, out value))
|
||||
{
|
||||
return value.ValueKind == JsonValueKind.String ? value.GetString() : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int? ReadOptionalInt(JsonElement element, string snakeCase, string camelCase)
|
||||
{
|
||||
if (TryGetPropertyIgnoreCase(element, snakeCase, out var value)
|
||||
|| TryGetPropertyIgnoreCase(element, camelCase, out value))
|
||||
{
|
||||
return value.ValueKind == JsonValueKind.Number && value.TryGetInt32(out var parsed)
|
||||
? parsed
|
||||
: null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DateTimeOffset? ReadOptionalDateTimeOffset(JsonElement element, string snakeCase, string camelCase)
|
||||
{
|
||||
var text = ReadOptionalString(element, snakeCase, camelCase);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return DateTimeOffset.TryParse(text, out var parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
private static string? NormalizeOptionalDigest(JsonElement element, string snakeCase, string camelCase)
|
||||
{
|
||||
var digest = ReadOptionalString(element, snakeCase, camelCase);
|
||||
return string.IsNullOrWhiteSpace(digest) ? null : NormalizeDigest(digest);
|
||||
}
|
||||
|
||||
private static bool TryDecodeBase64Utf8(string input, out string decoded)
|
||||
{
|
||||
decoded = string.Empty;
|
||||
try
|
||||
{
|
||||
var bytes = Convert.FromBase64String(input);
|
||||
decoded = Encoding.UTF8.GetString(bytes);
|
||||
return true;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed record ReplayEnvelopeDto
|
||||
{
|
||||
[JsonPropertyName("payloadType")]
|
||||
public required string PayloadType { get; init; }
|
||||
|
||||
[JsonPropertyName("payload")]
|
||||
public required string Payload { get; init; }
|
||||
|
||||
[JsonPropertyName("signatures")]
|
||||
public required IReadOnlyList<ReplayEnvelopeSignatureDto> Signatures { get; init; }
|
||||
}
|
||||
|
||||
private sealed record ReplayEnvelopeSignatureDto
|
||||
{
|
||||
[JsonPropertyName("keyid")]
|
||||
public string? KeyId { get; init; }
|
||||
|
||||
[JsonPropertyName("sig")]
|
||||
public required string Sig { get; init; }
|
||||
}
|
||||
|
||||
private sealed record ReplayPayloadDto
|
||||
{
|
||||
[JsonPropertyName("score_id")]
|
||||
public string? ScoreId { get; init; }
|
||||
|
||||
[JsonPropertyName("final_score")]
|
||||
public int? FinalScore { get; init; }
|
||||
|
||||
[JsonPropertyName("ews_digest")]
|
||||
public string? EwsDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("weight_manifest_version")]
|
||||
public string? WeightManifestVersion { get; init; }
|
||||
|
||||
[JsonPropertyName("signal_snapshot_sha256")]
|
||||
public string? SignalSnapshotSha256 { get; init; }
|
||||
|
||||
[JsonPropertyName("computed_at")]
|
||||
public DateTimeOffset? ComputedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("rekor_proof_valid")]
|
||||
public bool? RekorProofValid { get; init; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
<ProjectReference Include="..\__Libraries\StellaOps.Platform.Database\StellaOps.Platform.Database.csproj" />
|
||||
<!-- Persistence modules for demo data seeding (SeedEndpoints) -->
|
||||
<ProjectReference Include="..\..\Authority\__Libraries\StellaOps.Authority.Persistence\StellaOps.Authority.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\Scheduler\__Libraries\StellaOps.Scheduler.Persistence\StellaOps.Scheduler.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\JobEngine\StellaOps.Scheduler.__Libraries\StellaOps.Scheduler.Persistence\StellaOps.Scheduler.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\Concelier\__Libraries\StellaOps.Concelier.Persistence\StellaOps.Concelier.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\Policy\__Libraries\StellaOps.Policy.Persistence\StellaOps.Policy.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\Notify\__Libraries\StellaOps.Notify.Persistence\StellaOps.Notify.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\Excititor\__Libraries\StellaOps.Excititor.Persistence\StellaOps.Excititor.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\Concelier\__Libraries\StellaOps.Excititor.Persistence\StellaOps.Excititor.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Localization\StellaOps.Localization.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,29 +1,26 @@
|
||||
{
|
||||
"_meta": { "locale": "bg-BG", "namespace": "platform", "version": "1.0" },
|
||||
|
||||
"platform.health.status_healthy": "Vsichki sistemi rabotyat normalno.",
|
||||
"platform.health.status_degraded": "Nyakoi uslugi imat problemi.",
|
||||
"platform.health.status_unavailable": "Platformata v momenta ne e dostupna.",
|
||||
|
||||
"platform.quota.limit_exceeded": "Limitat na kvotata za {0} e nadhvurlen.",
|
||||
"platform.quota.usage_warning": "Izpolzvaneto e {0}% ot limita na kvotata.",
|
||||
"platform.quota.reset_at": "Kvotata se nulyava v {0}.",
|
||||
|
||||
"platform.onboarding.welcome": "Dobro doshli v StellaOps.",
|
||||
"platform.onboarding.step_authority": "Konfiguriraite dostavchik na identichnost.",
|
||||
"platform.onboarding.step_registry": "Svurzhete container registry.",
|
||||
"platform.onboarding.step_environments": "Definiraite tselevi sredi.",
|
||||
"platform.onboarding.step_complete": "Nastroikata e zavarshena. Gotovo za rabota.",
|
||||
|
||||
"platform.setup.required": "Predi izpolzvane na platformata e nuzhna nachalna nastroika.",
|
||||
"platform.setup.in_progress": "Nastroikata e v proces.",
|
||||
"platform.setup.complete": "Nastroikata e zavarshena.",
|
||||
|
||||
"platform.context.region_not_found": "Region {0} ne e nameren.",
|
||||
"platform.context.environment_not_found": "Sreda {0} ne e namerena.",
|
||||
|
||||
"platform.migration.started": "Migratsiyata zapochna.",
|
||||
"platform.migration.completed": "Migratsiyata priklyuchi uspeshno.",
|
||||
"platform.migration.failed": "Migratsiyata se provali: {0}."
|
||||
{
|
||||
"_meta": {
|
||||
"locale": "bg-BG",
|
||||
"namespace": "platform",
|
||||
"version": "1.0"
|
||||
},
|
||||
"platform.health.status_healthy": "Всички системи работят нормално.",
|
||||
"platform.health.status_degraded": "Някои услуги имат проблеми.",
|
||||
"platform.health.status_unavailable": "Платформата в момента не е достъпна.",
|
||||
"platform.quota.limit_exceeded": "Лимитът на квотата за {0} е надвишен.",
|
||||
"platform.quota.usage_warning": "Използването е {0}% от лимита на квотата.",
|
||||
"platform.quota.reset_at": "Квотата се нулира в {0}.",
|
||||
"platform.onboarding.welcome": "Добре дошли в StellaOps.",
|
||||
"platform.onboarding.step_authority": "Конфигурирайте доставчик на идентичност.",
|
||||
"platform.onboarding.step_registry": "Свържете контейнерния регистър.",
|
||||
"platform.onboarding.step_environments": "Дефинирайте целеви среди.",
|
||||
"platform.onboarding.step_complete": "Настройката е завършена. Готово за работа.",
|
||||
"platform.setup.required": "Преди използване на платформата е нужна начална настройка.",
|
||||
"platform.setup.in_progress": "Настройката е в процес.",
|
||||
"platform.setup.complete": "Настройката е завършена.",
|
||||
"platform.context.region_not_found": "Регион {0} не е намерен.",
|
||||
"platform.context.environment_not_found": "Среда {0} не е намерена.",
|
||||
"platform.migration.started": "Миграцията започна.",
|
||||
"platform.migration.completed": "Миграцията приключи успешно.",
|
||||
"platform.migration.failed": "Миграцията се провали: {0}."
|
||||
}
|
||||
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "bg-BG", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Loading...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Something went wrong.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"ui.actions.save": "Save",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.cancel": "Cancel",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.retry": "Retry",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Fresh auth: Active",
|
||||
"ui.auth.fresh_stale": "Fresh auth: Stale",
|
||||
"ui.locale.label": "Ezik",
|
||||
"ui.locale.en_us": "Angliiski (USA)",
|
||||
"ui.locale.de_de": "Nemski (Germania)",
|
||||
"ui.locale.bg_bg": "Balgarski (Balgaria)",
|
||||
"ui.locale.ru_ru": "Ruski (Rusia)",
|
||||
"ui.locale.es_es": "Ispanski (Ispania)",
|
||||
"ui.locale.fr_fr": "Frenski (Francia)",
|
||||
"ui.locale.zh_tw": "Kitaiski tradicionen (Taiwan)",
|
||||
"ui.locale.zh_cn": "Kitaiski oprosten (Kitai)",
|
||||
"ui.locale.uk_ua": "Ukrainian (Ukraine)",
|
||||
"ui.settings.language.title": "Ezik",
|
||||
"ui.settings.language.subtitle": "Zadadeite predpochtaniya ezik na konzolata.",
|
||||
"ui.settings.language.description": "Promenite se prilagat vednaga v UI.",
|
||||
"ui.settings.language.selector_label": "Predpochtan ezik",
|
||||
"ui.settings.language.persisted": "Zapazeno za vashiya akaunt i preizpolzvano ot CLI.",
|
||||
"ui.settings.language.persisted_error": "Zapazeno lokalno, no sinkhronizatsiyata na akaunta se provali.",
|
||||
"ui.settings.language.sign_in_hint": "Vlezte v sistema, za da sinkhronizirate tazi nastroika s CLI.",
|
||||
|
||||
"ui.first_signal.label": "First signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Waiting for first signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.failed": "Failed to load signal.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"_meta": {
|
||||
"locale": "bg-BG",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "Зареждане...",
|
||||
"ui.loading.spinner": "Моля, изчакайте...",
|
||||
"ui.loading.slow": "Това отнема повече време от очакваното...",
|
||||
"ui.error.generic": "Нещо се обърка.",
|
||||
"ui.error.network": "Мрежова грешка. Проверете връзката си.",
|
||||
"ui.error.timeout": "Времето за заявката изтече. Моля, опитайте отново.",
|
||||
"ui.error.not_found": "Заявеният ресурс не беше намерен.",
|
||||
"ui.error.unauthorized": "Нямате права да видите това.",
|
||||
"ui.error.server_error": "Грешка в сървъра. Моля, опитайте отново по-късно.",
|
||||
"ui.error.try_again": "Опитай отново",
|
||||
"ui.error.go_back": "Назад",
|
||||
"ui.offline.banner": "Офлайн сте.",
|
||||
"ui.offline.description": "Някои функции може да са недостъпни.",
|
||||
"ui.offline.reconnecting": "Повторно свързване...",
|
||||
"ui.offline.reconnected": "Отново онлайн.",
|
||||
"ui.toast.success": "Успех",
|
||||
"ui.toast.info": "Инфо",
|
||||
"ui.toast.warning": "Предупреждение",
|
||||
"ui.toast.error": "Грешка",
|
||||
"ui.toast.dismiss": "Скрий",
|
||||
"ui.toast.undo": "Отмени",
|
||||
"ui.actions.save": "Запази",
|
||||
"ui.actions.saving": "Запазване...",
|
||||
"ui.actions.saved": "Запазено",
|
||||
"ui.actions.cancel": "Отказ",
|
||||
"ui.actions.confirm": "Потвърди",
|
||||
"ui.actions.delete": "Изтрий",
|
||||
"ui.actions.deleting": "Изтриване...",
|
||||
"ui.actions.deleted": "Изтрито",
|
||||
"ui.actions.submit": "Изпрати",
|
||||
"ui.actions.submitting": "Изпращане...",
|
||||
"ui.actions.submitted": "Изпратено",
|
||||
"ui.actions.close": "Затвори",
|
||||
"ui.actions.expand": "Разгъни",
|
||||
"ui.actions.collapse": "Свий",
|
||||
"ui.actions.show_more": "Покажи още",
|
||||
"ui.actions.show_less": "Покажи по-малко",
|
||||
"ui.actions.retry": "Опитай отново",
|
||||
"ui.actions.refresh": "Опресни",
|
||||
"ui.actions.export": "Експортирай",
|
||||
"ui.actions.search": "Търси",
|
||||
"ui.actions.clear": "Изчисти",
|
||||
"ui.actions.view": "Преглед",
|
||||
"ui.actions.dismiss": "Скрий",
|
||||
"ui.actions.show": "Покажи",
|
||||
"ui.actions.hide": "Скрий",
|
||||
"ui.actions.sign_in": "Вход",
|
||||
"ui.actions.back_to_list": "Назад към списъка",
|
||||
"ui.actions.load_more": "Зареди още",
|
||||
"ui.labels.all": "Всички",
|
||||
"ui.labels.title": "Заглавие",
|
||||
"ui.labels.description": "Описание",
|
||||
"ui.labels.status": "Статус",
|
||||
"ui.labels.score": "Оценка",
|
||||
"ui.labels.severity": "Сериозност",
|
||||
"ui.labels.details": "Детайли",
|
||||
"ui.labels.actions": "Действия",
|
||||
"ui.labels.type": "Тип",
|
||||
"ui.labels.tags": "Етикети",
|
||||
"ui.labels.filters": "Филтри",
|
||||
"ui.labels.updated": "Обновено",
|
||||
"ui.labels.showing": "Показване",
|
||||
"ui.labels.of": "от",
|
||||
"ui.labels.total": "Общо",
|
||||
"ui.labels.not_applicable": "н/п",
|
||||
"ui.labels.selected": "избрани",
|
||||
"ui.labels.last_updated": "Последна актуализация:",
|
||||
"ui.labels.expires": "Изтича",
|
||||
"ui.validation.required": "Това поле е задължително.",
|
||||
"ui.validation.invalid": "Невалидна стойност.",
|
||||
"ui.validation.too_long": "Максимално позволени символи: {max}.",
|
||||
"ui.validation.too_short": "Минимално изисквани символи: {min}.",
|
||||
"ui.validation.invalid_email": "Моля, въведете валиден имейл адрес.",
|
||||
"ui.validation.invalid_url": "Моля, въведете валиден URL адрес.",
|
||||
"ui.a11y.loading": "Съдържанието се зарежда.",
|
||||
"ui.a11y.loaded": "Съдържанието е заредено.",
|
||||
"ui.a11y.error": "Възникна грешка.",
|
||||
"ui.a11y.expanded": "Разгънато",
|
||||
"ui.a11y.collapsed": "Свито",
|
||||
"ui.a11y.selected": "Избрано",
|
||||
"ui.a11y.deselected": "Изборът е отменен",
|
||||
"ui.a11y.required": "Задължително поле",
|
||||
"ui.a11y.optional": "Незадължително",
|
||||
"ui.motion.reduced": "Анимациите са ограничени.",
|
||||
"ui.motion.enabled": "Анимациите са включени.",
|
||||
"ui.auth.fresh_active": "Актуална автентикация: Активна",
|
||||
"ui.auth.fresh_stale": "Актуална автентикация: Изтекла",
|
||||
"ui.locale.label": "Език",
|
||||
"ui.locale.en_us": "Английски (САЩ)",
|
||||
"ui.locale.de_de": "Немски (Германия)",
|
||||
"ui.locale.bg_bg": "Български (България)",
|
||||
"ui.locale.ru_ru": "Руски (Русия)",
|
||||
"ui.locale.es_es": "Испански (Испания)",
|
||||
"ui.locale.fr_fr": "Френски (Франция)",
|
||||
"ui.locale.zh_tw": "Китайски традиционен (Тайван)",
|
||||
"ui.locale.zh_cn": "Китайски опростен (Китай)",
|
||||
"ui.locale.uk_ua": "Украински (Украйна)",
|
||||
"ui.settings.language.title": "Език",
|
||||
"ui.settings.language.subtitle": "Задайте предпочитания език на конзолата.",
|
||||
"ui.settings.language.description": "Промените се прилагат веднага в интерфейса.",
|
||||
"ui.settings.language.selector_label": "Предпочитан език",
|
||||
"ui.settings.language.persisted": "Запазено за вашия акаунт и използвано от CLI.",
|
||||
"ui.settings.language.persisted_error": "Запазено локално, но синхронизацията на акаунта се провали.",
|
||||
"ui.settings.language.sign_in_hint": "Влезте в системата, за да синхронизирате тази настройка с CLI.",
|
||||
"ui.first_signal.label": "Първи сигнал",
|
||||
"ui.first_signal.run_prefix": "Изпълнение:",
|
||||
"ui.first_signal.live": "На живо",
|
||||
"ui.first_signal.polling": "Опресняване",
|
||||
"ui.first_signal.range_prefix": "Диапазон",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "Изчакване на първия сигнал...",
|
||||
"ui.first_signal.not_available": "Сигналът все още не е наличен.",
|
||||
"ui.first_signal.offline": "Офлайн. Последният известен сигнал може да е остарял.",
|
||||
"ui.first_signal.failed": "Неуспешно зареждане на сигнала.",
|
||||
"ui.first_signal.retry": "Опитай отново",
|
||||
"ui.first_signal.try_again": "Опитай отново",
|
||||
"ui.first_signal.kind.queued": "На опашка",
|
||||
"ui.first_signal.kind.started": "Стартирано",
|
||||
"ui.first_signal.kind.phase": "В процес",
|
||||
"ui.first_signal.kind.blocked": "Блокирано",
|
||||
"ui.first_signal.kind.failed": "Неуспешно",
|
||||
"ui.first_signal.kind.succeeded": "Успешно",
|
||||
"ui.first_signal.kind.canceled": "Отказано",
|
||||
"ui.first_signal.kind.unavailable": "Недостъпно",
|
||||
"ui.first_signal.kind.unknown": "Неизвестно",
|
||||
"ui.first_signal.stage.resolve": "Разрешаване",
|
||||
"ui.first_signal.stage.fetch": "Извличане",
|
||||
"ui.first_signal.stage.restore": "Възстановяване",
|
||||
"ui.first_signal.stage.analyze": "Анализ",
|
||||
"ui.first_signal.stage.policy": "Оценка на политики",
|
||||
"ui.first_signal.stage.report": "Генериране на отчет",
|
||||
"ui.first_signal.stage.unknown": "Обработка",
|
||||
"ui.first_signal.aria.card_label": "Състояние на първия сигнал",
|
||||
"ui.severity.critical": "Критично",
|
||||
"ui.severity.high": "Висока",
|
||||
"ui.severity.medium": "Средна",
|
||||
"ui.severity.low": "Ниска",
|
||||
"ui.severity.info": "Инфо",
|
||||
"ui.severity.none": "Няма",
|
||||
"ui.release_orchestrator.title": "Оркестратор на издания",
|
||||
"ui.release_orchestrator.subtitle": "Преглед на пайплайна и управление на изданията",
|
||||
"ui.release_orchestrator.pipeline_runs": "Изпълнения на пайплайна",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Опресни таблото",
|
||||
"ui.risk_dashboard.eyebrow": "Шлюз · Риск",
|
||||
"ui.risk_dashboard.title": "Рискови профили",
|
||||
"ui.risk_dashboard.subtitle": "Рискова картина за тенанта с детерминистично подреждане.",
|
||||
"ui.risk_dashboard.up_to_date": "Актуално",
|
||||
"ui.risk_dashboard.last_computation": "Последно изчисление",
|
||||
"ui.risk_dashboard.search_placeholder": "Заглавието съдържа",
|
||||
"ui.risk_dashboard.evaluated": "Оценени",
|
||||
"ui.risk_dashboard.risks_suffix": "риска.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Неуспешно зареждане на рисковите профили.",
|
||||
"ui.risk_dashboard.no_risks_found": "Няма рискове за текущите филтри.",
|
||||
"ui.risk_dashboard.loading_risks": "Зареждане на рискове…",
|
||||
"ui.findings.title": "Констатации",
|
||||
"ui.findings.search_placeholder": "Търсене на констатации...",
|
||||
"ui.findings.clear_filters": "Изчисти филтрите",
|
||||
"ui.findings.bulk_triage": "Масов триаж",
|
||||
"ui.findings.export_all": "Експортирай всички констатации",
|
||||
"ui.findings.export_selected": "Експортирай избраните констатации",
|
||||
"ui.findings.select_all": "Избери всички констатации",
|
||||
"ui.findings.trust": "Доверие",
|
||||
"ui.findings.advisory": "Бюлетин",
|
||||
"ui.findings.package": "Пакет",
|
||||
"ui.findings.flags": "Флагове",
|
||||
"ui.findings.why": "Защо",
|
||||
"ui.findings.select": "Избери",
|
||||
"ui.findings.no_findings": "Няма констатации за показване.",
|
||||
"ui.findings.no_match": "Няма констатации, които съответстват на текущите филтри.",
|
||||
"ui.sources_dashboard.title": "Табло на източниците",
|
||||
"ui.sources_dashboard.verifying": "Проверка...",
|
||||
"ui.sources_dashboard.verify_24h": "Провери последните 24 ч.",
|
||||
"ui.sources_dashboard.loading_aoc": "Зареждане на AOC метрики...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Успех/Неуспех",
|
||||
"ui.sources_dashboard.pass_rate": "Процент успех",
|
||||
"ui.sources_dashboard.passed": "Успешни",
|
||||
"ui.sources_dashboard.failed": "Неуспешни",
|
||||
"ui.sources_dashboard.recent_violations": "Последни нарушения",
|
||||
"ui.sources_dashboard.no_violations": "Няма нарушения в избрания период",
|
||||
"ui.sources_dashboard.throughput_title": "Пропускателна способност на ingest",
|
||||
"ui.sources_dashboard.docs_per_min": "док./мин",
|
||||
"ui.sources_dashboard.avg_ms": "ср. ms",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"ui.sources_dashboard.queue": "опашка",
|
||||
"ui.sources_dashboard.errors": "грешки",
|
||||
"ui.sources_dashboard.verification_complete": "Проверката приключи",
|
||||
"ui.sources_dashboard.checked": "Проверени:",
|
||||
"ui.sources_dashboard.violations": "нарушение(я)",
|
||||
"ui.sources_dashboard.field": "Поле:",
|
||||
"ui.sources_dashboard.expected": "очаквано:",
|
||||
"ui.sources_dashboard.actual": "реално:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI еквивалент:",
|
||||
"ui.sources_dashboard.data_from": "Данни от",
|
||||
"ui.sources_dashboard.to": "до",
|
||||
"ui.sources_dashboard.hour_window": "часов прозорец",
|
||||
"ui.timeline.title": "Времева линия",
|
||||
"ui.timeline.event_timeline": "Времева линия на събитията",
|
||||
"ui.timeline.refresh_timeline": "Опресни времевата линия",
|
||||
"ui.timeline.loading": "Зареждане на времевата линия...",
|
||||
"ui.timeline.empty_state": "Въведете ID на корелация, за да видите времевата линия на събитията",
|
||||
"ui.timeline.critical_path": "Анализ на критичния път",
|
||||
"ui.timeline.causal_lanes": "Причинно-следствени пътеки на събития",
|
||||
"ui.timeline.load_more": "Зареди още събития",
|
||||
"ui.timeline.event_details": "Детайли за събитие",
|
||||
"ui.timeline.events": "събития",
|
||||
"ui.exception_center.title": "Център за изключения",
|
||||
"ui.exception_center.list_view": "Изглед списък",
|
||||
"ui.exception_center.kanban_view": "Канбан изглед",
|
||||
"ui.exception_center.new_exception": "+ Ново изключение",
|
||||
"ui.exception_center.search_placeholder": "Търсене на изключения...",
|
||||
"ui.exception_center.type_vulnerability": "уязвимост",
|
||||
"ui.exception_center.type_license": "лиценз",
|
||||
"ui.exception_center.type_policy": "политика",
|
||||
"ui.exception_center.type_entropy": "ентропия",
|
||||
"ui.exception_center.type_determinism": "детерминизъм",
|
||||
"ui.exception_center.expiring_soon": "Скоро изтича",
|
||||
"ui.exception_center.clear_filters": "Изчисти филтрите",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.exception_center.audit_title": "Преглед на одитния журнал",
|
||||
"ui.exception_center.no_exceptions": "Няма изключения, които съответстват на текущите филтри",
|
||||
"ui.exception_center.column_empty": "Няма изключения",
|
||||
"ui.exception_center.exceptions_suffix": "изключения",
|
||||
"ui.evidence_thread.back_to_list": "Назад към списъка",
|
||||
"ui.evidence_thread.title_default": "Нишка с доказателства",
|
||||
"ui.evidence_thread.copy_digest": "Копирай пълния дайджест",
|
||||
"ui.evidence_thread.risk_label": "Риск:",
|
||||
"ui.evidence_thread.nodes": "възли",
|
||||
"ui.evidence_thread.loading": "Зареждане на нишката с доказателства...",
|
||||
"ui.evidence_thread.graph_tab": "Граф",
|
||||
"ui.evidence_thread.timeline_tab": "Времева линия",
|
||||
"ui.evidence_thread.transcript_tab": "Транскрипт",
|
||||
"ui.evidence_thread.not_found": "Не е намерена нишка с доказателства за този артефакт.",
|
||||
"ui.vulnerability_detail.eyebrow": "Уязвимост",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.impact_first": "Водещо въздействие",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.kev_listed": "Включена",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Невключена",
|
||||
"ui.vulnerability_detail.reachability": "Достижимост",
|
||||
"ui.vulnerability_detail.blast_radius": "Обхват на въздействие",
|
||||
"ui.vulnerability_detail.assets": "активи",
|
||||
"ui.vulnerability_detail.binary_resolution": "Идентификация на бинарния файл",
|
||||
"ui.vulnerability_detail.evidence_suffix": "доказателства",
|
||||
"ui.vulnerability_detail.fingerprint_note": "Този бинарен файл е идентифициран като коригиран чрез анализ на отпечатък, а не само чрез съвпадение на версията.",
|
||||
"ui.vulnerability_detail.affected_components": "Засегнати компоненти",
|
||||
"ui.vulnerability_detail.fix": "поправка",
|
||||
"ui.vulnerability_detail.evidence_tree": "Дърво на доказателствата и връзки към цитати",
|
||||
"ui.vulnerability_detail.evidence_explorer": "преглед на доказателства",
|
||||
"ui.vulnerability_detail.references": "Препратки",
|
||||
"ui.vulnerability_detail.back_to_risk": "Назад към риска"
|
||||
}
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "de-DE", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Wird geladen...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Etwas ist schiefgelaufen.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"_meta": {
|
||||
"locale": "de-DE",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "Laden...",
|
||||
"ui.loading.spinner": "Bitte warten...",
|
||||
"ui.loading.slow": "Das dauert länger als erwartet...",
|
||||
"ui.error.generic": "Etwas ist schief gelaufen.",
|
||||
"ui.error.network": "Netzwerkfehler. Überprüfen Sie Ihre Verbindung.",
|
||||
"ui.error.timeout": "Zeitüberschreitung bei der Anfrage. Bitte versuchen Sie es erneut.",
|
||||
"ui.error.not_found": "Die angeforderte Ressource wurde nicht gefunden.",
|
||||
"ui.error.unauthorized": "Sie haben keine Berechtigung, dies anzuzeigen.",
|
||||
"ui.error.server_error": "Serverfehler. Bitte versuchen Sie es später noch einmal.",
|
||||
"ui.error.try_again": "Erneut versuchen",
|
||||
"ui.error.go_back": "Geh zurück",
|
||||
"ui.offline.banner": "Du bist offline.",
|
||||
"ui.offline.description": "Einige Funktionen sind möglicherweise nicht verfügbar.",
|
||||
"ui.offline.reconnecting": "Verbindung wird wiederhergestellt...",
|
||||
"ui.offline.reconnected": "Wieder online.",
|
||||
"ui.toast.success": "Erfolg",
|
||||
"ui.toast.info": "Information",
|
||||
"ui.toast.warning": "Warnung",
|
||||
"ui.toast.error": "Fehler",
|
||||
"ui.toast.dismiss": "Schließen",
|
||||
"ui.toast.undo": "Rückgängig machen",
|
||||
"ui.actions.save": "Speichern",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.saving": "Speichern...",
|
||||
"ui.actions.saved": "Gespeichert",
|
||||
"ui.actions.cancel": "Abbrechen",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.confirm": "Bestätigen",
|
||||
"ui.actions.delete": "Löschen",
|
||||
"ui.actions.deleting": "Löschen...",
|
||||
"ui.actions.deleted": "Gelöscht",
|
||||
"ui.actions.submit": "Senden",
|
||||
"ui.actions.submitting": "Senden...",
|
||||
"ui.actions.submitted": "Gesendet",
|
||||
"ui.actions.close": "Schließen",
|
||||
"ui.actions.expand": "Erweitern",
|
||||
"ui.actions.collapse": "Einklappen",
|
||||
"ui.actions.show_more": "Mehr anzeigen",
|
||||
"ui.actions.show_less": "Weniger anzeigen",
|
||||
"ui.actions.retry": "Erneut versuchen",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Frische Anmeldung: Aktiv",
|
||||
"ui.auth.fresh_stale": "Frische Anmeldung: Veraltet",
|
||||
"ui.actions.refresh": "Aktualisieren",
|
||||
"ui.actions.export": "Exportieren",
|
||||
"ui.actions.search": "Suchen",
|
||||
"ui.actions.clear": "Leeren",
|
||||
"ui.actions.view": "Anzeigen",
|
||||
"ui.actions.dismiss": "Schließen",
|
||||
"ui.actions.show": "Anzeigen",
|
||||
"ui.actions.hide": "Ausblenden",
|
||||
"ui.actions.sign_in": "Anmelden",
|
||||
"ui.actions.back_to_list": "Zurück zur Liste",
|
||||
"ui.actions.load_more": "Mehr laden",
|
||||
"ui.labels.all": "Alle",
|
||||
"ui.labels.title": "Titel",
|
||||
"ui.labels.description": "Beschreibung",
|
||||
"ui.labels.status": "Zustand",
|
||||
"ui.labels.score": "Punktzahl",
|
||||
"ui.labels.severity": "Schwere",
|
||||
"ui.labels.details": "Einzelheiten",
|
||||
"ui.labels.actions": "Aktionen",
|
||||
"ui.labels.type": "Typ",
|
||||
"ui.labels.tags": "Schlagworte",
|
||||
"ui.labels.filters": "Filter",
|
||||
"ui.labels.updated": "Aktualisiert",
|
||||
"ui.labels.showing": "Zeigt",
|
||||
"ui.labels.of": "von",
|
||||
"ui.labels.total": "Gesamt",
|
||||
"ui.labels.not_applicable": "n / A",
|
||||
"ui.labels.selected": "ausgewählt",
|
||||
"ui.labels.last_updated": "Letzte Aktualisierung:",
|
||||
"ui.labels.expires": "Läuft ab",
|
||||
"ui.validation.required": "Dieses Feld ist erforderlich.",
|
||||
"ui.validation.invalid": "Ungültiger Wert.",
|
||||
"ui.validation.too_long": "Maximal erlaubte {max}-Zeichen.",
|
||||
"ui.validation.too_short": "Mindestens {min} Zeichen erforderlich.",
|
||||
"ui.validation.invalid_email": "Bitte geben Sie eine gültige E-Mail-Adresse ein.",
|
||||
"ui.validation.invalid_url": "Bitte geben Sie eine gültige URL ein.",
|
||||
"ui.a11y.loading": "Der Inhalt wird geladen.",
|
||||
"ui.a11y.loaded": "Inhalt geladen.",
|
||||
"ui.a11y.error": "Es ist ein Fehler aufgetreten.",
|
||||
"ui.a11y.expanded": "Erweitert",
|
||||
"ui.a11y.collapsed": "Zusammengebrochen",
|
||||
"ui.a11y.selected": "Ausgewählt",
|
||||
"ui.a11y.deselected": "Abgewählt",
|
||||
"ui.a11y.required": "Erforderliches Feld",
|
||||
"ui.a11y.optional": "Optionales Feld",
|
||||
"ui.motion.reduced": "Animationen reduziert.",
|
||||
"ui.motion.enabled": "Animationen aktiviert.",
|
||||
"ui.auth.fresh_active": "Neue Authentifizierung: Aktiv",
|
||||
"ui.auth.fresh_stale": "Neue Authentifizierung: veraltet",
|
||||
"ui.locale.label": "Sprache",
|
||||
"ui.locale.en_us": "Englisch (USA)",
|
||||
"ui.locale.en_us": "Englisch (Vereinigte Staaten)",
|
||||
"ui.locale.de_de": "Deutsch (Deutschland)",
|
||||
"ui.locale.bg_bg": "Bulgarisch (Bulgarien)",
|
||||
"ui.locale.ru_ru": "Russisch (Russland)",
|
||||
"ui.locale.es_es": "Spanisch (Spanien)",
|
||||
"ui.locale.fr_fr": "Franzoesisch (Frankreich)",
|
||||
"ui.locale.zh_tw": "Chinesisch (Traditionell, Taiwan)",
|
||||
"ui.locale.zh_cn": "Chinesisch (Vereinfacht, China)",
|
||||
"ui.locale.uk_ua": "Ukrainian (Ukraine)",
|
||||
"ui.locale.fr_fr": "Französisch (Frankreich)",
|
||||
"ui.locale.zh_tw": "Chinesisch, traditionell (Taiwan)",
|
||||
"ui.locale.zh_cn": "Chinesisch, vereinfacht (China)",
|
||||
"ui.locale.uk_ua": "Ukrainisch (Ukraine)",
|
||||
"ui.settings.language.title": "Sprache",
|
||||
"ui.settings.language.subtitle": "Legen Sie Ihre bevorzugte Konsolensprache fest.",
|
||||
"ui.settings.language.description": "Aenderungen werden sofort in der UI angewendet.",
|
||||
"ui.settings.language.subtitle": "Legen Sie die bevorzugte Sprache der Konsole fest.",
|
||||
"ui.settings.language.description": "Änderungen werden sofort in der Benutzeroberfläche angewendet.",
|
||||
"ui.settings.language.selector_label": "Bevorzugte Sprache",
|
||||
"ui.settings.language.persisted": "Fuer Ihr Konto gespeichert und im CLI wiederverwendet.",
|
||||
"ui.settings.language.persisted_error": "Lokal gespeichert, aber Kontosynchronisierung fehlgeschlagen.",
|
||||
"ui.settings.language.sign_in_hint": "Melden Sie sich an, um diese Einstellung mit dem CLI zu synchronisieren.",
|
||||
|
||||
"ui.settings.language.persisted": "Für Ihr Konto gespeichert und von der CLI wiederverwendet.",
|
||||
"ui.settings.language.persisted_error": "Lokal gespeichert, aber die Kontosynchronisierung ist fehlgeschlagen.",
|
||||
"ui.settings.language.sign_in_hint": "Melden Sie sich an, um diese Einstellung mit der CLI zu synchronisieren.",
|
||||
"ui.first_signal.label": "Erstes Signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Warten auf erstes Signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.run_prefix": "Ausführung:",
|
||||
"ui.first_signal.live": "Echtzeit",
|
||||
"ui.first_signal.polling": "Abfrage",
|
||||
"ui.first_signal.range_prefix": "Bereich",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "Warten auf das erste Signal...",
|
||||
"ui.first_signal.not_available": "Signal noch nicht verfügbar.",
|
||||
"ui.first_signal.offline": "Offline. Das letzte bekannte Signal ist möglicherweise veraltet.",
|
||||
"ui.first_signal.failed": "Signal konnte nicht geladen werden.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"ui.first_signal.retry": "Erneut versuchen",
|
||||
"ui.first_signal.try_again": "Erneut versuchen",
|
||||
"ui.first_signal.kind.queued": "In der Warteschlange",
|
||||
"ui.first_signal.kind.started": "Begonnen",
|
||||
"ui.first_signal.kind.phase": "Im Gange",
|
||||
"ui.first_signal.kind.blocked": "Blockiert",
|
||||
"ui.first_signal.kind.failed": "Fehlgeschlagen",
|
||||
"ui.first_signal.kind.succeeded": "Erfolgreich",
|
||||
"ui.first_signal.kind.canceled": "Abgesagt",
|
||||
"ui.first_signal.kind.unavailable": "Nicht verfügbar",
|
||||
"ui.first_signal.kind.unknown": "Unbekannt",
|
||||
"ui.first_signal.stage.resolve": "Auflösen",
|
||||
"ui.first_signal.stage.fetch": "Abrufen",
|
||||
"ui.first_signal.stage.restore": "Wiederherstellen",
|
||||
"ui.first_signal.stage.analyze": "Analysieren",
|
||||
"ui.first_signal.stage.policy": "Richtlinienauswertung",
|
||||
"ui.first_signal.stage.report": "Bericht erstellen",
|
||||
"ui.first_signal.stage.unknown": "Verarbeitung",
|
||||
"ui.first_signal.aria.card_label": "Erster Signalstatus",
|
||||
"ui.severity.critical": "Kritisch",
|
||||
"ui.severity.high": "Hoch",
|
||||
"ui.severity.medium": "Mittel",
|
||||
"ui.severity.low": "Niedrig",
|
||||
"ui.severity.info": "Information",
|
||||
"ui.severity.none": "Keine",
|
||||
"ui.release_orchestrator.title": "Freigabe-JobEngine",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline-Übersicht und Freigabe-Management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipelineläufe",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Dashboard aktualisieren",
|
||||
"ui.risk_dashboard.eyebrow": "Gateway · Risiko",
|
||||
"ui.risk_dashboard.title": "Risikoprofile",
|
||||
"ui.risk_dashboard.subtitle": "Mandantenbezogene Risikolage mit deterministischer Sortierung.",
|
||||
"ui.risk_dashboard.up_to_date": "Auf dem neuesten Stand",
|
||||
"ui.risk_dashboard.last_computation": "Letzte Berechnung",
|
||||
"ui.risk_dashboard.search_placeholder": "Titel enthält",
|
||||
"ui.risk_dashboard.evaluated": "Bewertet",
|
||||
"ui.risk_dashboard.risks_suffix": "Risiken.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Risikoprofile können nicht geladen werden.",
|
||||
"ui.risk_dashboard.no_risks_found": "Für aktuelle Filter wurden keine Risiken festgestellt.",
|
||||
"ui.risk_dashboard.loading_risks": "Risiken werden geladen…",
|
||||
"ui.findings.title": "Befunde",
|
||||
"ui.findings.search_placeholder": "Befunde durchsuchen...",
|
||||
"ui.findings.clear_filters": "Filter löschen",
|
||||
"ui.findings.bulk_triage": "Massentriage",
|
||||
"ui.findings.export_all": "Alle Ergebnisse exportieren",
|
||||
"ui.findings.export_selected": "Ausgewählte Ergebnisse exportieren",
|
||||
"ui.findings.select_all": "Wählen Sie alle Ergebnisse aus",
|
||||
"ui.findings.trust": "Vertrauen",
|
||||
"ui.findings.advisory": "Hinweis",
|
||||
"ui.findings.package": "Paket",
|
||||
"ui.findings.flags": "Flaggen",
|
||||
"ui.findings.why": "Warum",
|
||||
"ui.findings.select": "Wählen",
|
||||
"ui.findings.no_findings": "Keine Ergebnisse zum Anzeigen.",
|
||||
"ui.findings.no_match": "Keine Ergebnisse entsprechen den aktuellen Filtern.",
|
||||
"ui.sources_dashboard.title": "Quellen-Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Überprüfung...",
|
||||
"ui.sources_dashboard.verify_24h": "Letzte 24 Stunden überprüfen",
|
||||
"ui.sources_dashboard.loading_aoc": "AOC-Metriken werden geladen...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC bestanden/nicht bestanden",
|
||||
"ui.sources_dashboard.pass_rate": "Erfolgsquote",
|
||||
"ui.sources_dashboard.passed": "Bestanden",
|
||||
"ui.sources_dashboard.failed": "Fehlgeschlagen",
|
||||
"ui.sources_dashboard.recent_violations": "Aktuelle Verstöße",
|
||||
"ui.sources_dashboard.no_violations": "Keine Verstöße im Zeitfenster",
|
||||
"ui.sources_dashboard.throughput_title": "Aufnahmedurchsatz",
|
||||
"ui.sources_dashboard.docs_per_min": "Dokumente/Min",
|
||||
"ui.sources_dashboard.avg_ms": "Durchschnitt ms",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"ui.sources_dashboard.queue": "Warteschlange",
|
||||
"ui.sources_dashboard.errors": "Fehler",
|
||||
"ui.sources_dashboard.verification_complete": "Verifizierung abgeschlossen",
|
||||
"ui.sources_dashboard.checked": "Geprüft:",
|
||||
"ui.sources_dashboard.violations": "Verstoß(e)",
|
||||
"ui.sources_dashboard.field": "Feld:",
|
||||
"ui.sources_dashboard.expected": "erwartet:",
|
||||
"ui.sources_dashboard.actual": "tatsächlich:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI-Äquivalent:",
|
||||
"ui.sources_dashboard.data_from": "Daten von",
|
||||
"ui.sources_dashboard.to": "Zu",
|
||||
"ui.sources_dashboard.hour_window": "h Fenster",
|
||||
"ui.timeline.title": "Zeitleiste",
|
||||
"ui.timeline.event_timeline": "Ereigniszeitleiste",
|
||||
"ui.timeline.refresh_timeline": "Zeitleiste aktualisieren",
|
||||
"ui.timeline.loading": "Zeitleiste wird geladen...",
|
||||
"ui.timeline.empty_state": "Geben Sie eine Korrelations-ID ein, um die Ereigniszeitleiste anzuzeigen",
|
||||
"ui.timeline.critical_path": "Kritische Pfadanalyse",
|
||||
"ui.timeline.causal_lanes": "Ereigniskausale Spuren",
|
||||
"ui.timeline.load_more": "Weitere Veranstaltungen laden",
|
||||
"ui.timeline.event_details": "Veranstaltungsdetails",
|
||||
"ui.timeline.events": "Ereignisse",
|
||||
"ui.exception_center.title": "Ausnahmezentrum",
|
||||
"ui.exception_center.list_view": "Listenansicht",
|
||||
"ui.exception_center.kanban_view": "Kanban-Ansicht",
|
||||
"ui.exception_center.new_exception": "+ Neue Ausnahme",
|
||||
"ui.exception_center.search_placeholder": "Ausnahmen suchen...",
|
||||
"ui.exception_center.type_vulnerability": "Schwachstelle",
|
||||
"ui.exception_center.type_license": "Lizenz",
|
||||
"ui.exception_center.type_policy": "Richtlinie",
|
||||
"ui.exception_center.type_entropy": "Entropie",
|
||||
"ui.exception_center.type_determinism": "Determinismus",
|
||||
"ui.exception_center.expiring_soon": "Läuft bald ab",
|
||||
"ui.exception_center.clear_filters": "Filter löschen",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.exception_center.audit_title": "Audit-Protokoll anzeigen",
|
||||
"ui.exception_center.no_exceptions": "Keine Ausnahmen entsprechen den aktuellen Filtern",
|
||||
"ui.exception_center.column_empty": "Keine Ausnahmen",
|
||||
"ui.exception_center.exceptions_suffix": "Ausnahmen",
|
||||
"ui.evidence_thread.back_to_list": "Zurück zur Liste",
|
||||
"ui.evidence_thread.title_default": "Beweisthread",
|
||||
"ui.evidence_thread.copy_digest": "Vollständigen Digest kopieren",
|
||||
"ui.evidence_thread.risk_label": "Risiko:",
|
||||
"ui.evidence_thread.nodes": "Knoten",
|
||||
"ui.evidence_thread.loading": "Beweisthread wird geladen...",
|
||||
"ui.evidence_thread.graph_tab": "Diagramm",
|
||||
"ui.evidence_thread.timeline_tab": "Zeitleiste",
|
||||
"ui.evidence_thread.transcript_tab": "Transkript",
|
||||
"ui.evidence_thread.not_found": "Für dieses Artefakt wurde kein Beweisthread gefunden.",
|
||||
"ui.vulnerability_detail.eyebrow": "Schwachstelle",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.impact_first": "Wirkung zuerst",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.kev_listed": "Gelistet",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Nicht aufgeführt",
|
||||
"ui.vulnerability_detail.reachability": "Erreichbarkeit",
|
||||
"ui.vulnerability_detail.blast_radius": "Explosionsradius",
|
||||
"ui.vulnerability_detail.assets": "Vermögenswerte",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binäre Auflösung",
|
||||
"ui.vulnerability_detail.evidence_suffix": "Beweis",
|
||||
"ui.vulnerability_detail.fingerprint_note": "Diese Binärdatei wurde anhand der Fingerabdruckanalyse und nicht nur anhand des Versionsabgleichs als gepatcht identifiziert.",
|
||||
"ui.vulnerability_detail.affected_components": "Betroffene Komponenten",
|
||||
"ui.vulnerability_detail.fix": "Fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidenzbaum und Zitierlinks",
|
||||
"ui.vulnerability_detail.evidence_explorer": "Beweisforscher",
|
||||
"ui.vulnerability_detail.references": "Referenzen",
|
||||
"ui.vulnerability_detail.back_to_risk": "Zurück zum Risiko"
|
||||
}
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "es-ES", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Loading...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Something went wrong.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"ui.actions.save": "Save",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.cancel": "Cancel",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.retry": "Retry",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Fresh auth: Active",
|
||||
"ui.auth.fresh_stale": "Fresh auth: Stale",
|
||||
"_meta": {
|
||||
"locale": "es-ES",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "Cargando...",
|
||||
"ui.loading.spinner": "Espere por favor...",
|
||||
"ui.loading.slow": "Esto está tardando más de lo esperado...",
|
||||
"ui.error.generic": "Algo salió mal.",
|
||||
"ui.error.network": "Error de red. Comprueba tu conexión.",
|
||||
"ui.error.timeout": "Se agotó el tiempo de espera de la solicitud. Por favor inténtalo de nuevo.",
|
||||
"ui.error.not_found": "No se encontró el recurso solicitado.",
|
||||
"ui.error.unauthorized": "No tienes permiso para ver esto.",
|
||||
"ui.error.server_error": "Error del servidor. Inténtelo de nuevo más tarde.",
|
||||
"ui.error.try_again": "Intentar de nuevo",
|
||||
"ui.error.go_back": "Volver",
|
||||
"ui.offline.banner": "Estás desconectado.",
|
||||
"ui.offline.description": "Es posible que algunas funciones no estén disponibles.",
|
||||
"ui.offline.reconnecting": "Reconectando...",
|
||||
"ui.offline.reconnected": "Conexión restablecida.",
|
||||
"ui.toast.success": "Éxito",
|
||||
"ui.toast.info": "Información",
|
||||
"ui.toast.warning": "Advertencia",
|
||||
"ui.toast.error": "Fallo",
|
||||
"ui.toast.dismiss": "Cerrar",
|
||||
"ui.toast.undo": "Deshacer",
|
||||
"ui.actions.save": "Guardar",
|
||||
"ui.actions.saving": "Guardando...",
|
||||
"ui.actions.saved": "Guardado",
|
||||
"ui.actions.cancel": "Cancelar",
|
||||
"ui.actions.confirm": "Confirmar",
|
||||
"ui.actions.delete": "Eliminar",
|
||||
"ui.actions.deleting": "Eliminando...",
|
||||
"ui.actions.deleted": "Eliminado",
|
||||
"ui.actions.submit": "Enviar",
|
||||
"ui.actions.submitting": "Enviando...",
|
||||
"ui.actions.submitted": "Enviado",
|
||||
"ui.actions.close": "Cerrar",
|
||||
"ui.actions.expand": "Expandir",
|
||||
"ui.actions.collapse": "Contraer",
|
||||
"ui.actions.show_more": "Mostrar más",
|
||||
"ui.actions.show_less": "Mostrar menos",
|
||||
"ui.actions.retry": "Reintentar",
|
||||
"ui.actions.refresh": "Actualizar",
|
||||
"ui.actions.export": "Exportar",
|
||||
"ui.actions.search": "Buscar",
|
||||
"ui.actions.clear": "Limpiar",
|
||||
"ui.actions.view": "Ver",
|
||||
"ui.actions.dismiss": "Cerrar",
|
||||
"ui.actions.show": "Mostrar",
|
||||
"ui.actions.hide": "Ocultar",
|
||||
"ui.actions.sign_in": "Iniciar sesión",
|
||||
"ui.actions.back_to_list": "Volver a la lista",
|
||||
"ui.actions.load_more": "Cargar más",
|
||||
"ui.labels.all": "Todo",
|
||||
"ui.labels.title": "Título",
|
||||
"ui.labels.description": "Descripción",
|
||||
"ui.labels.status": "Estado",
|
||||
"ui.labels.score": "Puntaje",
|
||||
"ui.labels.severity": "Gravedad",
|
||||
"ui.labels.details": "Detalles",
|
||||
"ui.labels.actions": "Comportamiento",
|
||||
"ui.labels.type": "Tipo",
|
||||
"ui.labels.tags": "Etiquetas",
|
||||
"ui.labels.filters": "Filtros",
|
||||
"ui.labels.updated": "Actualizado",
|
||||
"ui.labels.showing": "Demostración",
|
||||
"ui.labels.of": "de",
|
||||
"ui.labels.total": "Total general",
|
||||
"ui.labels.not_applicable": "n / A",
|
||||
"ui.labels.selected": "seleccionado",
|
||||
"ui.labels.last_updated": "Última actualización:",
|
||||
"ui.labels.expires": "Vence",
|
||||
"ui.validation.required": "Este campo es obligatorio.",
|
||||
"ui.validation.invalid": "Valor no válido.",
|
||||
"ui.validation.too_long": "Máximo de caracteres {max} permitidos.",
|
||||
"ui.validation.too_short": "Se requieren caracteres {min} mínimos.",
|
||||
"ui.validation.invalid_email": "Por favor, introduce una dirección de correo electrónico válida.",
|
||||
"ui.validation.invalid_url": "Por favor ingrese una URL válida.",
|
||||
"ui.a11y.loading": "El contenido se está cargando.",
|
||||
"ui.a11y.loaded": "Contenido cargado.",
|
||||
"ui.a11y.error": "Se produjo un error.",
|
||||
"ui.a11y.expanded": "Expandido",
|
||||
"ui.a11y.collapsed": "Colapsado",
|
||||
"ui.a11y.selected": "Seleccionado",
|
||||
"ui.a11y.deselected": "Deseleccionado",
|
||||
"ui.a11y.required": "Campo requerido",
|
||||
"ui.a11y.optional": "Opcional",
|
||||
"ui.motion.reduced": "Animaciones reducidas.",
|
||||
"ui.motion.enabled": "Animaciones habilitadas.",
|
||||
"ui.auth.fresh_active": "Nueva autenticación: activa",
|
||||
"ui.auth.fresh_stale": "Autenticación nueva: obsoleta",
|
||||
"ui.locale.label": "Idioma",
|
||||
"ui.locale.en_us": "Ingles (EE. UU.)",
|
||||
"ui.locale.de_de": "Aleman (Alemania)",
|
||||
"ui.locale.bg_bg": "Bulgaro (Bulgaria)",
|
||||
"ui.locale.en_us": "Inglés (Estados Unidos)",
|
||||
"ui.locale.de_de": "Alemán (Alemania)",
|
||||
"ui.locale.bg_bg": "Búlgaro (Bulgaria)",
|
||||
"ui.locale.ru_ru": "Ruso (Rusia)",
|
||||
"ui.locale.es_es": "Espanol (Espana)",
|
||||
"ui.locale.fr_fr": "Frances (Francia)",
|
||||
"ui.locale.zh_tw": "Chino tradicional (Taiwan)",
|
||||
"ui.locale.es_es": "Español (España)",
|
||||
"ui.locale.fr_fr": "Francés (Francia)",
|
||||
"ui.locale.zh_tw": "Chino tradicional (Taiwán)",
|
||||
"ui.locale.zh_cn": "Chino simplificado (China)",
|
||||
"ui.locale.uk_ua": "Ukrainian (Ukraine)",
|
||||
"ui.locale.uk_ua": "Ucraniano (Ucrania)",
|
||||
"ui.settings.language.title": "Idioma",
|
||||
"ui.settings.language.subtitle": "Define tu idioma preferido de la consola.",
|
||||
"ui.settings.language.description": "Los cambios se aplican de inmediato en la UI.",
|
||||
"ui.settings.language.subtitle": "Establece el idioma preferido de la consola.",
|
||||
"ui.settings.language.description": "Los cambios se aplican de inmediato en la interfaz.",
|
||||
"ui.settings.language.selector_label": "Idioma preferido",
|
||||
"ui.settings.language.persisted": "Guardado para tu cuenta y reutilizado por CLI.",
|
||||
"ui.settings.language.persisted_error": "Guardado localmente, pero fallo la sincronizacion de la cuenta.",
|
||||
"ui.settings.language.sign_in_hint": "Inicia sesion para sincronizar esta preferencia con CLI.",
|
||||
|
||||
"ui.first_signal.label": "First signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Waiting for first signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.failed": "Failed to load signal.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"ui.settings.language.persisted": "Guardado en tu cuenta y reutilizado por la CLI.",
|
||||
"ui.settings.language.persisted_error": "Guardado localmente, pero falló la sincronización de la cuenta.",
|
||||
"ui.settings.language.sign_in_hint": "Inicia sesión para sincronizar esta configuración con la CLI.",
|
||||
"ui.first_signal.label": "Primera señal",
|
||||
"ui.first_signal.run_prefix": "Ejecución:",
|
||||
"ui.first_signal.live": "Tiempo real",
|
||||
"ui.first_signal.polling": "Sondeo",
|
||||
"ui.first_signal.range_prefix": "Rango",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "Esperando la primera señal...",
|
||||
"ui.first_signal.not_available": "La señal aún no está disponible.",
|
||||
"ui.first_signal.offline": "Desconectado. La última señal conocida puede estar obsoleta.",
|
||||
"ui.first_signal.failed": "No se pudo cargar la señal.",
|
||||
"ui.first_signal.retry": "Reintentar",
|
||||
"ui.first_signal.try_again": "Intentar de nuevo",
|
||||
"ui.first_signal.kind.queued": "En cola",
|
||||
"ui.first_signal.kind.started": "Iniciado",
|
||||
"ui.first_signal.kind.phase": "En curso",
|
||||
"ui.first_signal.kind.blocked": "Bloqueado",
|
||||
"ui.first_signal.kind.failed": "Fallido",
|
||||
"ui.first_signal.kind.succeeded": "Completado",
|
||||
"ui.first_signal.kind.canceled": "Cancelado",
|
||||
"ui.first_signal.kind.unavailable": "Indisponible",
|
||||
"ui.first_signal.kind.unknown": "Desconocido",
|
||||
"ui.first_signal.stage.resolve": "Resolviendo",
|
||||
"ui.first_signal.stage.fetch": "Obteniendo",
|
||||
"ui.first_signal.stage.restore": "Restaurando",
|
||||
"ui.first_signal.stage.analyze": "Analizando",
|
||||
"ui.first_signal.stage.policy": "Evaluación de políticas",
|
||||
"ui.first_signal.stage.report": "Generando informe",
|
||||
"ui.first_signal.stage.unknown": "Procesando",
|
||||
"ui.first_signal.aria.card_label": "Estado de la primera señal",
|
||||
"ui.severity.critical": "Crítico",
|
||||
"ui.severity.high": "Alto",
|
||||
"ui.severity.medium": "Medio",
|
||||
"ui.severity.low": "Bajo",
|
||||
"ui.severity.info": "Información",
|
||||
"ui.severity.none": "Ninguna",
|
||||
"ui.release_orchestrator.title": "Orquestador de versiones",
|
||||
"ui.release_orchestrator.subtitle": "Descripción general de la canalización y gestión de versiones",
|
||||
"ui.release_orchestrator.pipeline_runs": "Ejecuciones de canalización",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Actualizar panel",
|
||||
"ui.risk_dashboard.eyebrow": "Puerta de enlace · Riesgo",
|
||||
"ui.risk_dashboard.title": "Perfiles de riesgo",
|
||||
"ui.risk_dashboard.subtitle": "Postura de riesgo por arrendatario con orden determinista.",
|
||||
"ui.risk_dashboard.up_to_date": "Actualizado",
|
||||
"ui.risk_dashboard.last_computation": "Último cálculo",
|
||||
"ui.risk_dashboard.search_placeholder": "El título contiene",
|
||||
"ui.risk_dashboard.evaluated": "Evaluado",
|
||||
"ui.risk_dashboard.risks_suffix": "riesgos.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "No se pueden cargar perfiles de riesgo.",
|
||||
"ui.risk_dashboard.no_risks_found": "No se encontraron riesgos para los filtros actuales.",
|
||||
"ui.risk_dashboard.loading_risks": "Cargando riesgos…",
|
||||
"ui.findings.title": "Hallazgos",
|
||||
"ui.findings.search_placeholder": "Buscar hallazgos...",
|
||||
"ui.findings.clear_filters": "Borrar filtros",
|
||||
"ui.findings.bulk_triage": "Triaje a granel",
|
||||
"ui.findings.export_all": "Exportar todos los hallazgos",
|
||||
"ui.findings.export_selected": "Exportar resultados seleccionados",
|
||||
"ui.findings.select_all": "Seleccionar todos los hallazgos",
|
||||
"ui.findings.trust": "Confianza",
|
||||
"ui.findings.advisory": "Aviso",
|
||||
"ui.findings.package": "Paquete",
|
||||
"ui.findings.flags": "Banderas",
|
||||
"ui.findings.why": "Por qué",
|
||||
"ui.findings.select": "Seleccionar",
|
||||
"ui.findings.no_findings": "No hay resultados para mostrar.",
|
||||
"ui.findings.no_match": "Ningún resultado coincide con los filtros actuales.",
|
||||
"ui.sources_dashboard.title": "Panel de fuentes",
|
||||
"ui.sources_dashboard.verifying": "Verificando...",
|
||||
"ui.sources_dashboard.verify_24h": "Verificar las últimas 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Cargando métricas de AOC...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC aprobado/rechazado",
|
||||
"ui.sources_dashboard.pass_rate": "Tasa de aprobación",
|
||||
"ui.sources_dashboard.passed": "Aprobado",
|
||||
"ui.sources_dashboard.failed": "Fallido",
|
||||
"ui.sources_dashboard.recent_violations": "Violaciones recientes",
|
||||
"ui.sources_dashboard.no_violations": "No hay violaciones en la ventana de tiempo",
|
||||
"ui.sources_dashboard.throughput_title": "Rendimiento de ingesta",
|
||||
"ui.sources_dashboard.docs_per_min": "documentos/min",
|
||||
"ui.sources_dashboard.avg_ms": "ms promedio",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"ui.sources_dashboard.queue": "cola",
|
||||
"ui.sources_dashboard.errors": "errores",
|
||||
"ui.sources_dashboard.verification_complete": "Verificación completa",
|
||||
"ui.sources_dashboard.checked": "Comprobado:",
|
||||
"ui.sources_dashboard.violations": "violaciones",
|
||||
"ui.sources_dashboard.field": "Campo:",
|
||||
"ui.sources_dashboard.expected": "esperado:",
|
||||
"ui.sources_dashboard.actual": "real:",
|
||||
"ui.sources_dashboard.cli_equivalent": "Equivalente CLI:",
|
||||
"ui.sources_dashboard.data_from": "Datos de",
|
||||
"ui.sources_dashboard.to": "a",
|
||||
"ui.sources_dashboard.hour_window": "ventana (h)",
|
||||
"ui.timeline.title": "Línea de tiempo",
|
||||
"ui.timeline.event_timeline": "Cronología del evento",
|
||||
"ui.timeline.refresh_timeline": "Actualizar línea de tiempo",
|
||||
"ui.timeline.loading": "Cargando línea de tiempo...",
|
||||
"ui.timeline.empty_state": "Ingrese un ID de correlación para ver la línea de tiempo del evento",
|
||||
"ui.timeline.critical_path": "Análisis de ruta crítica",
|
||||
"ui.timeline.causal_lanes": "Líneas causales de eventos",
|
||||
"ui.timeline.load_more": "Cargar más eventos",
|
||||
"ui.timeline.event_details": "Detalles del evento",
|
||||
"ui.timeline.events": "eventos",
|
||||
"ui.exception_center.title": "Centro de excepciones",
|
||||
"ui.exception_center.list_view": "Vista de lista",
|
||||
"ui.exception_center.kanban_view": "Vista Kanban",
|
||||
"ui.exception_center.new_exception": "+ Nueva excepción",
|
||||
"ui.exception_center.search_placeholder": "Excepciones de búsqueda...",
|
||||
"ui.exception_center.type_vulnerability": "Vulnerabilidad",
|
||||
"ui.exception_center.type_license": "Licencia",
|
||||
"ui.exception_center.type_policy": "Política",
|
||||
"ui.exception_center.type_entropy": "Entropía",
|
||||
"ui.exception_center.type_determinism": "Determinismo",
|
||||
"ui.exception_center.expiring_soon": "Expira pronto",
|
||||
"ui.exception_center.clear_filters": "Limpiar filtros",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.exception_center.audit_title": "Ver registro de auditoría",
|
||||
"ui.exception_center.no_exceptions": "Ninguna excepción coincide con los filtros actuales.",
|
||||
"ui.exception_center.column_empty": "Sin excepciones",
|
||||
"ui.exception_center.exceptions_suffix": "excepciones",
|
||||
"ui.evidence_thread.back_to_list": "volver a la lista",
|
||||
"ui.evidence_thread.title_default": "Hilo de evidencia",
|
||||
"ui.evidence_thread.copy_digest": "Copiar resumen completo",
|
||||
"ui.evidence_thread.risk_label": "Riesgo:",
|
||||
"ui.evidence_thread.nodes": "nodos",
|
||||
"ui.evidence_thread.loading": "Cargando hilo de evidencia...",
|
||||
"ui.evidence_thread.graph_tab": "Gráfico",
|
||||
"ui.evidence_thread.timeline_tab": "Línea de tiempo",
|
||||
"ui.evidence_thread.transcript_tab": "Transcripción",
|
||||
"ui.evidence_thread.not_found": "No se encontró ningún hilo de evidencia para este artefacto.",
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerabilidad",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impacto primero",
|
||||
"ui.vulnerability_detail.epss": "EPS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.kev_listed": "Listado",
|
||||
"ui.vulnerability_detail.kev_not_listed": "No listado",
|
||||
"ui.vulnerability_detail.reachability": "Accesibilidad",
|
||||
"ui.vulnerability_detail.blast_radius": "Radio de explosión",
|
||||
"ui.vulnerability_detail.assets": "activos",
|
||||
"ui.vulnerability_detail.binary_resolution": "Resolución binaria",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidencia",
|
||||
"ui.vulnerability_detail.fingerprint_note": "Este binario se identificó como parcheado mediante análisis de huellas dactilares, no solo coincidencia de versiones.",
|
||||
"ui.vulnerability_detail.affected_components": "Componentes afectados",
|
||||
"ui.vulnerability_detail.fix": "arreglar",
|
||||
"ui.vulnerability_detail.evidence_tree": "Árbol de evidencia y enlaces de citas",
|
||||
"ui.vulnerability_detail.evidence_explorer": "explorador de evidencia",
|
||||
"ui.vulnerability_detail.references": "Referencias",
|
||||
"ui.vulnerability_detail.back_to_risk": "Volver a Riesgo"
|
||||
}
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "fr-FR", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Loading...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Something went wrong.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"ui.actions.save": "Save",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.cancel": "Cancel",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.retry": "Retry",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Fresh auth: Active",
|
||||
"ui.auth.fresh_stale": "Fresh auth: Stale",
|
||||
"_meta": {
|
||||
"locale": "fr-FR",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "Chargement...",
|
||||
"ui.loading.spinner": "S'il vous plaît, attendez...",
|
||||
"ui.loading.slow": "Cela prend plus de temps que prévu...",
|
||||
"ui.error.generic": "Quelque chose s'est mal passé.",
|
||||
"ui.error.network": "Erreur réseau. Vérifiez votre connexion.",
|
||||
"ui.error.timeout": "La demande a expiré. Veuillez réessayer.",
|
||||
"ui.error.not_found": "La ressource demandée n'a pas été trouvée.",
|
||||
"ui.error.unauthorized": "Vous n'êtes pas autorisé à voir ceci.",
|
||||
"ui.error.server_error": "Erreur de serveur. Veuillez réessayer plus tard.",
|
||||
"ui.error.try_again": "Essayer à nouveau",
|
||||
"ui.error.go_back": "Retourner",
|
||||
"ui.offline.banner": "Vous êtes hors ligne.",
|
||||
"ui.offline.description": "Certaines fonctionnalités peuvent être indisponibles.",
|
||||
"ui.offline.reconnecting": "Reconnexion...",
|
||||
"ui.offline.reconnected": "De retour en ligne.",
|
||||
"ui.toast.success": "Succès",
|
||||
"ui.toast.info": "Informations",
|
||||
"ui.toast.warning": "Avertissement",
|
||||
"ui.toast.error": "Erreur",
|
||||
"ui.toast.dismiss": "Fermer",
|
||||
"ui.toast.undo": "Défaire",
|
||||
"ui.actions.save": "Enregistrer",
|
||||
"ui.actions.saving": "Enregistrement...",
|
||||
"ui.actions.saved": "Enregistré",
|
||||
"ui.actions.cancel": "Annuler",
|
||||
"ui.actions.confirm": "Confirmer",
|
||||
"ui.actions.delete": "Supprimer",
|
||||
"ui.actions.deleting": "Suppression...",
|
||||
"ui.actions.deleted": "Supprimé",
|
||||
"ui.actions.submit": "Soumettre",
|
||||
"ui.actions.submitting": "Envoi...",
|
||||
"ui.actions.submitted": "Soumis",
|
||||
"ui.actions.close": "Fermer",
|
||||
"ui.actions.expand": "Développer",
|
||||
"ui.actions.collapse": "Réduire",
|
||||
"ui.actions.show_more": "Afficher plus",
|
||||
"ui.actions.show_less": "Afficher moins",
|
||||
"ui.actions.retry": "Réessayer",
|
||||
"ui.actions.refresh": "Actualiser",
|
||||
"ui.actions.export": "Exporter",
|
||||
"ui.actions.search": "Rechercher",
|
||||
"ui.actions.clear": "Effacer",
|
||||
"ui.actions.view": "Voir",
|
||||
"ui.actions.dismiss": "Fermer",
|
||||
"ui.actions.show": "Afficher",
|
||||
"ui.actions.hide": "Masquer",
|
||||
"ui.actions.sign_in": "Se connecter",
|
||||
"ui.actions.back_to_list": "Retour à la liste",
|
||||
"ui.actions.load_more": "Charger plus",
|
||||
"ui.labels.all": "Tous",
|
||||
"ui.labels.title": "Titre",
|
||||
"ui.labels.description": "Descriptif",
|
||||
"ui.labels.status": "Statut",
|
||||
"ui.labels.score": "Note",
|
||||
"ui.labels.severity": "Gravité",
|
||||
"ui.labels.details": "Détails",
|
||||
"ui.labels.actions": "Actes",
|
||||
"ui.labels.type": "Taper",
|
||||
"ui.labels.tags": "Balises",
|
||||
"ui.labels.filters": "Filtres",
|
||||
"ui.labels.updated": "Mis à jour",
|
||||
"ui.labels.showing": "Affichage",
|
||||
"ui.labels.of": "de",
|
||||
"ui.labels.total": "Total général",
|
||||
"ui.labels.not_applicable": "n / A",
|
||||
"ui.labels.selected": "choisi",
|
||||
"ui.labels.last_updated": "Dernière mise à jour :",
|
||||
"ui.labels.expires": "Expire",
|
||||
"ui.validation.required": "Ce champ est obligatoire.",
|
||||
"ui.validation.invalid": "Valeur invalide.",
|
||||
"ui.validation.too_long": "Nombre maximum de caractères {max} autorisés.",
|
||||
"ui.validation.too_short": "Caractères {min} minimum requis.",
|
||||
"ui.validation.invalid_email": "S'il vous plaît, mettez une adresse email valide.",
|
||||
"ui.validation.invalid_url": "Veuillez saisir une URL valide.",
|
||||
"ui.a11y.loading": "Le contenu est en cours de chargement.",
|
||||
"ui.a11y.loaded": "Contenu chargé.",
|
||||
"ui.a11y.error": "Une erreur s'est produite.",
|
||||
"ui.a11y.expanded": "Étendu",
|
||||
"ui.a11y.collapsed": "Effondré",
|
||||
"ui.a11y.selected": "Choisi",
|
||||
"ui.a11y.deselected": "Désélectionné",
|
||||
"ui.a11y.required": "Champ obligatoire",
|
||||
"ui.a11y.optional": "Facultatif",
|
||||
"ui.motion.reduced": "Animations réduites.",
|
||||
"ui.motion.enabled": "Animations activées.",
|
||||
"ui.auth.fresh_active": "Nouvelle authentification : active",
|
||||
"ui.auth.fresh_stale": "Nouvelle authentification : obsolète",
|
||||
"ui.locale.label": "Langue",
|
||||
"ui.locale.en_us": "Anglais (Etats-Unis)",
|
||||
"ui.locale.en_us": "Anglais (États-Unis)",
|
||||
"ui.locale.de_de": "Allemand (Allemagne)",
|
||||
"ui.locale.bg_bg": "Bulgare (Bulgarie)",
|
||||
"ui.locale.ru_ru": "Russe (Russie)",
|
||||
"ui.locale.es_es": "Espagnol (Espagne)",
|
||||
"ui.locale.fr_fr": "Francais (France)",
|
||||
"ui.locale.zh_tw": "Chinois traditionnel (Taiwan)",
|
||||
"ui.locale.zh_cn": "Chinois simplifie (Chine)",
|
||||
"ui.locale.uk_ua": "Ukrainian (Ukraine)",
|
||||
"ui.locale.fr_fr": "Français (France)",
|
||||
"ui.locale.zh_tw": "Chinois traditionnel (Taïwan)",
|
||||
"ui.locale.zh_cn": "Chinois simplifié (Chine)",
|
||||
"ui.locale.uk_ua": "Ukrainien (Ukraine)",
|
||||
"ui.settings.language.title": "Langue",
|
||||
"ui.settings.language.subtitle": "Definissez votre langue de console preferee.",
|
||||
"ui.settings.language.description": "Les changements sont appliques immediatement dans l UI.",
|
||||
"ui.settings.language.selector_label": "Langue preferee",
|
||||
"ui.settings.language.persisted": "Enregistre pour votre compte et reutilise par le CLI.",
|
||||
"ui.settings.language.persisted_error": "Enregistre localement, mais la synchronisation du compte a echoue.",
|
||||
"ui.settings.language.sign_in_hint": "Connectez-vous pour synchroniser cette preference avec le CLI.",
|
||||
|
||||
"ui.first_signal.label": "First signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Waiting for first signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.failed": "Failed to load signal.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"ui.settings.language.subtitle": "Définissez la langue préférée de la console.",
|
||||
"ui.settings.language.description": "Les changements s'appliquent immédiatement dans l'interface.",
|
||||
"ui.settings.language.selector_label": "Langue préférée",
|
||||
"ui.settings.language.persisted": "Enregistré pour votre compte et réutilisé par la CLI.",
|
||||
"ui.settings.language.persisted_error": "Enregistré localement, mais la synchronisation du compte a échoué.",
|
||||
"ui.settings.language.sign_in_hint": "Connectez-vous pour synchroniser ce paramètre avec la CLI.",
|
||||
"ui.first_signal.label": "Premier signal",
|
||||
"ui.first_signal.run_prefix": "Exécution :",
|
||||
"ui.first_signal.live": "En direct",
|
||||
"ui.first_signal.polling": "Sondage",
|
||||
"ui.first_signal.range_prefix": "Plage",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "En attendant le premier signal…",
|
||||
"ui.first_signal.not_available": "Signal pas encore disponible.",
|
||||
"ui.first_signal.offline": "Hors ligne. Le dernier signal connu est peut-être périmé.",
|
||||
"ui.first_signal.failed": "Échec du chargement du signal.",
|
||||
"ui.first_signal.retry": "Réessayer",
|
||||
"ui.first_signal.try_again": "Essayer à nouveau",
|
||||
"ui.first_signal.kind.queued": "En file d'attente",
|
||||
"ui.first_signal.kind.started": "Démarré",
|
||||
"ui.first_signal.kind.phase": "En cours",
|
||||
"ui.first_signal.kind.blocked": "Bloqué",
|
||||
"ui.first_signal.kind.failed": "Échoué",
|
||||
"ui.first_signal.kind.succeeded": "Réussi",
|
||||
"ui.first_signal.kind.canceled": "Annulé",
|
||||
"ui.first_signal.kind.unavailable": "Indisponible",
|
||||
"ui.first_signal.kind.unknown": "Signal inconnu",
|
||||
"ui.first_signal.stage.resolve": "Résolution",
|
||||
"ui.first_signal.stage.fetch": "Récupération",
|
||||
"ui.first_signal.stage.restore": "Restauration",
|
||||
"ui.first_signal.stage.analyze": "Analyser",
|
||||
"ui.first_signal.stage.policy": "Évaluation des politiques",
|
||||
"ui.first_signal.stage.report": "Génération du rapport",
|
||||
"ui.first_signal.stage.unknown": "Traitement",
|
||||
"ui.first_signal.aria.card_label": "État du premier signal",
|
||||
"ui.severity.critical": "Critique",
|
||||
"ui.severity.high": "Haut",
|
||||
"ui.severity.medium": "Moyen",
|
||||
"ui.severity.low": "Faible",
|
||||
"ui.severity.info": "Informations",
|
||||
"ui.severity.none": "Aucune",
|
||||
"ui.release_orchestrator.title": "Orchestrateur de versions",
|
||||
"ui.release_orchestrator.subtitle": "Présentation du pipeline et gestion des versions",
|
||||
"ui.release_orchestrator.pipeline_runs": "Exécutions de pipelines",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Actualiser le tableau de bord",
|
||||
"ui.risk_dashboard.eyebrow": "Passerelle · Risque",
|
||||
"ui.risk_dashboard.title": "Profils de risque",
|
||||
"ui.risk_dashboard.subtitle": "Posture de risque par locataire avec tri déterministe.",
|
||||
"ui.risk_dashboard.up_to_date": "À jour",
|
||||
"ui.risk_dashboard.last_computation": "Dernier calcul",
|
||||
"ui.risk_dashboard.search_placeholder": "Le titre contient",
|
||||
"ui.risk_dashboard.evaluated": "Évalué",
|
||||
"ui.risk_dashboard.risks_suffix": "risques.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Impossible de charger les profils de risque.",
|
||||
"ui.risk_dashboard.no_risks_found": "Aucun risque trouvé pour les filtres actuels.",
|
||||
"ui.risk_dashboard.loading_risks": "Chargement des risques…",
|
||||
"ui.findings.title": "Constats",
|
||||
"ui.findings.search_placeholder": "Rechercher des constats...",
|
||||
"ui.findings.clear_filters": "Effacer les filtres",
|
||||
"ui.findings.bulk_triage": "Triage en masse",
|
||||
"ui.findings.export_all": "Exporter tous les résultats",
|
||||
"ui.findings.export_selected": "Exporter les résultats sélectionnés",
|
||||
"ui.findings.select_all": "Sélectionnez tous les résultats",
|
||||
"ui.findings.trust": "Confiance",
|
||||
"ui.findings.advisory": "Avis",
|
||||
"ui.findings.package": "Paquet",
|
||||
"ui.findings.flags": "Drapeaux",
|
||||
"ui.findings.why": "Pourquoi",
|
||||
"ui.findings.select": "Sélectionner",
|
||||
"ui.findings.no_findings": "Aucun résultat à afficher.",
|
||||
"ui.findings.no_match": "Aucun résultat ne correspond aux filtres actuels.",
|
||||
"ui.sources_dashboard.title": "Tableau de bord des sources",
|
||||
"ui.sources_dashboard.verifying": "Vérification...",
|
||||
"ui.sources_dashboard.verify_24h": "Vérifier les dernières 24 heures",
|
||||
"ui.sources_dashboard.loading_aoc": "Chargement des métriques AOC...",
|
||||
"ui.sources_dashboard.pass_fail_title": "Réussite/Échec de l'AOC",
|
||||
"ui.sources_dashboard.pass_rate": "Taux de réussite",
|
||||
"ui.sources_dashboard.passed": "Réussi",
|
||||
"ui.sources_dashboard.failed": "Échoué",
|
||||
"ui.sources_dashboard.recent_violations": "Violations récentes",
|
||||
"ui.sources_dashboard.no_violations": "Aucune violation dans la fenêtre horaire",
|
||||
"ui.sources_dashboard.throughput_title": "Débit d'ingestion",
|
||||
"ui.sources_dashboard.docs_per_min": "documents/min",
|
||||
"ui.sources_dashboard.avg_ms": "moy. ms",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"ui.sources_dashboard.queue": "file d'attente",
|
||||
"ui.sources_dashboard.errors": "erreurs",
|
||||
"ui.sources_dashboard.verification_complete": "Vérification terminée",
|
||||
"ui.sources_dashboard.checked": "Vérifié :",
|
||||
"ui.sources_dashboard.violations": "violations",
|
||||
"ui.sources_dashboard.field": "Champ:",
|
||||
"ui.sources_dashboard.expected": "attendu:",
|
||||
"ui.sources_dashboard.actual": "réel :",
|
||||
"ui.sources_dashboard.cli_equivalent": "Équivalent CLI :",
|
||||
"ui.sources_dashboard.data_from": "Données de",
|
||||
"ui.sources_dashboard.to": "à",
|
||||
"ui.sources_dashboard.hour_window": "fenêtre (h)",
|
||||
"ui.timeline.title": "Chronologie",
|
||||
"ui.timeline.event_timeline": "Chronologie de l'événement",
|
||||
"ui.timeline.refresh_timeline": "Actualiser la chronologie",
|
||||
"ui.timeline.loading": "Chargement de la chronologie...",
|
||||
"ui.timeline.empty_state": "Saisissez un ID de corrélation pour afficher la chronologie de l'événement",
|
||||
"ui.timeline.critical_path": "Analyse du chemin critique",
|
||||
"ui.timeline.causal_lanes": "Voies causales des événements",
|
||||
"ui.timeline.load_more": "Charger plus d'événements",
|
||||
"ui.timeline.event_details": "Détails de l'événement",
|
||||
"ui.timeline.events": "événements",
|
||||
"ui.exception_center.title": "Centre d'exceptions",
|
||||
"ui.exception_center.list_view": "Vue en liste",
|
||||
"ui.exception_center.kanban_view": "Vue Kanban",
|
||||
"ui.exception_center.new_exception": "+ Nouvelle exception",
|
||||
"ui.exception_center.search_placeholder": "Rechercher des exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnérabilité",
|
||||
"ui.exception_center.type_license": "licence",
|
||||
"ui.exception_center.type_policy": "politique",
|
||||
"ui.exception_center.type_entropy": "entropie",
|
||||
"ui.exception_center.type_determinism": "déterminisme",
|
||||
"ui.exception_center.expiring_soon": "Expire bientôt",
|
||||
"ui.exception_center.clear_filters": "Effacer les filtres",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.audit_title": "Afficher le journal d'audit",
|
||||
"ui.exception_center.no_exceptions": "Aucune exception ne correspond aux filtres actuels",
|
||||
"ui.exception_center.column_empty": "Aucune exception",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.evidence_thread.back_to_list": "Retour à la liste",
|
||||
"ui.evidence_thread.title_default": "Fil de preuve",
|
||||
"ui.evidence_thread.copy_digest": "Copier le résumé complet",
|
||||
"ui.evidence_thread.risk_label": "Risque:",
|
||||
"ui.evidence_thread.nodes": "nœuds",
|
||||
"ui.evidence_thread.loading": "Chargement du fil de discussion sur les preuves...",
|
||||
"ui.evidence_thread.graph_tab": "Graphique",
|
||||
"ui.evidence_thread.timeline_tab": "Chronologie",
|
||||
"ui.evidence_thread.transcript_tab": "Transcription",
|
||||
"ui.evidence_thread.not_found": "Aucun fil de preuve trouvé pour cet artefact.",
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnérabilité",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.impact_first": "L’impact d’abord",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.kev_listed": "Inscrit",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Non répertorié",
|
||||
"ui.vulnerability_detail.reachability": "Accessibilité",
|
||||
"ui.vulnerability_detail.blast_radius": "Rayon de souffle",
|
||||
"ui.vulnerability_detail.assets": "actifs",
|
||||
"ui.vulnerability_detail.binary_resolution": "Résolution binaire",
|
||||
"ui.vulnerability_detail.evidence_suffix": "preuve",
|
||||
"ui.vulnerability_detail.fingerprint_note": "Ce binaire a été identifié comme corrigé à l’aide d’une analyse d’empreintes digitales, et pas seulement d’une correspondance de version.",
|
||||
"ui.vulnerability_detail.affected_components": "Composants concernés",
|
||||
"ui.vulnerability_detail.fix": "réparer",
|
||||
"ui.vulnerability_detail.evidence_tree": "Arbre de preuves et liens vers les citations",
|
||||
"ui.vulnerability_detail.evidence_explorer": "explorateur de preuves",
|
||||
"ui.vulnerability_detail.references": "Références",
|
||||
"ui.vulnerability_detail.back_to_risk": "Retour au risque"
|
||||
}
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "ru-RU", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Loading...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Something went wrong.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"ui.actions.save": "Save",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.cancel": "Cancel",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.retry": "Retry",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Fresh auth: Active",
|
||||
"ui.auth.fresh_stale": "Fresh auth: Stale",
|
||||
"ui.locale.label": "Yazyk",
|
||||
"ui.locale.en_us": "Angliyskiy (USA)",
|
||||
"ui.locale.de_de": "Nemetskiy (Germaniya)",
|
||||
"ui.locale.bg_bg": "Bolgarskiy (Bolgariya)",
|
||||
"ui.locale.ru_ru": "Russkiy (Rossiya)",
|
||||
"ui.locale.es_es": "Ispanskiy (Ispaniya)",
|
||||
"ui.locale.fr_fr": "Frantsuzskiy (Frantsiya)",
|
||||
"ui.locale.zh_tw": "Kitayskiy tradicionnyy (Taiwan)",
|
||||
"ui.locale.zh_cn": "Kitayskiy uproshchennyy (Kitay)",
|
||||
"ui.locale.uk_ua": "Ukrainian (Ukraine)",
|
||||
"ui.settings.language.title": "Yazyk",
|
||||
"ui.settings.language.subtitle": "Vyberite predpochtitelnyy yazyk konsoli.",
|
||||
"ui.settings.language.description": "Izmeneniya primenyayutsya srazu v UI.",
|
||||
"ui.settings.language.selector_label": "Predpochtitelnyy yazyk",
|
||||
"ui.settings.language.persisted": "Sohraneno dlya vashego akkaunta i ispolzuetsya v CLI.",
|
||||
"ui.settings.language.persisted_error": "Lokalno sohraneno, no sinkhronizatsiya akkaunta ne udalas.",
|
||||
"ui.settings.language.sign_in_hint": "Vypolnite vkhod, chtoby sinkhronizirovat etu nastroiku s CLI.",
|
||||
|
||||
"ui.first_signal.label": "First signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Waiting for first signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.failed": "Failed to load signal.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"_meta": {
|
||||
"locale": "ru-RU",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "Загрузка...",
|
||||
"ui.loading.spinner": "Пожалуйста, подождите...",
|
||||
"ui.loading.slow": "Это занимает больше времени, чем ожидалось...",
|
||||
"ui.error.generic": "Что-то пошло не так.",
|
||||
"ui.error.network": "Ошибка сети. Проверьте свое соединение.",
|
||||
"ui.error.timeout": "Время запроса истекло. Пожалуйста, попробуйте еще раз.",
|
||||
"ui.error.not_found": "Запрошенный ресурс не найден.",
|
||||
"ui.error.unauthorized": "У вас нет разрешения на просмотр этого.",
|
||||
"ui.error.server_error": "Ошибка сервера. Пожалуйста, повторите попытку позже.",
|
||||
"ui.error.try_again": "Попробовать снова",
|
||||
"ui.error.go_back": "Возвращаться",
|
||||
"ui.offline.banner": "Вы не в сети.",
|
||||
"ui.offline.description": "Некоторые функции могут быть недоступны.",
|
||||
"ui.offline.reconnecting": "Повторное подключение...",
|
||||
"ui.offline.reconnected": "Снова в сети.",
|
||||
"ui.toast.success": "Успех",
|
||||
"ui.toast.info": "Информация",
|
||||
"ui.toast.warning": "Предупреждение",
|
||||
"ui.toast.error": "Ошибка",
|
||||
"ui.toast.dismiss": "Закрыть",
|
||||
"ui.toast.undo": "Отменить",
|
||||
"ui.actions.save": "Сохранить",
|
||||
"ui.actions.saving": "Сохранение...",
|
||||
"ui.actions.saved": "Сохранено",
|
||||
"ui.actions.cancel": "Отмена",
|
||||
"ui.actions.confirm": "Подтвердить",
|
||||
"ui.actions.delete": "Удалить",
|
||||
"ui.actions.deleting": "Удаление...",
|
||||
"ui.actions.deleted": "Удалено",
|
||||
"ui.actions.submit": "Отправить",
|
||||
"ui.actions.submitting": "Отправка...",
|
||||
"ui.actions.submitted": "Отправлено",
|
||||
"ui.actions.close": "Закрыть",
|
||||
"ui.actions.expand": "Развернуть",
|
||||
"ui.actions.collapse": "Свернуть",
|
||||
"ui.actions.show_more": "Показать больше",
|
||||
"ui.actions.show_less": "Показать меньше",
|
||||
"ui.actions.retry": "Повторить",
|
||||
"ui.actions.refresh": "Обновить",
|
||||
"ui.actions.export": "Экспортировать",
|
||||
"ui.actions.search": "Поиск",
|
||||
"ui.actions.clear": "Очистить",
|
||||
"ui.actions.view": "Просмотр",
|
||||
"ui.actions.dismiss": "Закрыть",
|
||||
"ui.actions.show": "Показать",
|
||||
"ui.actions.hide": "Скрыть",
|
||||
"ui.actions.sign_in": "Войти",
|
||||
"ui.actions.back_to_list": "Вернуться к списку",
|
||||
"ui.actions.load_more": "Загрузить еще",
|
||||
"ui.labels.all": "Все",
|
||||
"ui.labels.title": "Заголовок",
|
||||
"ui.labels.description": "Описание",
|
||||
"ui.labels.status": "Статус",
|
||||
"ui.labels.score": "Счет",
|
||||
"ui.labels.severity": "Серьезность",
|
||||
"ui.labels.details": "Подробности",
|
||||
"ui.labels.actions": "Действия",
|
||||
"ui.labels.type": "Тип",
|
||||
"ui.labels.tags": "Теги",
|
||||
"ui.labels.filters": "Фильтры",
|
||||
"ui.labels.updated": "Обновлено",
|
||||
"ui.labels.showing": "Показаны",
|
||||
"ui.labels.of": "из",
|
||||
"ui.labels.total": "Общий",
|
||||
"ui.labels.not_applicable": "н/д",
|
||||
"ui.labels.selected": "выбрано",
|
||||
"ui.labels.last_updated": "Последнее обновление:",
|
||||
"ui.labels.expires": "Срок действия истекает",
|
||||
"ui.validation.required": "Это поле обязательно к заполнению.",
|
||||
"ui.validation.invalid": "Недопустимое значение.",
|
||||
"ui.validation.too_long": "Разрешено максимальное количество символов {max}.",
|
||||
"ui.validation.too_short": "Требуется минимум символов {min}.",
|
||||
"ui.validation.invalid_email": "Пожалуйста, введите действительный адрес электронной почты.",
|
||||
"ui.validation.invalid_url": "Введите действительный URL-адрес.",
|
||||
"ui.a11y.loading": "Содержимое загружается.",
|
||||
"ui.a11y.loaded": "Контент загружен.",
|
||||
"ui.a11y.error": "Произошла ошибка.",
|
||||
"ui.a11y.expanded": "Расширенный",
|
||||
"ui.a11y.collapsed": "Свернутый",
|
||||
"ui.a11y.selected": "Выбрано",
|
||||
"ui.a11y.deselected": "Отменено выделение",
|
||||
"ui.a11y.required": "Обязательное поле",
|
||||
"ui.a11y.optional": "Необязательный",
|
||||
"ui.motion.reduced": "Анимации уменьшены.",
|
||||
"ui.motion.enabled": "Анимации включены.",
|
||||
"ui.auth.fresh_active": "Свежая авторизация: активна",
|
||||
"ui.auth.fresh_stale": "Свежая авторизация: устаревшая",
|
||||
"ui.locale.label": "Язык",
|
||||
"ui.locale.en_us": "Английский (США)",
|
||||
"ui.locale.de_de": "Немецкий (Германия)",
|
||||
"ui.locale.bg_bg": "Болгарский (Болгария)",
|
||||
"ui.locale.ru_ru": "Русский (Россия)",
|
||||
"ui.locale.es_es": "Испанский (Испания)",
|
||||
"ui.locale.fr_fr": "Французский (Франция)",
|
||||
"ui.locale.zh_tw": "Китайский традиционный (Тайвань)",
|
||||
"ui.locale.zh_cn": "Китайский упрощённый (Китай)",
|
||||
"ui.locale.uk_ua": "Украинский (Украина)",
|
||||
"ui.settings.language.title": "Язык",
|
||||
"ui.settings.language.subtitle": "Выберите предпочитаемый язык консоли.",
|
||||
"ui.settings.language.description": "Изменения применяются сразу в интерфейсе.",
|
||||
"ui.settings.language.selector_label": "Предпочитаемый язык",
|
||||
"ui.settings.language.persisted": "Сохранено для вашей учётной записи и используется в CLI.",
|
||||
"ui.settings.language.persisted_error": "Сохранено локально, но синхронизация учётной записи не удалась.",
|
||||
"ui.settings.language.sign_in_hint": "Войдите в систему, чтобы синхронизировать этот параметр с CLI.",
|
||||
"ui.first_signal.label": "Первый сигнал",
|
||||
"ui.first_signal.run_prefix": "Запуск:",
|
||||
"ui.first_signal.live": "В реальном времени",
|
||||
"ui.first_signal.polling": "Опрос",
|
||||
"ui.first_signal.range_prefix": "Диапазон",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "Ждем первого сигнала…",
|
||||
"ui.first_signal.not_available": "Сигнал пока недоступен.",
|
||||
"ui.first_signal.offline": "Офлайн. Последний известный сигнал может быть устаревшим.",
|
||||
"ui.first_signal.failed": "Не удалось загрузить сигнал.",
|
||||
"ui.first_signal.retry": "Повторить",
|
||||
"ui.first_signal.try_again": "Попробовать снова",
|
||||
"ui.first_signal.kind.queued": "В очереди",
|
||||
"ui.first_signal.kind.started": "Запущено",
|
||||
"ui.first_signal.kind.phase": "В процессе",
|
||||
"ui.first_signal.kind.blocked": "Заблокировано",
|
||||
"ui.first_signal.kind.failed": "Ошибка",
|
||||
"ui.first_signal.kind.succeeded": "Успешно",
|
||||
"ui.first_signal.kind.canceled": "Отменено",
|
||||
"ui.first_signal.kind.unavailable": "Недоступно",
|
||||
"ui.first_signal.kind.unknown": "Неизвестно",
|
||||
"ui.first_signal.stage.resolve": "Разрешение",
|
||||
"ui.first_signal.stage.fetch": "Получение данных",
|
||||
"ui.first_signal.stage.restore": "Восстановление",
|
||||
"ui.first_signal.stage.analyze": "Анализ",
|
||||
"ui.first_signal.stage.policy": "Оценка политики",
|
||||
"ui.first_signal.stage.report": "Формирование отчета",
|
||||
"ui.first_signal.stage.unknown": "Обработка",
|
||||
"ui.first_signal.aria.card_label": "Статус первого сигнала",
|
||||
"ui.severity.critical": "Критический",
|
||||
"ui.severity.high": "Высокий",
|
||||
"ui.severity.medium": "Середина",
|
||||
"ui.severity.low": "Низкий",
|
||||
"ui.severity.info": "Информация",
|
||||
"ui.severity.none": "Нет",
|
||||
"ui.release_orchestrator.title": "Оркестратор релизов",
|
||||
"ui.release_orchestrator.subtitle": "Обзор конвейера и управление выпусками",
|
||||
"ui.release_orchestrator.pipeline_runs": "Трубопроводные трассы",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Обновить панель мониторинга",
|
||||
"ui.risk_dashboard.eyebrow": "Шлюз · Риск",
|
||||
"ui.risk_dashboard.title": "Профили рисков",
|
||||
"ui.risk_dashboard.subtitle": "Риск-позиция по арендатору с детерминированной сортировкой.",
|
||||
"ui.risk_dashboard.up_to_date": "Актуально",
|
||||
"ui.risk_dashboard.last_computation": "Последнее вычисление",
|
||||
"ui.risk_dashboard.search_placeholder": "Название содержит",
|
||||
"ui.risk_dashboard.evaluated": "оценено",
|
||||
"ui.risk_dashboard.risks_suffix": "риски.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Невозможно загрузить профили рисков.",
|
||||
"ui.risk_dashboard.no_risks_found": "Никаких рисков для существующих фильтров не обнаружено.",
|
||||
"ui.risk_dashboard.loading_risks": "Загрузка рисков…",
|
||||
"ui.findings.title": "Находки",
|
||||
"ui.findings.search_placeholder": "Поиск находок...",
|
||||
"ui.findings.clear_filters": "Очистить фильтры",
|
||||
"ui.findings.bulk_triage": "Массовая сортировка",
|
||||
"ui.findings.export_all": "Экспортировать все результаты",
|
||||
"ui.findings.export_selected": "Экспортировать выбранные результаты",
|
||||
"ui.findings.select_all": "Выбрать все выводы",
|
||||
"ui.findings.trust": "Доверие",
|
||||
"ui.findings.advisory": "Бюллетень",
|
||||
"ui.findings.package": "Пакет",
|
||||
"ui.findings.flags": "Флаги",
|
||||
"ui.findings.why": "Почему",
|
||||
"ui.findings.select": "Выбирать",
|
||||
"ui.findings.no_findings": "Нет выводов для отображения.",
|
||||
"ui.findings.no_match": "Нет результатов, соответствующих текущим фильтрам.",
|
||||
"ui.sources_dashboard.title": "Панель источников",
|
||||
"ui.sources_dashboard.verifying": "Проверка...",
|
||||
"ui.sources_dashboard.verify_24h": "Подтвердить за последние 24 часа",
|
||||
"ui.sources_dashboard.loading_aoc": "Загрузка показателей AOC...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC: пройдено/не пройдено",
|
||||
"ui.sources_dashboard.pass_rate": "Проходной балл",
|
||||
"ui.sources_dashboard.passed": "Пройдено",
|
||||
"ui.sources_dashboard.failed": "Не пройдено",
|
||||
"ui.sources_dashboard.recent_violations": "Недавние нарушения",
|
||||
"ui.sources_dashboard.no_violations": "Нет нарушений во временном окне",
|
||||
"ui.sources_dashboard.throughput_title": "Пропускная способность приема",
|
||||
"ui.sources_dashboard.docs_per_min": "документов/мин",
|
||||
"ui.sources_dashboard.avg_ms": "в среднем мс",
|
||||
"ui.sources_dashboard.p95_ms": "p95 мс",
|
||||
"ui.sources_dashboard.queue": "очередь",
|
||||
"ui.sources_dashboard.errors": "ошибки",
|
||||
"ui.sources_dashboard.verification_complete": "Проверка завершена",
|
||||
"ui.sources_dashboard.checked": "Проверено:",
|
||||
"ui.sources_dashboard.violations": "нарушение(я)",
|
||||
"ui.sources_dashboard.field": "Поле:",
|
||||
"ui.sources_dashboard.expected": "ожидал:",
|
||||
"ui.sources_dashboard.actual": "фактическое:",
|
||||
"ui.sources_dashboard.cli_equivalent": "Эквивалент CLI:",
|
||||
"ui.sources_dashboard.data_from": "Данные из",
|
||||
"ui.sources_dashboard.to": "к",
|
||||
"ui.sources_dashboard.hour_window": "часовое окно",
|
||||
"ui.timeline.title": "Хронология",
|
||||
"ui.timeline.event_timeline": "Хронология событий",
|
||||
"ui.timeline.refresh_timeline": "Обновить хронологию",
|
||||
"ui.timeline.loading": "Загрузка графика...",
|
||||
"ui.timeline.empty_state": "Введите идентификатор корреляции, чтобы просмотреть хронологию событий.",
|
||||
"ui.timeline.critical_path": "Анализ критического пути",
|
||||
"ui.timeline.causal_lanes": "Причинно-следственные связи событий",
|
||||
"ui.timeline.load_more": "Загрузить больше событий",
|
||||
"ui.timeline.event_details": "Подробности мероприятия",
|
||||
"ui.timeline.events": "события",
|
||||
"ui.exception_center.title": "Центр исключений",
|
||||
"ui.exception_center.list_view": "Просмотр списка",
|
||||
"ui.exception_center.kanban_view": "Канбан-представление",
|
||||
"ui.exception_center.new_exception": "+ Новое исключение",
|
||||
"ui.exception_center.search_placeholder": "Искать исключения...",
|
||||
"ui.exception_center.type_vulnerability": "уязвимость",
|
||||
"ui.exception_center.type_license": "лицензия",
|
||||
"ui.exception_center.type_policy": "политика",
|
||||
"ui.exception_center.type_entropy": "энтропия",
|
||||
"ui.exception_center.type_determinism": "детерминизм",
|
||||
"ui.exception_center.expiring_soon": "Срок действия скоро истекает",
|
||||
"ui.exception_center.clear_filters": "Очистить фильтры",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.exception_center.audit_title": "Посмотреть журнал аудита",
|
||||
"ui.exception_center.no_exceptions": "Нет исключений, соответствующих текущим фильтрам.",
|
||||
"ui.exception_center.column_empty": "Никаких исключений",
|
||||
"ui.exception_center.exceptions_suffix": "исключения",
|
||||
"ui.evidence_thread.back_to_list": "Вернуться к списку",
|
||||
"ui.evidence_thread.title_default": "Доказательная тема",
|
||||
"ui.evidence_thread.copy_digest": "Копировать полный дайджест",
|
||||
"ui.evidence_thread.risk_label": "Риск:",
|
||||
"ui.evidence_thread.nodes": "узлы",
|
||||
"ui.evidence_thread.loading": "Загрузка цепочки доказательств...",
|
||||
"ui.evidence_thread.graph_tab": "График",
|
||||
"ui.evidence_thread.timeline_tab": "Хронология",
|
||||
"ui.evidence_thread.transcript_tab": "Стенограмма",
|
||||
"ui.evidence_thread.not_found": "Для этого артефакта не найдено нити доказательств.",
|
||||
"ui.vulnerability_detail.eyebrow": "Уязвимость",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.impact_first": "Воздействие прежде всего",
|
||||
"ui.vulnerability_detail.epss": "ЭПСС",
|
||||
"ui.vulnerability_detail.kev": "КЕВ",
|
||||
"ui.vulnerability_detail.kev_listed": "Внесен в список",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Нет в списке",
|
||||
"ui.vulnerability_detail.reachability": "Доступность",
|
||||
"ui.vulnerability_detail.blast_radius": "Радиус взрыва",
|
||||
"ui.vulnerability_detail.assets": "ресурсы",
|
||||
"ui.vulnerability_detail.binary_resolution": "Двоичное разрешение",
|
||||
"ui.vulnerability_detail.evidence_suffix": "доказательство",
|
||||
"ui.vulnerability_detail.fingerprint_note": "Этот двоичный файл был идентифицирован как исправленный с помощью анализа отпечатков пальцев, а не просто сопоставления версий.",
|
||||
"ui.vulnerability_detail.affected_components": "Затронутые компоненты",
|
||||
"ui.vulnerability_detail.fix": "исправить",
|
||||
"ui.vulnerability_detail.evidence_tree": "Дерево доказательств и ссылки на цитирование",
|
||||
"ui.vulnerability_detail.evidence_explorer": "исследователь доказательств",
|
||||
"ui.vulnerability_detail.references": "Ссылки",
|
||||
"ui.vulnerability_detail.back_to_risk": "Назад к риску"
|
||||
}
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "uk-UA", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Loading...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Something went wrong.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"ui.actions.save": "Save",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.cancel": "Cancel",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.retry": "Retry",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Fresh auth: Active",
|
||||
"ui.auth.fresh_stale": "Fresh auth: Stale",
|
||||
"ui.locale.label": "Mova",
|
||||
"ui.locale.en_us": "Angliiska (SSHA)",
|
||||
"ui.locale.de_de": "Nimetska (Nimechchyna)",
|
||||
"ui.locale.bg_bg": "Bolgarska (Bolhariia)",
|
||||
"ui.locale.ru_ru": "Rosiiska (Rosiia)",
|
||||
"ui.locale.es_es": "Ispanska (Ispaniia)",
|
||||
"ui.locale.fr_fr": "Frantsuzka (Frantsiia)",
|
||||
"ui.locale.zh_tw": "Kytaiska tradytsiina (Taivan)",
|
||||
"ui.locale.zh_cn": "Kytaiska sproshchena (Kytai)",
|
||||
"ui.locale.uk_ua": "Ukrainska (Ukraina)",
|
||||
"ui.settings.language.title": "Mova",
|
||||
"ui.settings.language.subtitle": "Vstanovit bazhanu movu konsoli.",
|
||||
"ui.settings.language.description": "Zminy zastosovuiutsia v UI odrazu.",
|
||||
"ui.settings.language.selector_label": "Bazhana mova",
|
||||
"ui.settings.language.persisted": "Zberezheno dlia vashoho oblikovoho zapysu ta povtorno vykorystovuietsia v CLI.",
|
||||
"ui.settings.language.persisted_error": "Lokalno zberezheno, ale synkhronizatsiia oblikovoho zapysu ne vdlasia.",
|
||||
"ui.settings.language.sign_in_hint": "Uvijdit, shchob synkhronizuvaty tsiu nalashtunku z CLI.",
|
||||
|
||||
"ui.first_signal.label": "First signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Waiting for first signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.failed": "Failed to load signal.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"_meta": {
|
||||
"locale": "uk-UA",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "Завантаження...",
|
||||
"ui.loading.spinner": "Будь ласка, зачекайте...",
|
||||
"ui.loading.slow": "Це триває довше, ніж очікувалося...",
|
||||
"ui.error.generic": "Щось пішло не так.",
|
||||
"ui.error.network": "Помилка мережі. Перевірте підключення.",
|
||||
"ui.error.timeout": "Час очікування запиту минув. Спробуйте ще раз.",
|
||||
"ui.error.not_found": "Потрібний ресурс не знайдено.",
|
||||
"ui.error.unauthorized": "Ви не маєте дозволу переглядати це.",
|
||||
"ui.error.server_error": "Помилка сервера. Спробуйте пізніше.",
|
||||
"ui.error.try_again": "Спробувати ще раз",
|
||||
"ui.error.go_back": "Іди назад",
|
||||
"ui.offline.banner": "Ви офлайн.",
|
||||
"ui.offline.description": "Деякі функції можуть бути недоступні.",
|
||||
"ui.offline.reconnecting": "Повторне підключення...",
|
||||
"ui.offline.reconnected": "Знову онлайн.",
|
||||
"ui.toast.success": "Успіх",
|
||||
"ui.toast.info": "Інформація",
|
||||
"ui.toast.warning": "Попередження",
|
||||
"ui.toast.error": "Помилка",
|
||||
"ui.toast.dismiss": "Закрити",
|
||||
"ui.toast.undo": "Скасувати",
|
||||
"ui.actions.save": "Зберегти",
|
||||
"ui.actions.saving": "Збереження...",
|
||||
"ui.actions.saved": "Збережено",
|
||||
"ui.actions.cancel": "Скасувати",
|
||||
"ui.actions.confirm": "Підтвердити",
|
||||
"ui.actions.delete": "Видалити",
|
||||
"ui.actions.deleting": "Видалення...",
|
||||
"ui.actions.deleted": "Видалено",
|
||||
"ui.actions.submit": "Надіслати",
|
||||
"ui.actions.submitting": "Надсилання...",
|
||||
"ui.actions.submitted": "Надіслано",
|
||||
"ui.actions.close": "Закрити",
|
||||
"ui.actions.expand": "Розгорнути",
|
||||
"ui.actions.collapse": "Згорнути",
|
||||
"ui.actions.show_more": "Показати більше",
|
||||
"ui.actions.show_less": "Показати менше",
|
||||
"ui.actions.retry": "Повторити",
|
||||
"ui.actions.refresh": "Оновити",
|
||||
"ui.actions.export": "Експортувати",
|
||||
"ui.actions.search": "Пошук",
|
||||
"ui.actions.clear": "Очистити",
|
||||
"ui.actions.view": "Переглянути",
|
||||
"ui.actions.dismiss": "Закрити",
|
||||
"ui.actions.show": "Показати",
|
||||
"ui.actions.hide": "Сховати",
|
||||
"ui.actions.sign_in": "Увійти",
|
||||
"ui.actions.back_to_list": "Повернутися до списку",
|
||||
"ui.actions.load_more": "Завантажити ще",
|
||||
"ui.labels.all": "все",
|
||||
"ui.labels.title": "Назва",
|
||||
"ui.labels.description": "опис",
|
||||
"ui.labels.status": "Статус",
|
||||
"ui.labels.score": "Оцінка",
|
||||
"ui.labels.severity": "Суворість",
|
||||
"ui.labels.details": "Подробиці",
|
||||
"ui.labels.actions": "Дії",
|
||||
"ui.labels.type": "Тип",
|
||||
"ui.labels.tags": "Теги",
|
||||
"ui.labels.filters": "Фільтри",
|
||||
"ui.labels.updated": "Оновлено",
|
||||
"ui.labels.showing": "Показ",
|
||||
"ui.labels.of": "з",
|
||||
"ui.labels.total": "Всього",
|
||||
"ui.labels.not_applicable": "н/д",
|
||||
"ui.labels.selected": "вибрано",
|
||||
"ui.labels.last_updated": "Останнє оновлення:",
|
||||
"ui.labels.expires": "Термін дії закінчується",
|
||||
"ui.validation.required": "Це поле є обов'язковим для заповнення.",
|
||||
"ui.validation.invalid": "Недійсне значення.",
|
||||
"ui.validation.too_long": "Максимальна дозволена кількість символів: {max}.",
|
||||
"ui.validation.too_short": "Необхідна мінімум {min} символів.",
|
||||
"ui.validation.invalid_email": "Введіть дійсну електронну адресу.",
|
||||
"ui.validation.invalid_url": "Введіть дійсну URL-адресу.",
|
||||
"ui.a11y.loading": "Вміст завантажується.",
|
||||
"ui.a11y.loaded": "Вміст завантажено.",
|
||||
"ui.a11y.error": "Сталася помилка.",
|
||||
"ui.a11y.expanded": "Розширений",
|
||||
"ui.a11y.collapsed": "Згорнуто",
|
||||
"ui.a11y.selected": "Вибране",
|
||||
"ui.a11y.deselected": "Знято вибір",
|
||||
"ui.a11y.required": "Обов'язкове поле",
|
||||
"ui.a11y.optional": "Додатково",
|
||||
"ui.motion.reduced": "Анімації зменшено.",
|
||||
"ui.motion.enabled": "Анімації включені.",
|
||||
"ui.auth.fresh_active": "Свіжа авторизація: активна",
|
||||
"ui.auth.fresh_stale": "Свіжа авторизація: застаріла",
|
||||
"ui.locale.label": "Мова",
|
||||
"ui.locale.en_us": "Англійська (США)",
|
||||
"ui.locale.de_de": "Німецька (Німеччина)",
|
||||
"ui.locale.bg_bg": "Болгарська (Болгарія)",
|
||||
"ui.locale.ru_ru": "Російська (Росія)",
|
||||
"ui.locale.es_es": "Іспанська (Іспанія)",
|
||||
"ui.locale.fr_fr": "Французька (Франція)",
|
||||
"ui.locale.zh_tw": "Китайська традиційна (Тайвань)",
|
||||
"ui.locale.zh_cn": "Китайська спрощена (Китай)",
|
||||
"ui.locale.uk_ua": "Українська (Україна)",
|
||||
"ui.settings.language.title": "Мова",
|
||||
"ui.settings.language.subtitle": "Виберіть бажану мову консолі.",
|
||||
"ui.settings.language.description": "Зміни застосовуються одразу в інтерфейсі.",
|
||||
"ui.settings.language.selector_label": "Бажана мова",
|
||||
"ui.settings.language.persisted": "Збережено для вашого облікового запису та використовується в CLI.",
|
||||
"ui.settings.language.persisted_error": "Збережено локально, але синхронізація облікового запису не вдалася.",
|
||||
"ui.settings.language.sign_in_hint": "Увійдіть у систему, щоб синхронізувати цей параметр із CLI.",
|
||||
"ui.first_signal.label": "Перший сигнал",
|
||||
"ui.first_signal.run_prefix": "Запуск:",
|
||||
"ui.first_signal.live": "Наживо",
|
||||
"ui.first_signal.polling": "Опитування",
|
||||
"ui.first_signal.range_prefix": "Діапазон",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "Очікування першого сигналу…",
|
||||
"ui.first_signal.not_available": "Сигнал ще недоступний.",
|
||||
"ui.first_signal.offline": "Офлайн. Останній відомий сигнал може бути застарілим.",
|
||||
"ui.first_signal.failed": "Не вдалося завантажити сигнал.",
|
||||
"ui.first_signal.retry": "Повторити",
|
||||
"ui.first_signal.try_again": "Спробувати ще раз",
|
||||
"ui.first_signal.kind.queued": "У черзі",
|
||||
"ui.first_signal.kind.started": "Розпочато",
|
||||
"ui.first_signal.kind.phase": "У процесі",
|
||||
"ui.first_signal.kind.blocked": "Заблоковано",
|
||||
"ui.first_signal.kind.failed": "Помилка",
|
||||
"ui.first_signal.kind.succeeded": "Успішно",
|
||||
"ui.first_signal.kind.canceled": "Скасовано",
|
||||
"ui.first_signal.kind.unavailable": "Недоступно",
|
||||
"ui.first_signal.kind.unknown": "Невідомо",
|
||||
"ui.first_signal.stage.resolve": "Визначення",
|
||||
"ui.first_signal.stage.fetch": "Отримання даних",
|
||||
"ui.first_signal.stage.restore": "Відновлення",
|
||||
"ui.first_signal.stage.analyze": "Аналіз",
|
||||
"ui.first_signal.stage.policy": "Оцінка політики",
|
||||
"ui.first_signal.stage.report": "Формування звіту",
|
||||
"ui.first_signal.stage.unknown": "Обробка",
|
||||
"ui.first_signal.aria.card_label": "Статус першого сигналу",
|
||||
"ui.severity.critical": "Критичний",
|
||||
"ui.severity.high": "Високий",
|
||||
"ui.severity.medium": "Середній",
|
||||
"ui.severity.low": "Низький",
|
||||
"ui.severity.info": "Інформація",
|
||||
"ui.severity.none": "Немає",
|
||||
"ui.release_orchestrator.title": "Оркестратор релізів",
|
||||
"ui.release_orchestrator.subtitle": "Огляд конвеєра та керування випуском",
|
||||
"ui.release_orchestrator.pipeline_runs": "Трубопроводи",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Оновити інформаційну панель",
|
||||
"ui.risk_dashboard.eyebrow": "Шлюз · Ризик",
|
||||
"ui.risk_dashboard.title": "Профілі ризиків",
|
||||
"ui.risk_dashboard.subtitle": "Ризик-позиція в межах тенанта з детермінованим сортуванням.",
|
||||
"ui.risk_dashboard.up_to_date": "В актуальному стані",
|
||||
"ui.risk_dashboard.last_computation": "Останнє обчислення",
|
||||
"ui.risk_dashboard.search_placeholder": "Назва містить",
|
||||
"ui.risk_dashboard.evaluated": "Оцінено",
|
||||
"ui.risk_dashboard.risks_suffix": "ризики.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Не вдалося завантажити профілі ризиків.",
|
||||
"ui.risk_dashboard.no_risks_found": "Жодних ризиків для поточних фільтрів не виявлено.",
|
||||
"ui.risk_dashboard.loading_risks": "Завантаження ризиків…",
|
||||
"ui.findings.title": "Знахідки",
|
||||
"ui.findings.search_placeholder": "Пошук знахідок...",
|
||||
"ui.findings.clear_filters": "Очистити фільтри",
|
||||
"ui.findings.bulk_triage": "Масове сортування",
|
||||
"ui.findings.export_all": "Експортувати всі висновки",
|
||||
"ui.findings.export_selected": "Експорт вибраних результатів",
|
||||
"ui.findings.select_all": "Виберіть усі знахідки",
|
||||
"ui.findings.trust": "Довіра",
|
||||
"ui.findings.advisory": "Бюлетень",
|
||||
"ui.findings.package": "Пакет",
|
||||
"ui.findings.flags": "Прапори",
|
||||
"ui.findings.why": "Чому",
|
||||
"ui.findings.select": "Виберіть",
|
||||
"ui.findings.no_findings": "Немає знахідок для відображення.",
|
||||
"ui.findings.no_match": "Жодна знахідка не відповідає поточним фільтрам.",
|
||||
"ui.sources_dashboard.title": "Інформаційна панель джерел",
|
||||
"ui.sources_dashboard.verifying": "Перевірка...",
|
||||
"ui.sources_dashboard.verify_24h": "Перевірте останні 24 години",
|
||||
"ui.sources_dashboard.loading_aoc": "Завантаження показників AOC...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC: пройдено/не пройдено",
|
||||
"ui.sources_dashboard.pass_rate": "Прохідний рейтинг",
|
||||
"ui.sources_dashboard.passed": "Пройдено",
|
||||
"ui.sources_dashboard.failed": "Не пройдено",
|
||||
"ui.sources_dashboard.recent_violations": "Останні порушення",
|
||||
"ui.sources_dashboard.no_violations": "Без порушень у часовому вікні",
|
||||
"ui.sources_dashboard.throughput_title": "Пропускна здатність прийому",
|
||||
"ui.sources_dashboard.docs_per_min": "документів/хв",
|
||||
"ui.sources_dashboard.avg_ms": "середнє мс",
|
||||
"ui.sources_dashboard.p95_ms": "p95 мс",
|
||||
"ui.sources_dashboard.queue": "черга",
|
||||
"ui.sources_dashboard.errors": "помилки",
|
||||
"ui.sources_dashboard.verification_complete": "Перевірку завершено",
|
||||
"ui.sources_dashboard.checked": "Перевірено:",
|
||||
"ui.sources_dashboard.violations": "порушення",
|
||||
"ui.sources_dashboard.field": "Поле:",
|
||||
"ui.sources_dashboard.expected": "очікується:",
|
||||
"ui.sources_dashboard.actual": "фактично:",
|
||||
"ui.sources_dashboard.cli_equivalent": "Еквівалент CLI:",
|
||||
"ui.sources_dashboard.data_from": "Дані з",
|
||||
"ui.sources_dashboard.to": "до",
|
||||
"ui.sources_dashboard.hour_window": "год. вікно",
|
||||
"ui.timeline.title": "Хронологія",
|
||||
"ui.timeline.event_timeline": "Хронологія події",
|
||||
"ui.timeline.refresh_timeline": "Оновити шкалу часу",
|
||||
"ui.timeline.loading": "Завантаження хронології...",
|
||||
"ui.timeline.empty_state": "Введіть ідентифікатор кореляції, щоб переглянути часову шкалу події",
|
||||
"ui.timeline.critical_path": "Аналіз критичного шляху",
|
||||
"ui.timeline.causal_lanes": "Причинно-наслідкові шляхи події",
|
||||
"ui.timeline.load_more": "Завантажити більше подій",
|
||||
"ui.timeline.event_details": "Деталі події",
|
||||
"ui.timeline.events": "події",
|
||||
"ui.exception_center.title": "Центр винятків",
|
||||
"ui.exception_center.list_view": "Перегляд списку",
|
||||
"ui.exception_center.kanban_view": "Вид Канбан",
|
||||
"ui.exception_center.new_exception": "+ Новий виняток",
|
||||
"ui.exception_center.search_placeholder": "Винятки пошуку...",
|
||||
"ui.exception_center.type_vulnerability": "вразливість",
|
||||
"ui.exception_center.type_license": "ліцензія",
|
||||
"ui.exception_center.type_policy": "політика",
|
||||
"ui.exception_center.type_entropy": "ентропія",
|
||||
"ui.exception_center.type_determinism": "детермінізм",
|
||||
"ui.exception_center.expiring_soon": "Термін дії скоро закінчується",
|
||||
"ui.exception_center.clear_filters": "Очистити фільтри",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.exception_center.audit_title": "Переглянути журнал аудиту",
|
||||
"ui.exception_center.no_exceptions": "Жодні винятки не відповідають поточним фільтрам",
|
||||
"ui.exception_center.column_empty": "Без винятків",
|
||||
"ui.exception_center.exceptions_suffix": "винятки",
|
||||
"ui.evidence_thread.back_to_list": "Повернутися до списку",
|
||||
"ui.evidence_thread.title_default": "Нитка доказів",
|
||||
"ui.evidence_thread.copy_digest": "Копіювати повний дайджест",
|
||||
"ui.evidence_thread.risk_label": "Ризик:",
|
||||
"ui.evidence_thread.nodes": "вузлів",
|
||||
"ui.evidence_thread.loading": "Завантаження потоку доказів...",
|
||||
"ui.evidence_thread.graph_tab": "Графік",
|
||||
"ui.evidence_thread.timeline_tab": "Хронологія",
|
||||
"ui.evidence_thread.transcript_tab": "Стенограма",
|
||||
"ui.evidence_thread.not_found": "Не знайдено доказів цього артефакту.",
|
||||
"ui.vulnerability_detail.eyebrow": "Вразливість",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.impact_first": "Вплив Перший",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.kev_listed": "Перераховано",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Не вказано",
|
||||
"ui.vulnerability_detail.reachability": "Досяжність",
|
||||
"ui.vulnerability_detail.blast_radius": "Радіус вибуху",
|
||||
"ui.vulnerability_detail.assets": "активів",
|
||||
"ui.vulnerability_detail.binary_resolution": "Двійкова роздільна здатність",
|
||||
"ui.vulnerability_detail.evidence_suffix": "докази",
|
||||
"ui.vulnerability_detail.fingerprint_note": "Цей двійковий файл було ідентифіковано як виправлений за допомогою аналізу відбитків пальців, а не лише зіставлення версій.",
|
||||
"ui.vulnerability_detail.affected_components": "Уражені компоненти",
|
||||
"ui.vulnerability_detail.fix": "виправити",
|
||||
"ui.vulnerability_detail.evidence_tree": "Дерево доказів і посилання на цитування",
|
||||
"ui.vulnerability_detail.evidence_explorer": "дослідник доказів",
|
||||
"ui.vulnerability_detail.references": "Список літератури",
|
||||
"ui.vulnerability_detail.back_to_risk": "Назад до Ризику"
|
||||
}
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "zh-CN", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Loading...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Something went wrong.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"ui.actions.save": "Save",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.cancel": "Cancel",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.retry": "Retry",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Fresh auth: Active",
|
||||
"ui.auth.fresh_stale": "Fresh auth: Stale",
|
||||
"ui.locale.label": "Language",
|
||||
"ui.locale.en_us": "English (US)",
|
||||
"ui.locale.de_de": "German (Germany)",
|
||||
"ui.locale.bg_bg": "Bulgarian (Bulgaria)",
|
||||
"ui.locale.ru_ru": "Russian (Russia)",
|
||||
"ui.locale.es_es": "Spanish (Spain)",
|
||||
"ui.locale.fr_fr": "French (France)",
|
||||
"ui.locale.zh_tw": "Chinese Traditional (Taiwan)",
|
||||
"ui.locale.zh_cn": "Chinese Simplified (China)",
|
||||
"ui.locale.uk_ua": "Ukrainian (Ukraine)",
|
||||
"ui.settings.language.title": "Yuyan",
|
||||
"ui.settings.language.subtitle": "Shezhi nin shouxuan de kongzhi tai yuyan.",
|
||||
"ui.settings.language.description": "Genggai hui liji yingyong dao UI.",
|
||||
"ui.settings.language.selector_label": "Shouxuan yuyan",
|
||||
"ui.settings.language.persisted": "Yi baocun dao nin de zhanghu bing zai CLI zhong chongyong.",
|
||||
"ui.settings.language.persisted_error": "Yi ben di baocun, dan zhanghu tongbu shibai.",
|
||||
"ui.settings.language.sign_in_hint": "Qing denglu yi jiang ci pianhao tongbu dao CLI.",
|
||||
|
||||
"ui.first_signal.label": "First signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Waiting for first signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.failed": "Failed to load signal.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"_meta": {
|
||||
"locale": "zh-CN",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "加载中...",
|
||||
"ui.loading.spinner": "请稍等...",
|
||||
"ui.loading.slow": "这比预期花费的时间更长......",
|
||||
"ui.error.generic": "出了点问题。",
|
||||
"ui.error.network": "网络错误。检查您的连接。",
|
||||
"ui.error.timeout": "请求超时。请再试一次。",
|
||||
"ui.error.not_found": "未找到请求的资源。",
|
||||
"ui.error.unauthorized": "您无权查看此内容。",
|
||||
"ui.error.server_error": "服务器错误。请稍后重试。",
|
||||
"ui.error.try_again": "重试",
|
||||
"ui.error.go_back": "回去",
|
||||
"ui.offline.banner": "当前离线。",
|
||||
"ui.offline.description": "某些功能可能不可用。",
|
||||
"ui.offline.reconnecting": "正在重新连接...",
|
||||
"ui.offline.reconnected": "已恢复在线。",
|
||||
"ui.toast.success": "成功",
|
||||
"ui.toast.info": "信息",
|
||||
"ui.toast.warning": "警告",
|
||||
"ui.toast.error": "错误",
|
||||
"ui.toast.dismiss": "关闭",
|
||||
"ui.toast.undo": "撤消",
|
||||
"ui.actions.save": "保存",
|
||||
"ui.actions.saving": "正在保存...",
|
||||
"ui.actions.saved": "已保存",
|
||||
"ui.actions.cancel": "取消",
|
||||
"ui.actions.confirm": "确认",
|
||||
"ui.actions.delete": "删除",
|
||||
"ui.actions.deleting": "正在删除...",
|
||||
"ui.actions.deleted": "已删除",
|
||||
"ui.actions.submit": "提交",
|
||||
"ui.actions.submitting": "正在提交...",
|
||||
"ui.actions.submitted": "已提交",
|
||||
"ui.actions.close": "关闭",
|
||||
"ui.actions.expand": "展开",
|
||||
"ui.actions.collapse": "收起",
|
||||
"ui.actions.show_more": "显示更多",
|
||||
"ui.actions.show_less": "显示更少",
|
||||
"ui.actions.retry": "重试",
|
||||
"ui.actions.refresh": "刷新",
|
||||
"ui.actions.export": "导出",
|
||||
"ui.actions.search": "搜索",
|
||||
"ui.actions.clear": "清除",
|
||||
"ui.actions.view": "查看",
|
||||
"ui.actions.dismiss": "关闭",
|
||||
"ui.actions.show": "显示",
|
||||
"ui.actions.hide": "隐藏",
|
||||
"ui.actions.sign_in": "登录",
|
||||
"ui.actions.back_to_list": "返回列表",
|
||||
"ui.actions.load_more": "加载更多",
|
||||
"ui.labels.all": "全部",
|
||||
"ui.labels.title": "标题",
|
||||
"ui.labels.description": "描述",
|
||||
"ui.labels.status": "地位",
|
||||
"ui.labels.score": "分数",
|
||||
"ui.labels.severity": "严重性",
|
||||
"ui.labels.details": "细节",
|
||||
"ui.labels.actions": "行动",
|
||||
"ui.labels.type": "类型",
|
||||
"ui.labels.tags": "标签",
|
||||
"ui.labels.filters": "过滤器",
|
||||
"ui.labels.updated": "已更新",
|
||||
"ui.labels.showing": "显示中",
|
||||
"ui.labels.of": "的",
|
||||
"ui.labels.total": "全部的",
|
||||
"ui.labels.not_applicable": "不适用",
|
||||
"ui.labels.selected": "已选择",
|
||||
"ui.labels.last_updated": "最后更新:",
|
||||
"ui.labels.expires": "过期",
|
||||
"ui.validation.required": "此字段是必需的。",
|
||||
"ui.validation.invalid": "无效值。",
|
||||
"ui.validation.too_long": "允许的最大字符数为 {max}。",
|
||||
"ui.validation.too_short": "最少需要 {min} 个字符。",
|
||||
"ui.validation.invalid_email": "请输入有效的电子邮件地址。",
|
||||
"ui.validation.invalid_url": "请输入有效的网址。",
|
||||
"ui.a11y.loading": "内容正在加载。",
|
||||
"ui.a11y.loaded": "内容已加载。",
|
||||
"ui.a11y.error": "发生错误。",
|
||||
"ui.a11y.expanded": "扩展",
|
||||
"ui.a11y.collapsed": "倒塌",
|
||||
"ui.a11y.selected": "已选择",
|
||||
"ui.a11y.deselected": "取消选择",
|
||||
"ui.a11y.required": "必填字段",
|
||||
"ui.a11y.optional": "选修的",
|
||||
"ui.motion.reduced": "动画减少。",
|
||||
"ui.motion.enabled": "动画已启用。",
|
||||
"ui.auth.fresh_active": "新鲜授权:活跃",
|
||||
"ui.auth.fresh_stale": "新鲜授权:陈旧",
|
||||
"ui.locale.label": "语言",
|
||||
"ui.locale.en_us": "英语(美国)",
|
||||
"ui.locale.de_de": "德语(德国)",
|
||||
"ui.locale.bg_bg": "保加利亚语(保加利亚)",
|
||||
"ui.locale.ru_ru": "俄语(俄罗斯)",
|
||||
"ui.locale.es_es": "西班牙语(西班牙)",
|
||||
"ui.locale.fr_fr": "法语(法国)",
|
||||
"ui.locale.zh_tw": "繁体中文(台湾)",
|
||||
"ui.locale.zh_cn": "简体中文(中国)",
|
||||
"ui.locale.uk_ua": "乌克兰语(乌克兰)",
|
||||
"ui.settings.language.title": "语言",
|
||||
"ui.settings.language.subtitle": "设置控制台的首选语言。",
|
||||
"ui.settings.language.description": "更改会立即应用到界面。",
|
||||
"ui.settings.language.selector_label": "首选语言",
|
||||
"ui.settings.language.persisted": "已保存到你的账户,并在 CLI 中复用。",
|
||||
"ui.settings.language.persisted_error": "已在本地保存,但账户同步失败。",
|
||||
"ui.settings.language.sign_in_hint": "请登录以将此设置同步到 CLI。",
|
||||
"ui.first_signal.label": "首个信号",
|
||||
"ui.first_signal.run_prefix": "运行:",
|
||||
"ui.first_signal.live": "实时",
|
||||
"ui.first_signal.polling": "轮询",
|
||||
"ui.first_signal.range_prefix": "范围",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "等待第一个信号…",
|
||||
"ui.first_signal.not_available": "信号尚未可用。",
|
||||
"ui.first_signal.offline": "离线。最后已知的信号可能已过时。",
|
||||
"ui.first_signal.failed": "无法加载信号。",
|
||||
"ui.first_signal.retry": "重试",
|
||||
"ui.first_signal.try_again": "重试",
|
||||
"ui.first_signal.kind.queued": "排队中",
|
||||
"ui.first_signal.kind.started": "已开始",
|
||||
"ui.first_signal.kind.phase": "进行中",
|
||||
"ui.first_signal.kind.blocked": "已阻止",
|
||||
"ui.first_signal.kind.failed": "失败",
|
||||
"ui.first_signal.kind.succeeded": "已成功",
|
||||
"ui.first_signal.kind.canceled": "已取消",
|
||||
"ui.first_signal.kind.unavailable": "不可用",
|
||||
"ui.first_signal.kind.unknown": "未知",
|
||||
"ui.first_signal.stage.resolve": "解析中",
|
||||
"ui.first_signal.stage.fetch": "获取中",
|
||||
"ui.first_signal.stage.restore": "正在恢复",
|
||||
"ui.first_signal.stage.analyze": "分析中",
|
||||
"ui.first_signal.stage.policy": "策略评估",
|
||||
"ui.first_signal.stage.report": "生成报告",
|
||||
"ui.first_signal.stage.unknown": "处理中",
|
||||
"ui.first_signal.aria.card_label": "第一信号状态",
|
||||
"ui.severity.critical": "批判的",
|
||||
"ui.severity.high": "高的",
|
||||
"ui.severity.medium": "中等的",
|
||||
"ui.severity.low": "低的",
|
||||
"ui.severity.info": "信息",
|
||||
"ui.severity.none": "无",
|
||||
"ui.release_orchestrator.title": "发布编排器",
|
||||
"ui.release_orchestrator.subtitle": "管道概述和发布管理",
|
||||
"ui.release_orchestrator.pipeline_runs": "管道运行",
|
||||
"ui.release_orchestrator.refresh_dashboard": "刷新仪表板",
|
||||
"ui.risk_dashboard.eyebrow": "网关 · 风险",
|
||||
"ui.risk_dashboard.title": "风险概况",
|
||||
"ui.risk_dashboard.subtitle": "按租户范围并采用确定性排序的风险态势。",
|
||||
"ui.risk_dashboard.up_to_date": "最新",
|
||||
"ui.risk_dashboard.last_computation": "最后计算",
|
||||
"ui.risk_dashboard.search_placeholder": "标题包含",
|
||||
"ui.risk_dashboard.evaluated": "已评估",
|
||||
"ui.risk_dashboard.risks_suffix": "风险。",
|
||||
"ui.risk_dashboard.error_unable_to_load": "无法加载风险概况。",
|
||||
"ui.risk_dashboard.no_risks_found": "目前的过滤器未发现任何风险。",
|
||||
"ui.risk_dashboard.loading_risks": "正在加载风险…",
|
||||
"ui.findings.title": "安全发现",
|
||||
"ui.findings.search_placeholder": "搜索发现...",
|
||||
"ui.findings.clear_filters": "清除过滤器",
|
||||
"ui.findings.bulk_triage": "批量分类",
|
||||
"ui.findings.export_all": "导出所有结果",
|
||||
"ui.findings.export_selected": "导出选定的结果",
|
||||
"ui.findings.select_all": "选择所有结果",
|
||||
"ui.findings.trust": "可信度",
|
||||
"ui.findings.advisory": "安全通告",
|
||||
"ui.findings.package": "软件包",
|
||||
"ui.findings.flags": "标记",
|
||||
"ui.findings.why": "原因",
|
||||
"ui.findings.select": "选择",
|
||||
"ui.findings.no_findings": "没有可显示的结果。",
|
||||
"ui.findings.no_match": "没有发现与当前过滤器匹配的结果。",
|
||||
"ui.sources_dashboard.title": "来源仪表板",
|
||||
"ui.sources_dashboard.verifying": "正在验证...",
|
||||
"ui.sources_dashboard.verify_24h": "验证最近 24 小时",
|
||||
"ui.sources_dashboard.loading_aoc": "正在加载 AOC 指标...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC 通过/失败",
|
||||
"ui.sources_dashboard.pass_rate": "通过率",
|
||||
"ui.sources_dashboard.passed": "通过",
|
||||
"ui.sources_dashboard.failed": "失败",
|
||||
"ui.sources_dashboard.recent_violations": "最近的违规行为",
|
||||
"ui.sources_dashboard.no_violations": "时间窗口内无违规行为",
|
||||
"ui.sources_dashboard.throughput_title": "摄取吞吐量",
|
||||
"ui.sources_dashboard.docs_per_min": "文档/分钟",
|
||||
"ui.sources_dashboard.avg_ms": "平均毫秒数",
|
||||
"ui.sources_dashboard.p95_ms": "p95毫秒",
|
||||
"ui.sources_dashboard.queue": "队列",
|
||||
"ui.sources_dashboard.errors": "错误",
|
||||
"ui.sources_dashboard.verification_complete": "验证完成",
|
||||
"ui.sources_dashboard.checked": "已检查:",
|
||||
"ui.sources_dashboard.violations": "违规行为",
|
||||
"ui.sources_dashboard.field": "字段:",
|
||||
"ui.sources_dashboard.expected": "预期的:",
|
||||
"ui.sources_dashboard.actual": "实际:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI 等效项:",
|
||||
"ui.sources_dashboard.data_from": "数据来自",
|
||||
"ui.sources_dashboard.to": "到",
|
||||
"ui.sources_dashboard.hour_window": "小时窗口",
|
||||
"ui.timeline.title": "时间轴",
|
||||
"ui.timeline.event_timeline": "事件时间表",
|
||||
"ui.timeline.refresh_timeline": "刷新时间线",
|
||||
"ui.timeline.loading": "加载时间线...",
|
||||
"ui.timeline.empty_state": "输入关联 ID 以查看事件时间线",
|
||||
"ui.timeline.critical_path": "关键路径分析",
|
||||
"ui.timeline.causal_lanes": "事件因果车道",
|
||||
"ui.timeline.load_more": "加载更多事件",
|
||||
"ui.timeline.event_details": "活动详情",
|
||||
"ui.timeline.events": "事件",
|
||||
"ui.exception_center.title": "异常中心",
|
||||
"ui.exception_center.list_view": "列表视图",
|
||||
"ui.exception_center.kanban_view": "看板视图",
|
||||
"ui.exception_center.new_exception": "+ 新异常",
|
||||
"ui.exception_center.search_placeholder": "搜索例外...",
|
||||
"ui.exception_center.type_vulnerability": "漏洞",
|
||||
"ui.exception_center.type_license": "许可证",
|
||||
"ui.exception_center.type_policy": "策略",
|
||||
"ui.exception_center.type_entropy": "熵",
|
||||
"ui.exception_center.type_determinism": "确定性",
|
||||
"ui.exception_center.expiring_soon": "即将到期",
|
||||
"ui.exception_center.clear_filters": "清除过滤器",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.exception_center.audit_title": "查看审核日志",
|
||||
"ui.exception_center.no_exceptions": "没有与当前过滤器匹配的异常",
|
||||
"ui.exception_center.column_empty": "暂无例外",
|
||||
"ui.exception_center.exceptions_suffix": "例外情况",
|
||||
"ui.evidence_thread.back_to_list": "返回列表",
|
||||
"ui.evidence_thread.title_default": "证据线索",
|
||||
"ui.evidence_thread.copy_digest": "复制完整摘要",
|
||||
"ui.evidence_thread.risk_label": "风险:",
|
||||
"ui.evidence_thread.nodes": "节点",
|
||||
"ui.evidence_thread.loading": "正在加载证据线程...",
|
||||
"ui.evidence_thread.graph_tab": "图形",
|
||||
"ui.evidence_thread.timeline_tab": "时间轴",
|
||||
"ui.evidence_thread.transcript_tab": "成绩单",
|
||||
"ui.evidence_thread.not_found": "没有找到该文物的证据线索。",
|
||||
"ui.vulnerability_detail.eyebrow": "漏洞",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.impact_first": "影响第一",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.kev": "凯夫",
|
||||
"ui.vulnerability_detail.kev_listed": "上市",
|
||||
"ui.vulnerability_detail.kev_not_listed": "未列出",
|
||||
"ui.vulnerability_detail.reachability": "可达性",
|
||||
"ui.vulnerability_detail.blast_radius": "爆炸半径",
|
||||
"ui.vulnerability_detail.assets": "资产",
|
||||
"ui.vulnerability_detail.binary_resolution": "二进制分辨率",
|
||||
"ui.vulnerability_detail.evidence_suffix": "证据",
|
||||
"ui.vulnerability_detail.fingerprint_note": "该二进制文件通过指纹分析(而不仅仅是版本匹配)被识别为已修补。",
|
||||
"ui.vulnerability_detail.affected_components": "受影响的组件",
|
||||
"ui.vulnerability_detail.fix": "使固定",
|
||||
"ui.vulnerability_detail.evidence_tree": "证据树和引文链接",
|
||||
"ui.vulnerability_detail.evidence_explorer": "证据探索者",
|
||||
"ui.vulnerability_detail.references": "参考",
|
||||
"ui.vulnerability_detail.back_to_risk": "回到风险"
|
||||
}
|
||||
|
||||
@@ -1,275 +1,259 @@
|
||||
{
|
||||
"_meta": { "locale": "zh-TW", "namespace": "ui", "version": "1.0" },
|
||||
|
||||
"ui.loading.skeleton": "Loading...",
|
||||
"ui.loading.spinner": "Please wait...",
|
||||
"ui.loading.slow": "This is taking longer than expected...",
|
||||
|
||||
"ui.error.generic": "Something went wrong.",
|
||||
"ui.error.network": "Network error. Check your connection.",
|
||||
"ui.error.timeout": "Request timed out. Please try again.",
|
||||
"ui.error.not_found": "The requested resource was not found.",
|
||||
"ui.error.unauthorized": "You don't have permission to view this.",
|
||||
"ui.error.server_error": "Server error. Please try again later.",
|
||||
"ui.error.try_again": "Try again",
|
||||
"ui.error.go_back": "Go back",
|
||||
|
||||
"ui.offline.banner": "You're offline.",
|
||||
"ui.offline.description": "Some features may be unavailable.",
|
||||
"ui.offline.reconnecting": "Reconnecting...",
|
||||
"ui.offline.reconnected": "Back online.",
|
||||
|
||||
"ui.toast.success": "Success",
|
||||
"ui.toast.info": "Info",
|
||||
"ui.toast.warning": "Warning",
|
||||
"ui.toast.error": "Error",
|
||||
"ui.toast.dismiss": "Dismiss",
|
||||
"ui.toast.undo": "Undo",
|
||||
|
||||
"ui.actions.save": "Save",
|
||||
"ui.actions.saving": "Saving...",
|
||||
"ui.actions.saved": "Saved",
|
||||
"ui.actions.cancel": "Cancel",
|
||||
"ui.actions.confirm": "Confirm",
|
||||
"ui.actions.delete": "Delete",
|
||||
"ui.actions.deleting": "Deleting...",
|
||||
"ui.actions.deleted": "Deleted",
|
||||
"ui.actions.submit": "Submit",
|
||||
"ui.actions.submitting": "Submitting...",
|
||||
"ui.actions.submitted": "Submitted",
|
||||
"ui.actions.close": "Close",
|
||||
"ui.actions.expand": "Expand",
|
||||
"ui.actions.collapse": "Collapse",
|
||||
"ui.actions.show_more": "Show more",
|
||||
"ui.actions.show_less": "Show less",
|
||||
"ui.actions.retry": "Retry",
|
||||
"ui.actions.refresh": "Refresh",
|
||||
"ui.actions.export": "Export",
|
||||
"ui.actions.search": "Search",
|
||||
"ui.actions.clear": "Clear",
|
||||
"ui.actions.view": "View",
|
||||
"ui.actions.dismiss": "Dismiss",
|
||||
"ui.actions.show": "Show",
|
||||
"ui.actions.hide": "Hide",
|
||||
"ui.actions.sign_in": "Sign in",
|
||||
"ui.actions.back_to_list": "Back to list",
|
||||
"ui.actions.load_more": "Load more",
|
||||
|
||||
"ui.labels.all": "All",
|
||||
"ui.labels.title": "Title",
|
||||
"ui.labels.description": "Description",
|
||||
"ui.labels.status": "Status",
|
||||
"ui.labels.score": "Score",
|
||||
"ui.labels.severity": "Severity",
|
||||
"ui.labels.details": "Details",
|
||||
"ui.labels.actions": "Actions",
|
||||
"ui.labels.type": "Type",
|
||||
"ui.labels.tags": "Tags",
|
||||
"ui.labels.filters": "Filters",
|
||||
"ui.labels.updated": "Updated",
|
||||
"ui.labels.showing": "Showing",
|
||||
"ui.labels.of": "of",
|
||||
"ui.labels.total": "Total",
|
||||
"ui.labels.not_applicable": "n/a",
|
||||
"ui.labels.selected": "selected",
|
||||
"ui.labels.last_updated": "Last updated:",
|
||||
"ui.labels.expires": "Expires",
|
||||
|
||||
"ui.validation.required": "This field is required.",
|
||||
"ui.validation.invalid": "Invalid value.",
|
||||
"ui.validation.too_long": "Maximum {max} characters allowed.",
|
||||
"ui.validation.too_short": "Minimum {min} characters required.",
|
||||
"ui.validation.invalid_email": "Please enter a valid email address.",
|
||||
"ui.validation.invalid_url": "Please enter a valid URL.",
|
||||
|
||||
"ui.a11y.loading": "Content is loading.",
|
||||
"ui.a11y.loaded": "Content loaded.",
|
||||
"ui.a11y.error": "An error occurred.",
|
||||
"ui.a11y.expanded": "Expanded",
|
||||
"ui.a11y.collapsed": "Collapsed",
|
||||
"ui.a11y.selected": "Selected",
|
||||
"ui.a11y.deselected": "Deselected",
|
||||
"ui.a11y.required": "Required field",
|
||||
"ui.a11y.optional": "Optional",
|
||||
|
||||
"ui.motion.reduced": "Animations reduced.",
|
||||
"ui.motion.enabled": "Animations enabled.",
|
||||
|
||||
"ui.auth.fresh_active": "Fresh auth: Active",
|
||||
"ui.auth.fresh_stale": "Fresh auth: Stale",
|
||||
"ui.locale.label": "Language",
|
||||
"ui.locale.en_us": "English (US)",
|
||||
"ui.locale.de_de": "German (Germany)",
|
||||
"ui.locale.bg_bg": "Bulgarian (Bulgaria)",
|
||||
"ui.locale.ru_ru": "Russian (Russia)",
|
||||
"ui.locale.es_es": "Spanish (Spain)",
|
||||
"ui.locale.fr_fr": "French (France)",
|
||||
"ui.locale.zh_tw": "Chinese Traditional (Taiwan)",
|
||||
"ui.locale.zh_cn": "Chinese Simplified (China)",
|
||||
"ui.locale.uk_ua": "Ukrainian (Ukraine)",
|
||||
"ui.settings.language.title": "Yuyan",
|
||||
"ui.settings.language.subtitle": "Shezhi nin pianhao de kongzhi tai yuyan.",
|
||||
"ui.settings.language.description": "Biangeng hui liji shengxiao zai UI.",
|
||||
"ui.settings.language.selector_label": "Pianhao yuyan",
|
||||
"ui.settings.language.persisted": "Yijing baocun dao zhanghu bing gong CLI chongyong.",
|
||||
"ui.settings.language.persisted_error": "Yijing benji baocun, dan zhanghu tongbu shibai.",
|
||||
"ui.settings.language.sign_in_hint": "Qing dengru yi jiang ci pianhao tongbu dao CLI.",
|
||||
|
||||
"ui.first_signal.label": "First signal",
|
||||
"ui.first_signal.run_prefix": "Run:",
|
||||
"ui.first_signal.live": "Live",
|
||||
"ui.first_signal.polling": "Polling",
|
||||
"ui.first_signal.range_prefix": "Range",
|
||||
"ui.first_signal.range_separator": "\u2013",
|
||||
"ui.first_signal.stage_separator": " \u00b7 ",
|
||||
"ui.first_signal.waiting": "Waiting for first signal\u2026",
|
||||
"ui.first_signal.not_available": "Signal not available yet.",
|
||||
"ui.first_signal.offline": "Offline. Last known signal may be stale.",
|
||||
"ui.first_signal.failed": "Failed to load signal.",
|
||||
"ui.first_signal.retry": "Retry",
|
||||
"ui.first_signal.try_again": "Try again",
|
||||
"ui.first_signal.kind.queued": "Queued",
|
||||
"ui.first_signal.kind.started": "Started",
|
||||
"ui.first_signal.kind.phase": "In progress",
|
||||
"ui.first_signal.kind.blocked": "Blocked",
|
||||
"ui.first_signal.kind.failed": "Failed",
|
||||
"ui.first_signal.kind.succeeded": "Succeeded",
|
||||
"ui.first_signal.kind.canceled": "Canceled",
|
||||
"ui.first_signal.kind.unavailable": "Unavailable",
|
||||
"ui.first_signal.kind.unknown": "Signal",
|
||||
"ui.first_signal.stage.resolve": "Resolving",
|
||||
"ui.first_signal.stage.fetch": "Fetching",
|
||||
"ui.first_signal.stage.restore": "Restoring",
|
||||
"ui.first_signal.stage.analyze": "Analyzing",
|
||||
"ui.first_signal.stage.policy": "Evaluating policy",
|
||||
"ui.first_signal.stage.report": "Generating report",
|
||||
"ui.first_signal.stage.unknown": "Processing",
|
||||
"ui.first_signal.aria.card_label": "First signal status",
|
||||
|
||||
"ui.severity.critical": "Critical",
|
||||
"ui.severity.high": "High",
|
||||
"ui.severity.medium": "Medium",
|
||||
"ui.severity.low": "Low",
|
||||
"ui.severity.info": "Info",
|
||||
"ui.severity.none": "None",
|
||||
|
||||
"ui.release_orchestrator.title": "Release Orchestrator",
|
||||
"ui.release_orchestrator.subtitle": "Pipeline overview and release management",
|
||||
"ui.release_orchestrator.pipeline_runs": "Pipeline Runs",
|
||||
"ui.release_orchestrator.refresh_dashboard": "Refresh dashboard",
|
||||
|
||||
"ui.risk_dashboard.eyebrow": "Gateway \u00b7 Risk",
|
||||
"ui.risk_dashboard.title": "Risk Profiles",
|
||||
"ui.risk_dashboard.subtitle": "Tenant-scoped risk posture with deterministic ordering.",
|
||||
"ui.risk_dashboard.up_to_date": "Up to date",
|
||||
"ui.risk_dashboard.last_computation": "Last Computation",
|
||||
"ui.risk_dashboard.search_placeholder": "Title contains",
|
||||
"ui.risk_dashboard.evaluated": "Evaluated",
|
||||
"ui.risk_dashboard.risks_suffix": "risks.",
|
||||
"ui.risk_dashboard.error_unable_to_load": "Unable to load risk profiles.",
|
||||
"ui.risk_dashboard.no_risks_found": "No risks found for current filters.",
|
||||
"ui.risk_dashboard.loading_risks": "Loading risks\u2026",
|
||||
|
||||
"ui.findings.title": "Findings",
|
||||
"ui.findings.search_placeholder": "Search findings...",
|
||||
"ui.findings.clear_filters": "Clear Filters",
|
||||
"ui.findings.bulk_triage": "Bulk Triage",
|
||||
"ui.findings.export_all": "Export all findings",
|
||||
"ui.findings.export_selected": "Export selected findings",
|
||||
"ui.findings.select_all": "Select all findings",
|
||||
"ui.findings.trust": "Trust",
|
||||
"ui.findings.advisory": "Advisory",
|
||||
"ui.findings.package": "Package",
|
||||
"ui.findings.flags": "Flags",
|
||||
"ui.findings.why": "Why",
|
||||
"ui.findings.select": "Select",
|
||||
"ui.findings.no_findings": "No findings to display.",
|
||||
"ui.findings.no_match": "No findings match the current filters.",
|
||||
|
||||
"ui.sources_dashboard.title": "Sources Dashboard",
|
||||
"ui.sources_dashboard.verifying": "Verifying...",
|
||||
"ui.sources_dashboard.verify_24h": "Verify last 24h",
|
||||
"ui.sources_dashboard.loading_aoc": "Loading AOC metrics...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC Pass/Fail",
|
||||
"ui.sources_dashboard.pass_rate": "Pass Rate",
|
||||
"ui.sources_dashboard.passed": "Passed",
|
||||
"ui.sources_dashboard.failed": "Failed",
|
||||
"ui.sources_dashboard.recent_violations": "Recent Violations",
|
||||
"ui.sources_dashboard.no_violations": "No violations in time window",
|
||||
"ui.sources_dashboard.throughput_title": "Ingest Throughput",
|
||||
"ui.sources_dashboard.docs_per_min": "docs/min",
|
||||
"ui.sources_dashboard.avg_ms": "avg ms",
|
||||
"ui.sources_dashboard.p95_ms": "p95 ms",
|
||||
"ui.sources_dashboard.queue": "queue",
|
||||
"ui.sources_dashboard.errors": "errors",
|
||||
"ui.sources_dashboard.verification_complete": "Verification Complete",
|
||||
"ui.sources_dashboard.checked": "Checked:",
|
||||
"ui.sources_dashboard.violations": "violation(s)",
|
||||
"ui.sources_dashboard.field": "Field:",
|
||||
"ui.sources_dashboard.expected": "expected:",
|
||||
"ui.sources_dashboard.actual": "actual:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI equivalent:",
|
||||
"ui.sources_dashboard.data_from": "Data from",
|
||||
"ui.sources_dashboard.to": "to",
|
||||
"ui.sources_dashboard.hour_window": "h window",
|
||||
|
||||
"ui.timeline.title": "Timeline",
|
||||
"ui.timeline.event_timeline": "Event Timeline",
|
||||
"ui.timeline.refresh_timeline": "Refresh timeline",
|
||||
"ui.timeline.loading": "Loading timeline...",
|
||||
"ui.timeline.empty_state": "Enter a correlation ID to view the event timeline",
|
||||
"ui.timeline.critical_path": "Critical path analysis",
|
||||
"ui.timeline.causal_lanes": "Event causal lanes",
|
||||
"ui.timeline.load_more": "Load more events",
|
||||
"ui.timeline.event_details": "Event details",
|
||||
"ui.timeline.events": "events",
|
||||
|
||||
"ui.exception_center.title": "Exception Center",
|
||||
"ui.exception_center.list_view": "List view",
|
||||
"ui.exception_center.kanban_view": "Kanban view",
|
||||
"ui.exception_center.new_exception": "+ New Exception",
|
||||
"ui.exception_center.search_placeholder": "Search exceptions...",
|
||||
"ui.exception_center.type_vulnerability": "vulnerability",
|
||||
"ui.exception_center.type_license": "license",
|
||||
"ui.exception_center.type_policy": "policy",
|
||||
"ui.exception_center.type_entropy": "entropy",
|
||||
"ui.exception_center.type_determinism": "determinism",
|
||||
"ui.exception_center.expiring_soon": "Expiring soon",
|
||||
"ui.exception_center.clear_filters": "Clear filters",
|
||||
"_meta": {
|
||||
"locale": "zh-TW",
|
||||
"namespace": "ui",
|
||||
"version": "1.0"
|
||||
},
|
||||
"ui.loading.skeleton": "載入中...",
|
||||
"ui.loading.spinner": "請稍等...",
|
||||
"ui.loading.slow": "這比預期花費的時間更長.....",
|
||||
"ui.error.generic": "出了點問題。",
|
||||
"ui.error.network": "網路錯誤。檢查您的連線。",
|
||||
"ui.error.timeout": "請求超時。請再試一次。",
|
||||
"ui.error.not_found": "未找到請求的資源。",
|
||||
"ui.error.unauthorized": "您無權查看此內容。",
|
||||
"ui.error.server_error": "伺服器錯誤。請稍後重試。",
|
||||
"ui.error.try_again": "重試",
|
||||
"ui.error.go_back": "回去",
|
||||
"ui.offline.banner": "目前離線。",
|
||||
"ui.offline.description": "某些功能可能無法使用。",
|
||||
"ui.offline.reconnecting": "正在重新連接...",
|
||||
"ui.offline.reconnected": "已重新連線。",
|
||||
"ui.toast.success": "成功",
|
||||
"ui.toast.info": "資訊",
|
||||
"ui.toast.warning": "警告",
|
||||
"ui.toast.error": "錯誤",
|
||||
"ui.toast.dismiss": "關閉",
|
||||
"ui.toast.undo": "撤銷",
|
||||
"ui.actions.save": "儲存",
|
||||
"ui.actions.saving": "儲存中...",
|
||||
"ui.actions.saved": "已儲存",
|
||||
"ui.actions.cancel": "取消",
|
||||
"ui.actions.confirm": "確認",
|
||||
"ui.actions.delete": "刪除",
|
||||
"ui.actions.deleting": "正在刪除...",
|
||||
"ui.actions.deleted": "已刪除",
|
||||
"ui.actions.submit": "提交",
|
||||
"ui.actions.submitting": "正在提交...",
|
||||
"ui.actions.submitted": "已提交",
|
||||
"ui.actions.close": "關閉",
|
||||
"ui.actions.expand": "展開",
|
||||
"ui.actions.collapse": "收合",
|
||||
"ui.actions.show_more": "顯示更多",
|
||||
"ui.actions.show_less": "顯示較少",
|
||||
"ui.actions.retry": "重試",
|
||||
"ui.actions.refresh": "重新整理",
|
||||
"ui.actions.export": "匯出",
|
||||
"ui.actions.search": "搜尋",
|
||||
"ui.actions.clear": "清除",
|
||||
"ui.actions.view": "檢視",
|
||||
"ui.actions.dismiss": "關閉",
|
||||
"ui.actions.show": "顯示",
|
||||
"ui.actions.hide": "隱藏",
|
||||
"ui.actions.sign_in": "登入",
|
||||
"ui.actions.back_to_list": "返回列表",
|
||||
"ui.actions.load_more": "載入更多",
|
||||
"ui.labels.all": "全部",
|
||||
"ui.labels.title": "標題",
|
||||
"ui.labels.description": "描述",
|
||||
"ui.labels.status": "地位",
|
||||
"ui.labels.score": "分數",
|
||||
"ui.labels.severity": "嚴重性",
|
||||
"ui.labels.details": "細節",
|
||||
"ui.labels.actions": "行動",
|
||||
"ui.labels.type": "類型",
|
||||
"ui.labels.tags": "標籤",
|
||||
"ui.labels.filters": "過濾器",
|
||||
"ui.labels.updated": "已更新",
|
||||
"ui.labels.showing": "顯示中",
|
||||
"ui.labels.of": "的",
|
||||
"ui.labels.total": "全部的",
|
||||
"ui.labels.not_applicable": "不適用",
|
||||
"ui.labels.selected": "已選擇",
|
||||
"ui.labels.last_updated": "最後更新:",
|
||||
"ui.labels.expires": "過期",
|
||||
"ui.validation.required": "此欄位是必需的。",
|
||||
"ui.validation.invalid": "無效值。",
|
||||
"ui.validation.too_long": "允許的最大字元數為 {max}。",
|
||||
"ui.validation.too_short": "最少需要 {min} 個字元。",
|
||||
"ui.validation.invalid_email": "請輸入有效的電子郵件地址。",
|
||||
"ui.validation.invalid_url": "請輸入有效的網址。",
|
||||
"ui.a11y.loading": "內容正在載入。",
|
||||
"ui.a11y.loaded": "內容已載入。",
|
||||
"ui.a11y.error": "發生錯誤。",
|
||||
"ui.a11y.expanded": "擴充",
|
||||
"ui.a11y.collapsed": "倒塌",
|
||||
"ui.a11y.selected": "已選擇",
|
||||
"ui.a11y.deselected": "取消選擇",
|
||||
"ui.a11y.required": "必填字段",
|
||||
"ui.a11y.optional": "選修的",
|
||||
"ui.motion.reduced": "動畫減少。",
|
||||
"ui.motion.enabled": "動畫已啟用。",
|
||||
"ui.auth.fresh_active": "新鮮授權:活躍",
|
||||
"ui.auth.fresh_stale": "新鮮授權:陳舊",
|
||||
"ui.locale.label": "語言",
|
||||
"ui.locale.en_us": "英語(美國)",
|
||||
"ui.locale.de_de": "德語(德國)",
|
||||
"ui.locale.bg_bg": "保加利亞語(保加利亞)",
|
||||
"ui.locale.ru_ru": "俄語(俄羅斯)",
|
||||
"ui.locale.es_es": "西班牙語(西班牙)",
|
||||
"ui.locale.fr_fr": "法語(法國)",
|
||||
"ui.locale.zh_tw": "繁體中文(台灣)",
|
||||
"ui.locale.zh_cn": "簡體中文(中國)",
|
||||
"ui.locale.uk_ua": "烏克蘭語(烏克蘭)",
|
||||
"ui.settings.language.title": "語言",
|
||||
"ui.settings.language.subtitle": "設定主控台的偏好語言。",
|
||||
"ui.settings.language.description": "變更會立即套用到介面。",
|
||||
"ui.settings.language.selector_label": "偏好語言",
|
||||
"ui.settings.language.persisted": "已儲存到你的帳戶,並在 CLI 中重用。",
|
||||
"ui.settings.language.persisted_error": "已在本機儲存,但帳戶同步失敗。",
|
||||
"ui.settings.language.sign_in_hint": "請登入以將此設定同步到 CLI。",
|
||||
"ui.first_signal.label": "首個訊號",
|
||||
"ui.first_signal.run_prefix": "執行:",
|
||||
"ui.first_signal.live": "即時",
|
||||
"ui.first_signal.polling": "輪詢",
|
||||
"ui.first_signal.range_prefix": "範圍",
|
||||
"ui.first_signal.range_separator": "–",
|
||||
"ui.first_signal.stage_separator": " · ",
|
||||
"ui.first_signal.waiting": "等待第一個訊號…",
|
||||
"ui.first_signal.not_available": "信號尚未可用。",
|
||||
"ui.first_signal.offline": "離線。最後已知的訊號可能已過時。",
|
||||
"ui.first_signal.failed": "無法加載信號。",
|
||||
"ui.first_signal.retry": "重試",
|
||||
"ui.first_signal.try_again": "重試",
|
||||
"ui.first_signal.kind.queued": "佇列中",
|
||||
"ui.first_signal.kind.started": "已開始",
|
||||
"ui.first_signal.kind.phase": "進行中",
|
||||
"ui.first_signal.kind.blocked": "已封鎖",
|
||||
"ui.first_signal.kind.failed": "失敗",
|
||||
"ui.first_signal.kind.succeeded": "已成功",
|
||||
"ui.first_signal.kind.canceled": "已取消",
|
||||
"ui.first_signal.kind.unavailable": "不可用",
|
||||
"ui.first_signal.kind.unknown": "未知",
|
||||
"ui.first_signal.stage.resolve": "解析中",
|
||||
"ui.first_signal.stage.fetch": "取得中",
|
||||
"ui.first_signal.stage.restore": "正在恢復",
|
||||
"ui.first_signal.stage.analyze": "分析中",
|
||||
"ui.first_signal.stage.policy": "政策評估",
|
||||
"ui.first_signal.stage.report": "產生報告",
|
||||
"ui.first_signal.stage.unknown": "處理中",
|
||||
"ui.first_signal.aria.card_label": "第一訊號狀態",
|
||||
"ui.severity.critical": "批判的",
|
||||
"ui.severity.high": "高的",
|
||||
"ui.severity.medium": "中等的",
|
||||
"ui.severity.low": "低的",
|
||||
"ui.severity.info": "資訊",
|
||||
"ui.severity.none": "無",
|
||||
"ui.release_orchestrator.title": "發佈編排器",
|
||||
"ui.release_orchestrator.subtitle": "管道概述和發布管理",
|
||||
"ui.release_orchestrator.pipeline_runs": "管道運行",
|
||||
"ui.release_orchestrator.refresh_dashboard": "刷新儀表板",
|
||||
"ui.risk_dashboard.eyebrow": "閘道 · 風險",
|
||||
"ui.risk_dashboard.title": "風險概況",
|
||||
"ui.risk_dashboard.subtitle": "按租戶範圍並採用確定性排序的風險態勢。",
|
||||
"ui.risk_dashboard.up_to_date": "最新",
|
||||
"ui.risk_dashboard.last_computation": "最後計算",
|
||||
"ui.risk_dashboard.search_placeholder": "標題包含",
|
||||
"ui.risk_dashboard.evaluated": "已評估",
|
||||
"ui.risk_dashboard.risks_suffix": "風險。",
|
||||
"ui.risk_dashboard.error_unable_to_load": "無法載入風險概況。",
|
||||
"ui.risk_dashboard.no_risks_found": "目前的過濾器未發現任何風險。",
|
||||
"ui.risk_dashboard.loading_risks": "正在載入風險…",
|
||||
"ui.findings.title": "安全發現",
|
||||
"ui.findings.search_placeholder": "搜尋發現...",
|
||||
"ui.findings.clear_filters": "清除過濾器",
|
||||
"ui.findings.bulk_triage": "批量分類",
|
||||
"ui.findings.export_all": "匯出所有結果",
|
||||
"ui.findings.export_selected": "匯出選定的結果",
|
||||
"ui.findings.select_all": "選擇所有結果",
|
||||
"ui.findings.trust": "可信度",
|
||||
"ui.findings.advisory": "安全公告",
|
||||
"ui.findings.package": "套件",
|
||||
"ui.findings.flags": "標記",
|
||||
"ui.findings.why": "原因",
|
||||
"ui.findings.select": "選擇",
|
||||
"ui.findings.no_findings": "沒有可顯示的結果。",
|
||||
"ui.findings.no_match": "沒有發現與當前過濾器匹配的結果。",
|
||||
"ui.sources_dashboard.title": "來源儀表板",
|
||||
"ui.sources_dashboard.verifying": "正在驗證...",
|
||||
"ui.sources_dashboard.verify_24h": "驗證最近 24 小時",
|
||||
"ui.sources_dashboard.loading_aoc": "正在載入 AOC 指標...",
|
||||
"ui.sources_dashboard.pass_fail_title": "AOC 通過/失敗",
|
||||
"ui.sources_dashboard.pass_rate": "通過率",
|
||||
"ui.sources_dashboard.passed": "通過",
|
||||
"ui.sources_dashboard.failed": "失敗",
|
||||
"ui.sources_dashboard.recent_violations": "最近的違規行為",
|
||||
"ui.sources_dashboard.no_violations": "時間窗口內無違規行為",
|
||||
"ui.sources_dashboard.throughput_title": "攝取吞吐量",
|
||||
"ui.sources_dashboard.docs_per_min": "文檔/分鐘",
|
||||
"ui.sources_dashboard.avg_ms": "平均毫秒數",
|
||||
"ui.sources_dashboard.p95_ms": "p95毫秒",
|
||||
"ui.sources_dashboard.queue": "佇列",
|
||||
"ui.sources_dashboard.errors": "錯誤",
|
||||
"ui.sources_dashboard.verification_complete": "驗證完成",
|
||||
"ui.sources_dashboard.checked": "已檢查:",
|
||||
"ui.sources_dashboard.violations": "違規行為",
|
||||
"ui.sources_dashboard.field": "欄位:",
|
||||
"ui.sources_dashboard.expected": "預期的:",
|
||||
"ui.sources_dashboard.actual": "實際:",
|
||||
"ui.sources_dashboard.cli_equivalent": "CLI 等效項:",
|
||||
"ui.sources_dashboard.data_from": "數據來自",
|
||||
"ui.sources_dashboard.to": "到",
|
||||
"ui.sources_dashboard.hour_window": "小時視窗",
|
||||
"ui.timeline.title": "時間軸",
|
||||
"ui.timeline.event_timeline": "事件時間表",
|
||||
"ui.timeline.refresh_timeline": "刷新時間軸",
|
||||
"ui.timeline.loading": "載入時間軸...",
|
||||
"ui.timeline.empty_state": "輸入關聯 ID 以查看事件時間軸",
|
||||
"ui.timeline.critical_path": "關鍵路徑分析",
|
||||
"ui.timeline.causal_lanes": "事件因果車道",
|
||||
"ui.timeline.load_more": "載入更多事件",
|
||||
"ui.timeline.event_details": "活動詳情",
|
||||
"ui.timeline.events": "事件",
|
||||
"ui.exception_center.title": "異常中心",
|
||||
"ui.exception_center.list_view": "清單視圖",
|
||||
"ui.exception_center.kanban_view": "看板視圖",
|
||||
"ui.exception_center.new_exception": "+ 新異常",
|
||||
"ui.exception_center.search_placeholder": "搜尋例外...",
|
||||
"ui.exception_center.type_vulnerability": "漏洞",
|
||||
"ui.exception_center.type_license": "授權",
|
||||
"ui.exception_center.type_policy": "策略",
|
||||
"ui.exception_center.type_entropy": "熵",
|
||||
"ui.exception_center.type_determinism": "確定性",
|
||||
"ui.exception_center.expiring_soon": "即將到期",
|
||||
"ui.exception_center.clear_filters": "清除過濾器",
|
||||
"ui.exception_center.audit_label": "[A]",
|
||||
"ui.exception_center.audit_title": "View audit log",
|
||||
"ui.exception_center.no_exceptions": "No exceptions match the current filters",
|
||||
"ui.exception_center.column_empty": "No exceptions",
|
||||
"ui.exception_center.exceptions_suffix": "exceptions",
|
||||
|
||||
"ui.evidence_thread.back_to_list": "Back to list",
|
||||
"ui.evidence_thread.title_default": "Evidence Thread",
|
||||
"ui.evidence_thread.copy_digest": "Copy full digest",
|
||||
"ui.evidence_thread.risk_label": "Risk:",
|
||||
"ui.evidence_thread.nodes": "nodes",
|
||||
"ui.evidence_thread.loading": "Loading evidence thread...",
|
||||
"ui.evidence_thread.graph_tab": "Graph",
|
||||
"ui.evidence_thread.timeline_tab": "Timeline",
|
||||
"ui.evidence_thread.transcript_tab": "Transcript",
|
||||
"ui.evidence_thread.not_found": "No evidence thread found for this artifact.",
|
||||
|
||||
"ui.vulnerability_detail.eyebrow": "Vulnerability",
|
||||
"ui.exception_center.audit_title": "查看審核日誌",
|
||||
"ui.exception_center.no_exceptions": "沒有與當前過濾器匹配的異常",
|
||||
"ui.exception_center.column_empty": "目前沒有例外",
|
||||
"ui.exception_center.exceptions_suffix": "例外情況",
|
||||
"ui.evidence_thread.back_to_list": "返回列表",
|
||||
"ui.evidence_thread.title_default": "證據線索",
|
||||
"ui.evidence_thread.copy_digest": "複製完整摘要",
|
||||
"ui.evidence_thread.risk_label": "風險:",
|
||||
"ui.evidence_thread.nodes": "節點",
|
||||
"ui.evidence_thread.loading": "正在加載證據線程...",
|
||||
"ui.evidence_thread.graph_tab": "圖形",
|
||||
"ui.evidence_thread.timeline_tab": "時間軸",
|
||||
"ui.evidence_thread.transcript_tab": "成績單",
|
||||
"ui.evidence_thread.not_found": "沒有找到該文物的證據線索。",
|
||||
"ui.vulnerability_detail.eyebrow": "漏洞",
|
||||
"ui.vulnerability_detail.cvss": "CVSS",
|
||||
"ui.vulnerability_detail.impact_first": "Impact First",
|
||||
"ui.vulnerability_detail.impact_first": "影響第一",
|
||||
"ui.vulnerability_detail.epss": "EPSS",
|
||||
"ui.vulnerability_detail.kev": "KEV",
|
||||
"ui.vulnerability_detail.kev_listed": "Listed",
|
||||
"ui.vulnerability_detail.kev_not_listed": "Not listed",
|
||||
"ui.vulnerability_detail.reachability": "Reachability",
|
||||
"ui.vulnerability_detail.blast_radius": "Blast Radius",
|
||||
"ui.vulnerability_detail.assets": "assets",
|
||||
"ui.vulnerability_detail.binary_resolution": "Binary Resolution",
|
||||
"ui.vulnerability_detail.evidence_suffix": "evidence",
|
||||
"ui.vulnerability_detail.fingerprint_note": "This binary was identified as patched using fingerprint analysis, not just version matching.",
|
||||
"ui.vulnerability_detail.affected_components": "Affected Components",
|
||||
"ui.vulnerability_detail.fix": "fix",
|
||||
"ui.vulnerability_detail.evidence_tree": "Evidence Tree and Citation Links",
|
||||
"ui.vulnerability_detail.evidence_explorer": "evidence explorer",
|
||||
"ui.vulnerability_detail.references": "References",
|
||||
"ui.vulnerability_detail.back_to_risk": "Back to Risk"
|
||||
"ui.vulnerability_detail.kev": "凱夫",
|
||||
"ui.vulnerability_detail.kev_listed": "上市",
|
||||
"ui.vulnerability_detail.kev_not_listed": "未列出",
|
||||
"ui.vulnerability_detail.reachability": "可及性",
|
||||
"ui.vulnerability_detail.blast_radius": "爆炸半徑",
|
||||
"ui.vulnerability_detail.assets": "資產",
|
||||
"ui.vulnerability_detail.binary_resolution": "二進制分辨率",
|
||||
"ui.vulnerability_detail.evidence_suffix": "證據",
|
||||
"ui.vulnerability_detail.fingerprint_note": "此二進位檔案透過指紋分析(而不僅僅是版本匹配)被識別為已修補。",
|
||||
"ui.vulnerability_detail.affected_components": "受影響的組件",
|
||||
"ui.vulnerability_detail.fix": "使固定",
|
||||
"ui.vulnerability_detail.evidence_tree": "證據樹和引文鏈接",
|
||||
"ui.vulnerability_detail.evidence_explorer": "證據探索者",
|
||||
"ui.vulnerability_detail.references": "參考",
|
||||
"ui.vulnerability_detail.back_to_risk": "回到風險"
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ using StellaOps.Unknowns.Persistence.Postgres;
|
||||
using StellaOps.VexHub.Persistence.Postgres;
|
||||
using StellaOps.VexLens.Persistence.Postgres;
|
||||
using StellaOps.Findings.Ledger.Infrastructure.Postgres;
|
||||
using StellaOps.Orchestrator.Infrastructure.Postgres;
|
||||
using StellaOps.JobEngine.Infrastructure.Postgres;
|
||||
|
||||
namespace StellaOps.Platform.Database;
|
||||
|
||||
@@ -283,7 +283,7 @@ public sealed class OrchestratorMigrationModulePlugin : IMigrationModulePlugin
|
||||
public MigrationModuleInfo Module { get; } = new(
|
||||
name: "Orchestrator",
|
||||
schemaName: "orchestrator",
|
||||
migrationsAssembly: typeof(OrchestratorDataSource).Assembly);
|
||||
migrationsAssembly: typeof(JobEngineDataSource).Assembly);
|
||||
}
|
||||
|
||||
public sealed class FindingsLedgerMigrationModulePlugin : IMigrationModulePlugin
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<ProjectReference Include="..\..\..\Concelier\__Libraries\StellaOps.Concelier.Persistence\StellaOps.Concelier.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\Graph\__Libraries\StellaOps.Graph.Indexer.Persistence\StellaOps.Graph.Indexer.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Evidence.Persistence\StellaOps.Evidence.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\Excititor\__Libraries\StellaOps.Excititor.Persistence\StellaOps.Excititor.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\Concelier\__Libraries\StellaOps.Excititor.Persistence\StellaOps.Excititor.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\Notify\__Libraries\StellaOps.Notify.Persistence\StellaOps.Notify.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\Plugin\StellaOps.Plugin.Registry\StellaOps.Plugin.Registry.csproj" />
|
||||
<ProjectReference Include="..\..\..\Policy\__Libraries\StellaOps.Policy.Persistence\StellaOps.Policy.Persistence.csproj" />
|
||||
@@ -29,9 +29,9 @@
|
||||
<ProjectReference Include="..\..\..\Scanner\__Libraries\StellaOps.Scanner.Storage\StellaOps.Scanner.Storage.csproj" />
|
||||
<ProjectReference Include="..\..\..\Signals\__Libraries\StellaOps.Signals.Persistence\StellaOps.Signals.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\Scanner\__Libraries\StellaOps.Scanner.Triage\StellaOps.Scanner.Triage.csproj" />
|
||||
<ProjectReference Include="..\..\..\Scheduler\__Libraries\StellaOps.Scheduler.Persistence\StellaOps.Scheduler.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\JobEngine\StellaOps.Scheduler.__Libraries\StellaOps.Scheduler.Persistence\StellaOps.Scheduler.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\Timeline\__Libraries\StellaOps.Timeline.Core\StellaOps.Timeline.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\TimelineIndexer\StellaOps.TimelineIndexer\StellaOps.TimelineIndexer.Infrastructure\StellaOps.TimelineIndexer.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\..\..\Timeline\__Libraries\StellaOps.TimelineIndexer.Infrastructure\StellaOps.TimelineIndexer.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\..\..\Unknowns\__Libraries\StellaOps.Unknowns.Persistence\StellaOps.Unknowns.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\VexHub\__Libraries\StellaOps.VexHub.Persistence\StellaOps.VexHub.Persistence.csproj" />
|
||||
<ProjectReference Include="..\..\..\VexLens\StellaOps.VexLens.Persistence\StellaOps.VexLens.Persistence.csproj" />
|
||||
@@ -42,7 +42,7 @@
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Eventing\StellaOps.Eventing.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Infrastructure.Postgres\StellaOps.Infrastructure.Postgres.csproj" />
|
||||
<ProjectReference Include="..\..\..\Findings\StellaOps.Findings.Ledger\StellaOps.Findings.Ledger.csproj" />
|
||||
<ProjectReference Include="..\..\..\Orchestrator\StellaOps.Orchestrator\StellaOps.Orchestrator.Infrastructure\StellaOps.Orchestrator.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\..\..\JobEngine\StellaOps.JobEngine\StellaOps.JobEngine.Infrastructure\StellaOps.JobEngine.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -376,9 +376,9 @@ public sealed class AnalyticsIngestionEdgeCaseTests
|
||||
[Fact]
|
||||
public void ResolveArtifactVersion_HandlesDigestInTag()
|
||||
{
|
||||
var envelope = new OrchestratorEventEnvelope
|
||||
var envelope = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Image = "registry.example.com/repo@sha256:abc123"
|
||||
}
|
||||
@@ -393,9 +393,9 @@ public sealed class AnalyticsIngestionEdgeCaseTests
|
||||
[Fact]
|
||||
public void ResolveArtifactVersion_HandlesPortInRegistry()
|
||||
{
|
||||
var envelope = new OrchestratorEventEnvelope
|
||||
var envelope = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Image = "registry.example.com:5000/repo:v1.2.3"
|
||||
}
|
||||
@@ -409,9 +409,9 @@ public sealed class AnalyticsIngestionEdgeCaseTests
|
||||
[Fact]
|
||||
public void ResolveArtifactVersion_ReturnsNullForPortOnly()
|
||||
{
|
||||
var envelope = new OrchestratorEventEnvelope
|
||||
var envelope = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Image = "registry.example.com:5000/repo"
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ public sealed class AnalyticsIngestionHelpersTests
|
||||
[Fact]
|
||||
public void ResolveArtifactVersion_ParsesImageTag()
|
||||
{
|
||||
var envelope = new OrchestratorEventEnvelope
|
||||
var envelope = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Image = "registry.example.com/repo:1.2.3"
|
||||
}
|
||||
@@ -53,9 +53,9 @@ public sealed class AnalyticsIngestionHelpersTests
|
||||
[Fact]
|
||||
public void ResolveArtifactVersion_ReturnsNullWhenMissingTag()
|
||||
{
|
||||
var envelope = new OrchestratorEventEnvelope
|
||||
var envelope = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Image = "registry.example.com/repo"
|
||||
}
|
||||
@@ -89,26 +89,26 @@ public sealed class AnalyticsIngestionHelpersTests
|
||||
[Fact]
|
||||
public void ResolveArtifactName_PrefersRepoThenImageThenComponent()
|
||||
{
|
||||
var withRepo = new OrchestratorEventEnvelope
|
||||
var withRepo = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Repo = "github.com/stellaops/core",
|
||||
Image = "registry.example.com/stellaops/core:1.2.3",
|
||||
Component = "stellaops-core"
|
||||
}
|
||||
};
|
||||
var withImage = new OrchestratorEventEnvelope
|
||||
var withImage = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Image = "registry.example.com/stellaops/console:2.0.0",
|
||||
Component = "stellaops-console"
|
||||
}
|
||||
};
|
||||
var withComponent = new OrchestratorEventEnvelope
|
||||
var withComponent = new JobEngineEventEnvelope
|
||||
{
|
||||
Scope = new OrchestratorEventScope
|
||||
Scope = new JobEngineEventScope
|
||||
{
|
||||
Component = "stellaops-agent"
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public sealed class AnalyticsIngestionHelpersTests
|
||||
Assert.Equal("github.com/stellaops/core", AnalyticsIngestionService.ResolveArtifactName(withRepo));
|
||||
Assert.Equal("registry.example.com/stellaops/console:2.0.0", AnalyticsIngestionService.ResolveArtifactName(withImage));
|
||||
Assert.Equal("stellaops-agent", AnalyticsIngestionService.ResolveArtifactName(withComponent));
|
||||
Assert.Equal("unknown", AnalyticsIngestionService.ResolveArtifactName(new OrchestratorEventEnvelope()));
|
||||
Assert.Equal("unknown", AnalyticsIngestionService.ResolveArtifactName(new JobEngineEventEnvelope()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -19,8 +19,8 @@ public sealed class ScannerPlatformEventsBehaviorTests
|
||||
[Fact]
|
||||
public void IsSupportedScannerEventKind_RecognizesReportReadyAndScanCompleted()
|
||||
{
|
||||
Assert.True(AnalyticsIngestionService.IsSupportedScannerEventKind(OrchestratorEventKinds.ScannerReportReady));
|
||||
Assert.True(AnalyticsIngestionService.IsSupportedScannerEventKind(OrchestratorEventKinds.ScannerScanCompleted));
|
||||
Assert.True(AnalyticsIngestionService.IsSupportedScannerEventKind(JobEngineEventKinds.ScannerReportReady));
|
||||
Assert.True(AnalyticsIngestionService.IsSupportedScannerEventKind(JobEngineEventKinds.ScannerScanCompleted));
|
||||
Assert.False(AnalyticsIngestionService.IsSupportedScannerEventKind("scanner.unknown"));
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public sealed class ScannerPlatformEventsBehaviorTests
|
||||
|
||||
var result = AnalyticsIngestionService.TryDeserializeScannerPayload(
|
||||
dsseElement,
|
||||
OrchestratorEventKinds.ScannerReportReady,
|
||||
JobEngineEventKinds.ScannerReportReady,
|
||||
SerializerOptions,
|
||||
out var parsed);
|
||||
|
||||
@@ -80,7 +80,7 @@ public sealed class ScannerPlatformEventsBehaviorTests
|
||||
|
||||
var result = AnalyticsIngestionService.TryDeserializeScannerPayload(
|
||||
completedElement,
|
||||
OrchestratorEventKinds.ScannerScanCompleted,
|
||||
JobEngineEventKinds.ScannerScanCompleted,
|
||||
SerializerOptions,
|
||||
out var parsed);
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ using StellaOps.Signals.EvidenceWeightedScore;
|
||||
using StellaOps.Signals.UnifiedScore;
|
||||
using StellaOps.Signals.UnifiedScore.Replay;
|
||||
using StellaOps.TestKit;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Platform.WebService.Tests;
|
||||
@@ -179,6 +181,26 @@ public sealed class ScoreEndpointsTests
|
||||
Assert.True(result.Value.ComputedAt > DateTimeOffset.UtcNow.AddMinutes(-1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EvaluateAsync_WithPartialSignals_ReturnsUnknownsAndProofReference()
|
||||
{
|
||||
var request = new ScoreEvaluateRequest
|
||||
{
|
||||
Signals = new SignalInputs
|
||||
{
|
||||
Reachability = 0.8
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _service.EvaluateAsync(_context, request);
|
||||
|
||||
Assert.NotNull(result.Value.Unknowns);
|
||||
Assert.Contains("runtime", result.Value.Unknowns!);
|
||||
Assert.Contains("backport", result.Value.Unknowns!);
|
||||
Assert.NotNull(result.Value.ProofRef);
|
||||
Assert.StartsWith("proof://score/", result.Value.ProofRef, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EvaluateAsync_DifferentTenants_ProduceDifferentScoreIds()
|
||||
{
|
||||
@@ -238,6 +260,49 @@ public sealed class ScoreEndpointsTests
|
||||
Assert.Null(result.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetExplanationAsync_NonExistent_ReturnsNull()
|
||||
{
|
||||
var result = await _service.GetExplanationAsync(_context, "sha256:missing");
|
||||
|
||||
Assert.Null(result.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetExplanationAsync_WithPersistedDigest_ReturnsCanonicalContract()
|
||||
{
|
||||
var record = new ScoreHistoryRecord
|
||||
{
|
||||
Id = "score_123",
|
||||
TenantId = "test-tenant",
|
||||
ProjectId = "proj-a",
|
||||
CveId = "CVE-2026-0001",
|
||||
Purl = "pkg:generic/demo@1.0.0",
|
||||
Score = 0.62m,
|
||||
Band = "Investigate",
|
||||
WeightsVersion = "v-test",
|
||||
SignalSnapshot = "{\"vex\":{\"isPresent\":true},\"epss\":{\"isPresent\":true},\"reachability\":{\"isPresent\":false},\"runtime\":{\"isPresent\":true},\"backport\":{\"isPresent\":false},\"sbom\":{\"isPresent\":true}}",
|
||||
ReplayDigest = "sha256:abc123",
|
||||
CreatedAt = DateTimeOffset.Parse("2026-02-26T12:00:00Z")
|
||||
};
|
||||
|
||||
_scoreHistoryStore
|
||||
.GetByReplayDigestAsync("sha256:abc123", "test-tenant", Arg.Any<CancellationToken>())
|
||||
.Returns(record);
|
||||
|
||||
var result = await _service.GetExplanationAsync(_context, "SHA256:ABC123");
|
||||
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Equal("score.explain.v1", result.Value.ContractVersion);
|
||||
Assert.Equal("sha256:abc123", result.Value.Digest);
|
||||
Assert.Equal("score_123", result.Value.ScoreId);
|
||||
Assert.Equal(62, result.Value.FinalScore);
|
||||
Assert.Equal("sha256:abc123", result.Value.DeterministicInputHash);
|
||||
Assert.Equal("/api/v1/score/score_123/replay", result.Value.ReplayLink);
|
||||
Assert.Equal(6, result.Value.Factors.Count);
|
||||
Assert.Equal(2, result.Value.Sources.Count);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TSF-005: ListWeightManifestsAsync
|
||||
@@ -348,7 +413,7 @@ public sealed class ScoreEndpointsTests
|
||||
{
|
||||
var request = new ScoreVerifyRequest
|
||||
{
|
||||
SignedReplayLogDsse = "eyJwYXlsb2FkIjoiZXlKMFpYTjBJam9pYUdWc2JHOGlmUT09In0=",
|
||||
SignedReplayLogDsse = CreateReplayEnvelope(),
|
||||
OriginalInputs = new ScoreVerifyInputs
|
||||
{
|
||||
Signals = new SignalInputs
|
||||
@@ -378,7 +443,7 @@ public sealed class ScoreEndpointsTests
|
||||
{
|
||||
var request = new ScoreVerifyRequest
|
||||
{
|
||||
SignedReplayLogDsse = "eyJwYXlsb2FkIjoiZXlKMFpYTjBJam9pYUdWc2JHOGlmUT09In0=",
|
||||
SignedReplayLogDsse = CreateReplayEnvelope(),
|
||||
OriginalInputs = null
|
||||
};
|
||||
|
||||
@@ -393,7 +458,7 @@ public sealed class ScoreEndpointsTests
|
||||
{
|
||||
var request = new ScoreVerifyRequest
|
||||
{
|
||||
SignedReplayLogDsse = "eyJwYXlsb2FkIjoiZXlKMFpYTjBJam9pYUdWc2JHOGlmUT09In0=",
|
||||
SignedReplayLogDsse = CreateReplayEnvelope(),
|
||||
OriginalInputs = new ScoreVerifyInputs
|
||||
{
|
||||
Signals = new SignalInputs { Reachability = 0.5 }
|
||||
@@ -411,7 +476,7 @@ public sealed class ScoreEndpointsTests
|
||||
{
|
||||
var request = new ScoreVerifyRequest
|
||||
{
|
||||
SignedReplayLogDsse = "eyJwYXlsb2FkIjoiZXlKMFpYTjBJam9pYUdWc2JHOGlmUT09In0=",
|
||||
SignedReplayLogDsse = CreateReplayEnvelope(),
|
||||
OriginalInputs = new ScoreVerifyInputs
|
||||
{
|
||||
Signals = new SignalInputs { Reachability = 0.5 },
|
||||
@@ -425,6 +490,48 @@ public sealed class ScoreEndpointsTests
|
||||
Assert.True(result.Value.Verified);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifyReplayAsync_WithMismatchedReplayPayload_ReturnsDeterministicDifferences()
|
||||
{
|
||||
var request = new ScoreVerifyRequest
|
||||
{
|
||||
SignedReplayLogDsse = CreateReplayEnvelope(finalScore: 99, ewsDigest: "sha256:does-not-match"),
|
||||
OriginalInputs = new ScoreVerifyInputs
|
||||
{
|
||||
Signals = new SignalInputs { Reachability = 0.5, Runtime = 0.5 }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _service.VerifyReplayAsync(_context, request);
|
||||
|
||||
Assert.False(result.Value.Verified);
|
||||
Assert.False(result.Value.ScoreMatches);
|
||||
Assert.False(result.Value.DigestMatches);
|
||||
Assert.NotNull(result.Value.Differences);
|
||||
Assert.Contains(result.Value.Differences!, diff => diff.Field == "final_score");
|
||||
Assert.Contains(result.Value.Differences!, diff => diff.Field == "ews_digest");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifyReplayAsync_WithMalformedEnvelope_ReturnsDeterministicEnvelopeError()
|
||||
{
|
||||
var request = new ScoreVerifyRequest
|
||||
{
|
||||
SignedReplayLogDsse = "not-base64",
|
||||
OriginalInputs = new ScoreVerifyInputs
|
||||
{
|
||||
Signals = new SignalInputs { Reachability = 0.5, Runtime = 0.5 }
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _service.VerifyReplayAsync(_context, request);
|
||||
|
||||
Assert.False(result.Value.Verified);
|
||||
Assert.NotNull(result.Value.Differences);
|
||||
var envelopeDifference = Assert.Single(result.Value.Differences!, diff => diff.Field == "signed_replay_log_dsse");
|
||||
Assert.Equal("valid_dsse_envelope", envelopeDifference.Expected);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region TSF-011: GetReplayAsync
|
||||
@@ -605,5 +712,28 @@ public sealed class ScoreEndpointsTests
|
||||
.Returns(result);
|
||||
}
|
||||
|
||||
private static string CreateReplayEnvelope(int? finalScore = null, string? ewsDigest = null)
|
||||
{
|
||||
var payload = new Dictionary<string, object?>();
|
||||
if (finalScore.HasValue)
|
||||
{
|
||||
payload["final_score"] = finalScore.Value;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ewsDigest))
|
||||
{
|
||||
payload["ews_digest"] = ewsDigest;
|
||||
}
|
||||
|
||||
var payloadBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(payload));
|
||||
var envelope = new Dictionary<string, object?>
|
||||
{
|
||||
["payloadType"] = "application/vnd.stellaops.score-replay+json",
|
||||
["payload"] = Convert.ToBase64String(payloadBytes)
|
||||
};
|
||||
|
||||
return Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(envelope)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user