sprints completion. new product advisories prepared

This commit is contained in:
master
2026-01-16 16:30:03 +02:00
parent a927d924e3
commit 4ca3ce8fb4
255 changed files with 42434 additions and 1020 deletions

View File

@@ -0,0 +1,494 @@
// -----------------------------------------------------------------------------
// BinaryIndexOpsModels.cs
// Sprint: SPRINT_20260112_007_BINIDX_binaryindex_user_config
// Task: BINIDX-OPS-02
// Description: Response models for BinaryIndex ops endpoints.
// -----------------------------------------------------------------------------
using System.Collections.Immutable;
using System.Text.Json.Serialization;
namespace StellaOps.BinaryIndex.Core.Configuration;
/// <summary>
/// Response for GET /api/v1/ops/binaryindex/health
/// </summary>
public sealed record BinaryIndexOpsHealthResponse
{
/// <summary>
/// Overall health status.
/// </summary>
[JsonPropertyName("status")]
public required string Status { get; init; }
/// <summary>
/// Timestamp of the health check (ISO-8601).
/// </summary>
[JsonPropertyName("timestamp")]
public required string Timestamp { get; init; }
/// <summary>
/// Component health details.
/// </summary>
[JsonPropertyName("components")]
public required BinaryIndexComponentHealth Components { get; init; }
/// <summary>
/// Lifter pool warmness status.
/// </summary>
[JsonPropertyName("lifterWarmness")]
public required BinaryIndexLifterWarmness LifterWarmness { get; init; }
/// <summary>
/// Service version.
/// </summary>
[JsonPropertyName("version")]
public required string Version { get; init; }
}
/// <summary>
/// Health status for individual components.
/// </summary>
public sealed record BinaryIndexComponentHealth
{
/// <summary>
/// Valkey cache health.
/// </summary>
[JsonPropertyName("valkey")]
public required ComponentHealthStatus Valkey { get; init; }
/// <summary>
/// PostgreSQL persistence health.
/// </summary>
[JsonPropertyName("postgresql")]
public required ComponentHealthStatus Postgresql { get; init; }
/// <summary>
/// B2R2 lifter pool health.
/// </summary>
[JsonPropertyName("lifterPool")]
public required ComponentHealthStatus LifterPool { get; init; }
}
/// <summary>
/// Health status for a single component.
/// </summary>
public sealed record ComponentHealthStatus
{
/// <summary>
/// Status: "healthy", "degraded", "unhealthy", or "unknown".
/// </summary>
[JsonPropertyName("status")]
public required string Status { get; init; }
/// <summary>
/// Optional message with details.
/// </summary>
[JsonPropertyName("message")]
public string? Message { get; init; }
/// <summary>
/// Response time in milliseconds.
/// </summary>
[JsonPropertyName("responseTimeMs")]
public long? ResponseTimeMs { get; init; }
}
/// <summary>
/// Lifter warmness status per ISA.
/// </summary>
public sealed record BinaryIndexLifterWarmness
{
/// <summary>
/// Whether warm preload is enabled.
/// </summary>
[JsonPropertyName("warmPreloadEnabled")]
public required bool WarmPreloadEnabled { get; init; }
/// <summary>
/// Warmness status by ISA.
/// </summary>
[JsonPropertyName("isas")]
public required ImmutableDictionary<string, IsaWarmness> Isas { get; init; }
}
/// <summary>
/// Warmness status for a single ISA.
/// </summary>
public sealed record IsaWarmness
{
/// <summary>
/// Whether the ISA is warmed up.
/// </summary>
[JsonPropertyName("isWarm")]
public required bool IsWarm { get; init; }
/// <summary>
/// Number of pooled lifters available.
/// </summary>
[JsonPropertyName("pooledCount")]
public required int PooledCount { get; init; }
/// <summary>
/// Maximum pool size for this ISA.
/// </summary>
[JsonPropertyName("maxPoolSize")]
public required int MaxPoolSize { get; init; }
}
/// <summary>
/// Response for POST /api/v1/ops/binaryindex/bench/run
/// </summary>
public sealed record BinaryIndexBenchResponse
{
/// <summary>
/// Bench run timestamp (ISO-8601).
/// </summary>
[JsonPropertyName("timestamp")]
public required string Timestamp { get; init; }
/// <summary>
/// Sample size used.
/// </summary>
[JsonPropertyName("sampleSize")]
public required int SampleSize { get; init; }
/// <summary>
/// Latency summary.
/// </summary>
[JsonPropertyName("latency")]
public required BenchLatencySummary Latency { get; init; }
/// <summary>
/// Per-operation breakdown.
/// </summary>
[JsonPropertyName("operations")]
public required ImmutableArray<BenchOperationResult> Operations { get; init; }
/// <summary>
/// Whether the bench completed successfully.
/// </summary>
[JsonPropertyName("success")]
public required bool Success { get; init; }
/// <summary>
/// Error message if bench failed.
/// </summary>
[JsonPropertyName("error")]
public string? Error { get; init; }
}
/// <summary>
/// Latency summary statistics.
/// </summary>
public sealed record BenchLatencySummary
{
/// <summary>
/// Minimum latency in milliseconds.
/// </summary>
[JsonPropertyName("minMs")]
public required double MinMs { get; init; }
/// <summary>
/// Maximum latency in milliseconds.
/// </summary>
[JsonPropertyName("maxMs")]
public required double MaxMs { get; init; }
/// <summary>
/// Mean latency in milliseconds.
/// </summary>
[JsonPropertyName("meanMs")]
public required double MeanMs { get; init; }
/// <summary>
/// P50 (median) latency in milliseconds.
/// </summary>
[JsonPropertyName("p50Ms")]
public required double P50Ms { get; init; }
/// <summary>
/// P95 latency in milliseconds.
/// </summary>
[JsonPropertyName("p95Ms")]
public required double P95Ms { get; init; }
/// <summary>
/// P99 latency in milliseconds.
/// </summary>
[JsonPropertyName("p99Ms")]
public required double P99Ms { get; init; }
}
/// <summary>
/// Result for a single bench operation.
/// </summary>
public sealed record BenchOperationResult
{
/// <summary>
/// Operation name.
/// </summary>
[JsonPropertyName("operation")]
public required string Operation { get; init; }
/// <summary>
/// Latency in milliseconds.
/// </summary>
[JsonPropertyName("latencyMs")]
public required double LatencyMs { get; init; }
/// <summary>
/// Whether the operation succeeded.
/// </summary>
[JsonPropertyName("success")]
public required bool Success { get; init; }
/// <summary>
/// ISA used for the operation.
/// </summary>
[JsonPropertyName("isa")]
public string? Isa { get; init; }
}
/// <summary>
/// Response for GET /api/v1/ops/binaryindex/cache
/// </summary>
public sealed record BinaryIndexFunctionCacheStats
{
/// <summary>
/// Timestamp of stats collection (ISO-8601).
/// </summary>
[JsonPropertyName("timestamp")]
public required string Timestamp { get; init; }
/// <summary>
/// Whether caching is enabled.
/// </summary>
[JsonPropertyName("enabled")]
public required bool Enabled { get; init; }
/// <summary>
/// Backend type (e.g., "Valkey", "Redis", "InMemory").
/// </summary>
[JsonPropertyName("backend")]
public required string Backend { get; init; }
/// <summary>
/// Total cache hits.
/// </summary>
[JsonPropertyName("hits")]
public required long Hits { get; init; }
/// <summary>
/// Total cache misses.
/// </summary>
[JsonPropertyName("misses")]
public required long Misses { get; init; }
/// <summary>
/// Total evictions.
/// </summary>
[JsonPropertyName("evictions")]
public required long Evictions { get; init; }
/// <summary>
/// Hit rate (0.0 to 1.0).
/// </summary>
[JsonPropertyName("hitRate")]
public required double HitRate { get; init; }
/// <summary>
/// Key prefix used.
/// </summary>
[JsonPropertyName("keyPrefix")]
public required string KeyPrefix { get; init; }
/// <summary>
/// Configured TTL.
/// </summary>
[JsonPropertyName("cacheTtl")]
public required string CacheTtl { get; init; }
/// <summary>
/// Estimated entry count (if available).
/// </summary>
[JsonPropertyName("estimatedEntries")]
public long? EstimatedEntries { get; init; }
/// <summary>
/// Estimated memory usage in bytes (if available).
/// </summary>
[JsonPropertyName("estimatedMemoryBytes")]
public long? EstimatedMemoryBytes { get; init; }
}
/// <summary>
/// Response for GET /api/v1/ops/binaryindex/config
/// </summary>
public sealed record BinaryIndexEffectiveConfig
{
/// <summary>
/// Timestamp of config snapshot (ISO-8601).
/// </summary>
[JsonPropertyName("timestamp")]
public required string Timestamp { get; init; }
/// <summary>
/// B2R2 pool configuration (sanitized).
/// </summary>
[JsonPropertyName("b2r2Pool")]
public required B2R2PoolConfigView B2R2Pool { get; init; }
/// <summary>
/// Semantic lifting configuration.
/// </summary>
[JsonPropertyName("semanticLifting")]
public required SemanticLiftingConfigView SemanticLifting { get; init; }
/// <summary>
/// Function cache configuration (sanitized).
/// </summary>
[JsonPropertyName("functionCache")]
public required FunctionCacheConfigView FunctionCache { get; init; }
/// <summary>
/// Persistence configuration (sanitized).
/// </summary>
[JsonPropertyName("persistence")]
public required PersistenceConfigView Persistence { get; init; }
/// <summary>
/// Backend versions.
/// </summary>
[JsonPropertyName("versions")]
public required BackendVersions Versions { get; init; }
}
/// <summary>
/// Sanitized view of B2R2 pool config.
/// </summary>
public sealed record B2R2PoolConfigView
{
[JsonPropertyName("maxPoolSizePerIsa")]
public required int MaxPoolSizePerIsa { get; init; }
[JsonPropertyName("warmPreloadEnabled")]
public required bool WarmPreloadEnabled { get; init; }
[JsonPropertyName("warmPreloadIsas")]
public required ImmutableArray<string> WarmPreloadIsas { get; init; }
[JsonPropertyName("acquireTimeoutSeconds")]
public required double AcquireTimeoutSeconds { get; init; }
[JsonPropertyName("metricsEnabled")]
public required bool MetricsEnabled { get; init; }
}
/// <summary>
/// Sanitized view of semantic lifting config.
/// </summary>
public sealed record SemanticLiftingConfigView
{
[JsonPropertyName("enabled")]
public required bool Enabled { get; init; }
[JsonPropertyName("b2r2Version")]
public required string B2R2Version { get; init; }
[JsonPropertyName("normalizationRecipeVersion")]
public required string NormalizationRecipeVersion { get; init; }
[JsonPropertyName("maxInstructionsPerFunction")]
public required int MaxInstructionsPerFunction { get; init; }
[JsonPropertyName("maxFunctionsPerBinary")]
public required int MaxFunctionsPerBinary { get; init; }
[JsonPropertyName("functionLiftTimeoutSeconds")]
public required double FunctionLiftTimeoutSeconds { get; init; }
[JsonPropertyName("deduplicationEnabled")]
public required bool DeduplicationEnabled { get; init; }
}
/// <summary>
/// Sanitized view of function cache config.
/// </summary>
public sealed record FunctionCacheConfigView
{
[JsonPropertyName("enabled")]
public required bool Enabled { get; init; }
[JsonPropertyName("backend")]
public required string Backend { get; init; }
[JsonPropertyName("keyPrefix")]
public required string KeyPrefix { get; init; }
[JsonPropertyName("cacheTtl")]
public required string CacheTtl { get; init; }
[JsonPropertyName("maxTtl")]
public required string MaxTtl { get; init; }
[JsonPropertyName("earlyExpiryEnabled")]
public required bool EarlyExpiryEnabled { get; init; }
[JsonPropertyName("earlyExpiryFactor")]
public required double EarlyExpiryFactor { get; init; }
[JsonPropertyName("maxEntrySizeBytes")]
public required int MaxEntrySizeBytes { get; init; }
}
/// <summary>
/// Sanitized view of persistence config.
/// </summary>
public sealed record PersistenceConfigView
{
[JsonPropertyName("enabled")]
public required bool Enabled { get; init; }
[JsonPropertyName("schema")]
public required string Schema { get; init; }
[JsonPropertyName("minPoolSize")]
public required int MinPoolSize { get; init; }
[JsonPropertyName("maxPoolSize")]
public required int MaxPoolSize { get; init; }
[JsonPropertyName("commandTimeoutSeconds")]
public required double CommandTimeoutSeconds { get; init; }
[JsonPropertyName("retryOnFailureEnabled")]
public required bool RetryOnFailureEnabled { get; init; }
[JsonPropertyName("maxRetryCount")]
public required int MaxRetryCount { get; init; }
[JsonPropertyName("batchSize")]
public required int BatchSize { get; init; }
}
/// <summary>
/// Backend version information.
/// </summary>
public sealed record BackendVersions
{
[JsonPropertyName("service")]
public required string Service { get; init; }
[JsonPropertyName("b2r2")]
public required string B2R2 { get; init; }
[JsonPropertyName("postgresql")]
public string? Postgresql { get; init; }
[JsonPropertyName("valkey")]
public string? Valkey { get; init; }
[JsonPropertyName("dotnet")]
public required string Dotnet { get; init; }
}

View File

@@ -0,0 +1,276 @@
// -----------------------------------------------------------------------------
// BinaryIndexOptions.cs
// Sprint: SPRINT_20260112_007_BINIDX_binaryindex_user_config
// Task: BINIDX-CONF-01
// Description: Unified configuration options for BinaryIndex services.
// -----------------------------------------------------------------------------
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
namespace StellaOps.BinaryIndex.Core.Configuration;
/// <summary>
/// Root configuration for BinaryIndex services.
/// </summary>
public sealed class BinaryIndexOptions
{
/// <summary>
/// Configuration section name.
/// </summary>
public const string SectionName = "StellaOps:BinaryIndex";
/// <summary>
/// B2R2 lifter pool configuration.
/// </summary>
public B2R2PoolOptions B2R2Pool { get; init; } = new();
/// <summary>
/// Semantic lifting configuration.
/// </summary>
public SemanticLiftingOptions SemanticLifting { get; init; } = new();
/// <summary>
/// Function cache (Valkey) configuration.
/// </summary>
public FunctionCacheOptions FunctionCache { get; init; } = new();
/// <summary>
/// PostgreSQL persistence configuration.
/// </summary>
public BinaryIndexPersistenceOptions Persistence { get; init; } = new();
/// <summary>
/// Operational settings.
/// </summary>
public BinaryIndexOpsOptions Ops { get; init; } = new();
}
/// <summary>
/// Configuration for B2R2 lifter pool.
/// </summary>
public sealed class B2R2PoolOptions
{
/// <summary>
/// Maximum pooled lifters per ISA.
/// </summary>
[Range(1, 64)]
public int MaxPoolSizePerIsa { get; init; } = 4;
/// <summary>
/// Whether to warm preload lifters at startup.
/// </summary>
public bool EnableWarmPreload { get; init; } = true;
/// <summary>
/// ISAs to warm preload at startup.
/// </summary>
public ImmutableArray<string> WarmPreloadIsas { get; init; } =
[
"intel-64",
"intel-32",
"armv8-64",
"armv7-32"
];
/// <summary>
/// Timeout for acquiring a lifter from the pool.
/// </summary>
public TimeSpan AcquireTimeout { get; init; } = TimeSpan.FromSeconds(5);
/// <summary>
/// Enable lifter pool metrics collection.
/// </summary>
public bool EnableMetrics { get; init; } = true;
}
/// <summary>
/// Configuration for semantic lifting (LowUIR).
/// </summary>
public sealed class SemanticLiftingOptions
{
/// <summary>
/// Whether semantic lifting is enabled.
/// </summary>
public bool Enabled { get; init; } = true;
/// <summary>
/// B2R2 LowUIR version string for cache keys.
/// </summary>
public string B2R2Version { get; init; } = "0.9.1";
/// <summary>
/// Normalization recipe version for deterministic fingerprints.
/// </summary>
public string NormalizationRecipeVersion { get; init; } = "v1";
/// <summary>
/// Maximum instructions per function to lift.
/// </summary>
[Range(100, 100000)]
public int MaxInstructionsPerFunction { get; init; } = 10000;
/// <summary>
/// Maximum functions per binary to process.
/// </summary>
[Range(10, 50000)]
public int MaxFunctionsPerBinary { get; init; } = 5000;
/// <summary>
/// Timeout for lifting a single function.
/// </summary>
public TimeSpan FunctionLiftTimeout { get; init; } = TimeSpan.FromSeconds(30);
/// <summary>
/// Enable IR statement deduplication.
/// </summary>
public bool EnableDeduplication { get; init; } = true;
}
/// <summary>
/// Configuration for Valkey function cache.
/// </summary>
public sealed class FunctionCacheOptions
{
/// <summary>
/// Whether caching is enabled.
/// </summary>
public bool Enabled { get; init; } = true;
/// <summary>
/// Valkey connection string or service name.
/// </summary>
public string? ConnectionString { get; init; }
/// <summary>
/// Key prefix for cache entries.
/// </summary>
public string KeyPrefix { get; init; } = "stellaops:binidx:funccache:";
/// <summary>
/// Default TTL for cached entries.
/// </summary>
public TimeSpan CacheTtl { get; init; } = TimeSpan.FromHours(4);
/// <summary>
/// Maximum TTL for any entry.
/// </summary>
public TimeSpan MaxTtl { get; init; } = TimeSpan.FromHours(24);
/// <summary>
/// Enable early expiry jitter to prevent thundering herd.
/// </summary>
public bool EnableEarlyExpiry { get; init; } = true;
/// <summary>
/// Early expiry jitter factor (0.0 to 0.5).
/// </summary>
[Range(0.0, 0.5)]
public double EarlyExpiryFactor { get; init; } = 0.1;
/// <summary>
/// Maximum cache entry size in bytes.
/// </summary>
[Range(1024, 10_000_000)]
public int MaxEntrySizeBytes { get; init; } = 1_000_000;
}
/// <summary>
/// Configuration for PostgreSQL persistence.
/// </summary>
public sealed class BinaryIndexPersistenceOptions
{
/// <summary>
/// Whether persistence is enabled.
/// </summary>
public bool Enabled { get; init; } = true;
/// <summary>
/// PostgreSQL schema name for BinaryIndex tables.
/// </summary>
public string Schema { get; init; } = "binary_index";
/// <summary>
/// Connection pool minimum size.
/// </summary>
[Range(1, 100)]
public int MinPoolSize { get; init; } = 2;
/// <summary>
/// Connection pool maximum size.
/// </summary>
[Range(1, 500)]
public int MaxPoolSize { get; init; } = 20;
/// <summary>
/// Command timeout for database operations.
/// </summary>
public TimeSpan CommandTimeout { get; init; } = TimeSpan.FromSeconds(30);
/// <summary>
/// Enable automatic retry on transient failures.
/// </summary>
public bool EnableRetryOnFailure { get; init; } = true;
/// <summary>
/// Maximum retry attempts.
/// </summary>
[Range(0, 10)]
public int MaxRetryCount { get; init; } = 3;
/// <summary>
/// Batch size for bulk operations.
/// </summary>
[Range(10, 10000)]
public int BatchSize { get; init; } = 500;
}
/// <summary>
/// Operational configuration.
/// </summary>
public sealed class BinaryIndexOpsOptions
{
/// <summary>
/// Enable health check endpoint.
/// </summary>
public bool EnableHealthEndpoint { get; init; } = true;
/// <summary>
/// Enable bench sampling endpoint.
/// </summary>
public bool EnableBenchEndpoint { get; init; } = true;
/// <summary>
/// Enable configuration visibility endpoint.
/// </summary>
public bool EnableConfigEndpoint { get; init; } = true;
/// <summary>
/// Enable cache stats endpoint.
/// </summary>
public bool EnableCacheStatsEndpoint { get; init; } = true;
/// <summary>
/// Rate limit for bench endpoint (calls per minute).
/// </summary>
[Range(1, 60)]
public int BenchRateLimitPerMinute { get; init; } = 5;
/// <summary>
/// Maximum bench sample size.
/// </summary>
[Range(1, 100)]
public int MaxBenchSampleSize { get; init; } = 10;
/// <summary>
/// Configuration keys to redact from visibility endpoint.
/// </summary>
public ImmutableArray<string> RedactedKeys { get; init; } =
[
"ConnectionString",
"Password",
"Secret",
"Token",
"ApiKey"
];
}